ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3205 -937
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1525 -573
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +223 -97
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3205 -937
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1525 -573
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +223 -97
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +143 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
ccxt/pro/bingx.py CHANGED
@@ -5,12 +5,13 @@
5
5
 
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
8
- from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
8
+ from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
+ from ccxt.base.errors import ArgumentsRequired
11
12
  from ccxt.base.errors import BadRequest
13
+ from ccxt.base.errors import NotSupported
12
14
  from ccxt.base.errors import NetworkError
13
- from ccxt.base.precise import Precise
14
15
 
15
16
 
16
17
  class bingx(ccxt.async_support.bingx):
@@ -20,19 +21,23 @@ class bingx(ccxt.async_support.bingx):
20
21
  'has': {
21
22
  'ws': True,
22
23
  'watchTrades': True,
24
+ 'watchTradesForSymbols': False,
23
25
  'watchOrderBook': True,
26
+ 'watchOrderBookForSymbols': True,
24
27
  'watchOHLCV': True,
28
+ 'watchOHLCVForSymbols': True,
25
29
  'watchOrders': True,
26
30
  'watchMyTrades': True,
27
31
  'watchTicker': True,
28
- 'watchTickers': False,
32
+ 'watchTickers': True,
29
33
  'watchBalance': True,
30
34
  },
31
35
  'urls': {
32
36
  'api': {
33
37
  'ws': {
34
38
  'spot': 'wss://open-api-ws.bingx.com/market',
35
- 'swap': 'wss://open-api-swap.bingx.com/swap-market',
39
+ 'linear': 'wss://open-api-swap.bingx.com/swap-market',
40
+ 'inverse': 'wss://open-api-cswap-ws.bingx.com/market',
36
41
  },
37
42
  },
38
43
  },
@@ -73,6 +78,14 @@ class bingx(ccxt.async_support.bingx):
73
78
  'fetchBalanceSnapshot': True, # needed to be True to keep track of used and free balance
74
79
  'awaitBalanceSnapshot': False, # whether to wait for the balance snapshot before providing updates
75
80
  },
81
+ 'watchOrderBook': {
82
+ 'depth': 100, # 5, 10, 20, 50, 100
83
+ 'interval': 500, # 100, 200, 500, 1000
84
+ },
85
+ 'watchOrderBookForSymbols': {
86
+ 'depth': 100, # 5, 10, 20, 50, 100
87
+ 'interval': 500, # 100, 200, 500, 1000
88
+ },
76
89
  },
77
90
  'streaming': {
78
91
  'keepAlive': 1800000, # 30 minutes
@@ -82,26 +95,36 @@ class bingx(ccxt.async_support.bingx):
82
95
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
83
96
  """
84
97
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
85
- :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes
98
+
99
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20to%2024-hour%20Price%20Change
100
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes
101
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%2024-Hour%20Price%20Change
102
+
86
103
  :param str symbol: unified symbol of the market to fetch the ticker for
87
104
  :param dict [params]: extra parameters specific to the exchange API endpoint
88
105
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
89
106
  """
90
107
  await self.load_markets()
91
108
  market = self.market(symbol)
92
- marketType, query = self.handle_market_type_and_params('watchTrades', market, params)
93
- url = self.safe_value(self.urls['api']['ws'], marketType)
94
- if url is None:
95
- raise BadRequest(self.id + ' watchTrades is not supported for ' + marketType + ' markets.')
96
- messageHash = market['id'] + '@ticker'
109
+ marketType = None
110
+ subType = None
111
+ url = None
112
+ marketType, params = self.handle_market_type_and_params('watchTicker', market, params)
113
+ subType, params = self.handle_sub_type_and_params('watchTicker', market, params, 'linear')
114
+ if marketType == 'swap':
115
+ url = self.safe_string(self.urls['api']['ws'], subType)
116
+ else:
117
+ url = self.safe_string(self.urls['api']['ws'], marketType)
118
+ subscriptionHash = market['id'] + '@ticker'
119
+ messageHash = self.get_message_hash('ticker', market['symbol'])
97
120
  uuid = self.uuid()
98
- request = {
121
+ request: dict = {
99
122
  'id': uuid,
100
- 'dataType': messageHash,
123
+ 'dataType': subscriptionHash,
101
124
  }
102
125
  if marketType == 'swap':
103
126
  request['reqType'] = 'sub'
104
- return await self.watch(url, messageHash, self.extend(request, query), messageHash)
127
+ return await self.watch(url, messageHash, self.extend(request, params), subscriptionHash)
105
128
 
106
129
  def handle_ticker(self, client: Client, message):
107
130
  #
@@ -167,8 +190,9 @@ class bingx(ccxt.async_support.bingx):
167
190
  symbol = market['symbol']
168
191
  ticker = self.parse_ws_ticker(data, market)
169
192
  self.tickers[symbol] = ticker
170
- messageHash = market['id'] + '@ticker'
171
- client.resolve(ticker, messageHash)
193
+ client.resolve(ticker, self.get_message_hash('ticker', symbol))
194
+ if self.safe_string(message, 'dataType') == 'all@ticker':
195
+ client.resolve(ticker, self.get_message_hash('ticker'))
172
196
 
173
197
  def parse_ws_ticker(self, message, market=None):
174
198
  #
@@ -193,7 +217,7 @@ class bingx(ccxt.async_support.bingx):
193
217
  # "b": "2.5747"
194
218
  # }
195
219
  #
196
- timestamp = self.safe_integer(message, 'ts')
220
+ timestamp = self.safe_integer(message, 'C')
197
221
  marketId = self.safe_string(message, 's')
198
222
  market = self.safe_market(marketId, market)
199
223
  close = self.safe_string(message, 'c')
@@ -220,40 +244,235 @@ class bingx(ccxt.async_support.bingx):
220
244
  'info': message,
221
245
  }, market)
222
246
 
247
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
248
+ """
249
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
250
+
251
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes%20of%20all%20trading%20pairs
252
+
253
+ :param str[] symbols: unified symbol of the market to watch the tickers for
254
+ :param dict [params]: extra parameters specific to the exchange API endpoint
255
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
256
+ """
257
+ await self.load_markets()
258
+ symbols = self.market_symbols(symbols, None, True, True, False)
259
+ firstMarket = None
260
+ marketType = None
261
+ subType = None
262
+ symbolsDefined = (symbols is not None)
263
+ if symbolsDefined:
264
+ firstMarket = self.market(symbols[0])
265
+ marketType, params = self.handle_market_type_and_params('watchTickers', firstMarket, params)
266
+ subType, params = self.handle_sub_type_and_params('watchTickers', firstMarket, params, 'linear')
267
+ if marketType == 'spot':
268
+ raise NotSupported(self.id + ' watchTickers is not supported for spot markets yet')
269
+ if subType == 'inverse':
270
+ raise NotSupported(self.id + ' watchTickers is not supported for inverse markets yet')
271
+ messageHashes = []
272
+ subscriptionHashes = ['all@ticker']
273
+ if symbolsDefined:
274
+ for i in range(0, len(symbols)):
275
+ symbol = symbols[i]
276
+ market = self.market(symbol)
277
+ messageHashes.append(self.get_message_hash('ticker', market['symbol']))
278
+ else:
279
+ messageHashes.append(self.get_message_hash('ticker'))
280
+ url = self.safe_string(self.urls['api']['ws'], subType)
281
+ uuid = self.uuid()
282
+ request: dict = {
283
+ 'id': uuid,
284
+ 'dataType': 'all@ticker',
285
+ }
286
+ if marketType == 'swap':
287
+ request['reqType'] = 'sub'
288
+ result = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), subscriptionHashes)
289
+ if self.newUpdates:
290
+ newDict: dict = {}
291
+ newDict[result['symbol']] = result
292
+ return newDict
293
+ return self.tickers
294
+
295
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
296
+ """
297
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
298
+
299
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data%20of%20all%20trading%20pairs
300
+
301
+ :param str[] symbols: unified array of symbols
302
+ :param int [limit]: the maximum amount of order book entries to return
303
+ :param dict [params]: extra parameters specific to the exchange API endpoint
304
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
305
+ """
306
+ symbols = self.market_symbols(symbols, None, True, True, False)
307
+ firstMarket = None
308
+ marketType = None
309
+ subType = None
310
+ symbolsDefined = (symbols is not None)
311
+ if symbolsDefined:
312
+ firstMarket = self.market(symbols[0])
313
+ marketType, params = self.handle_market_type_and_params('watchOrderBookForSymbols', firstMarket, params)
314
+ subType, params = self.handle_sub_type_and_params('watchOrderBookForSymbols', firstMarket, params, 'linear')
315
+ if marketType == 'spot':
316
+ raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for spot markets yet')
317
+ if subType == 'inverse':
318
+ raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for inverse markets yet')
319
+ limit = self.get_order_book_limit_by_market_type(marketType, limit)
320
+ interval = None
321
+ interval, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'interval', 500)
322
+ self.check_required_argument('watchOrderBookForSymbols', interval, 'interval', [100, 200, 500, 1000])
323
+ channelName = 'depth' + str(limit) + '@' + str(interval) + 'ms'
324
+ subscriptionHash = 'all@' + channelName
325
+ messageHashes = []
326
+ if symbolsDefined:
327
+ for i in range(0, len(symbols)):
328
+ symbol = symbols[i]
329
+ market = self.market(symbol)
330
+ messageHashes.append(self.get_message_hash('orderbook', market['symbol']))
331
+ else:
332
+ messageHashes.append(self.get_message_hash('orderbook'))
333
+ url = self.safe_string(self.urls['api']['ws'], subType)
334
+ uuid = self.uuid()
335
+ request: dict = {
336
+ 'id': uuid,
337
+ 'dataType': subscriptionHash,
338
+ }
339
+ if marketType == 'swap':
340
+ request['reqType'] = 'sub'
341
+ subscriptionArgs: dict = {
342
+ 'symbols': symbols,
343
+ 'limit': limit,
344
+ 'interval': interval,
345
+ 'params': params,
346
+ }
347
+ orderbook = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), [subscriptionHash], subscriptionArgs)
348
+ return orderbook.limit()
349
+
350
+ async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
351
+ """
352
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
353
+
354
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data%20of%20all%20trading%20pairs
355
+
356
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
357
+ :param int [since]: timestamp in ms of the earliest candle to fetch
358
+ :param int [limit]: the maximum amount of candles to fetch
359
+ :param dict [params]: extra parameters specific to the exchange API endpoint
360
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
361
+ """
362
+ symbolsLength = len(symbolsAndTimeframes)
363
+ if symbolsLength != 0 and not isinstance(symbolsAndTimeframes[0], list):
364
+ raise ArgumentsRequired(self.id + " watchOHLCVForSymbols() requires a an array like [['BTC/USDT:USDT', '1m'], ['LTC/USDT:USDT', '5m']]")
365
+ await self.load_markets()
366
+ messageHashes = []
367
+ marketType = None
368
+ subType = None
369
+ chosenTimeframe = None
370
+ firstMarket = None
371
+ if symbolsLength != 0:
372
+ symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
373
+ symbols = self.market_symbols(symbols, None, True, True, False)
374
+ firstMarket = self.market(symbols[0])
375
+ marketType, params = self.handle_market_type_and_params('watchOHLCVForSymbols', firstMarket, params)
376
+ subType, params = self.handle_sub_type_and_params('watchOHLCVForSymbols', firstMarket, params, 'linear')
377
+ if marketType == 'spot':
378
+ raise NotSupported(self.id + ' watchOHLCVForSymbols is not supported for spot markets yet')
379
+ if subType == 'inverse':
380
+ raise NotSupported(self.id + ' watchOHLCVForSymbols is not supported for inverse markets yet')
381
+ marketOptions = self.safe_dict(self.options, marketType)
382
+ timeframes = self.safe_dict(marketOptions, 'timeframes', {})
383
+ for i in range(0, len(symbolsAndTimeframes)):
384
+ symbolAndTimeframe = symbolsAndTimeframes[i]
385
+ sym = symbolAndTimeframe[0]
386
+ tf = symbolAndTimeframe[1]
387
+ market = self.market(sym)
388
+ rawTimeframe = self.safe_string(timeframes, tf, tf)
389
+ if chosenTimeframe is None:
390
+ chosenTimeframe = rawTimeframe
391
+ elif chosenTimeframe != rawTimeframe:
392
+ raise BadRequest(self.id + ' watchOHLCVForSymbols requires all timeframes to be the same')
393
+ messageHashes.append(self.get_message_hash('ohlcv', market['symbol'], chosenTimeframe))
394
+ subscriptionHash = 'all@kline_' + chosenTimeframe
395
+ url = self.safe_string(self.urls['api']['ws'], subType)
396
+ uuid = self.uuid()
397
+ request: dict = {
398
+ 'id': uuid,
399
+ 'dataType': subscriptionHash,
400
+ }
401
+ if marketType == 'swap':
402
+ request['reqType'] = 'sub'
403
+ subscriptionArgs: dict = {
404
+ 'limit': limit,
405
+ 'params': params,
406
+ }
407
+ symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, request, [subscriptionHash], subscriptionArgs)
408
+ if self.newUpdates:
409
+ limit = candles.getLimit(symbol, limit)
410
+ filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
411
+ return self.create_ohlcv_object(symbol, timeframe, filtered)
412
+
413
+ def get_order_book_limit_by_market_type(self, marketType: str, limit: Int = None):
414
+ if limit is None:
415
+ limit = 100
416
+ else:
417
+ if marketType == 'swap' or marketType == 'future':
418
+ limit = self.find_nearest_ceiling([5, 10, 20, 50, 100], limit)
419
+ elif marketType == 'spot':
420
+ limit = self.find_nearest_ceiling([20, 100], limit)
421
+ return limit
422
+
423
+ def get_message_hash(self, unifiedChannel: str, symbol: Str = None, extra: Str = None):
424
+ hash = unifiedChannel
425
+ if symbol is not None:
426
+ hash += '::' + symbol
427
+ else:
428
+ hash += 's' # tickers, orderbooks, ohlcvs ...
429
+ if extra is not None:
430
+ hash += '::' + extra
431
+ return hash
432
+
223
433
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
224
434
  """
225
435
  watches information on multiple trades made in a market
226
- :see: https://bingx-api.github.io/docs/#/spot/socket/market.html#Subscribe%20to%20tick-by-tick
227
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
436
+
437
+ https://bingx-api.github.io/docs/#/spot/socket/market.html#Subscribe%20to%20tick-by-tick
438
+ https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
439
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscription%20transaction%20by%20transaction
440
+
228
441
  :param str symbol: unified market symbol of the market orders were made in
229
442
  :param int [since]: the earliest time in ms to fetch orders for
230
443
  :param int [limit]: the maximum number of order structures to retrieve
231
444
  :param dict [params]: extra parameters specific to the exchange API endpoint
232
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
445
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
233
446
  """
234
447
  await self.load_markets()
235
448
  market = self.market(symbol)
236
- marketType, query = self.handle_market_type_and_params('watchTrades', market, params)
237
- url = self.safe_value(self.urls['api']['ws'], marketType)
238
- if url is None:
239
- raise BadRequest(self.id + ' watchTrades is not supported for ' + marketType + ' markets.')
240
- messageHash = market['id'] + '@trade'
449
+ symbol = market['symbol']
450
+ marketType = None
451
+ subType = None
452
+ url = None
453
+ marketType, params = self.handle_market_type_and_params('watchTrades', market, params)
454
+ subType, params = self.handle_sub_type_and_params('watchTrades', market, params, 'linear')
455
+ if marketType == 'swap':
456
+ url = self.safe_string(self.urls['api']['ws'], subType)
457
+ else:
458
+ url = self.safe_string(self.urls['api']['ws'], marketType)
459
+ rawHash = market['id'] + '@trade'
460
+ messageHash = 'trade::' + symbol
241
461
  uuid = self.uuid()
242
- request = {
462
+ request: dict = {
243
463
  'id': uuid,
244
- 'dataType': messageHash,
464
+ 'dataType': rawHash,
245
465
  }
246
466
  if marketType == 'swap':
247
467
  request['reqType'] = 'sub'
248
- trades = await self.watch(url, messageHash, self.extend(request, query), messageHash)
468
+ trades = await self.watch(url, messageHash, self.extend(request, params), messageHash)
249
469
  if self.newUpdates:
250
470
  limit = trades.getLimit(symbol, limit)
251
471
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
252
472
 
253
473
  def handle_trades(self, client: Client, message):
254
474
  #
255
- # spot
256
- # first snapshot
475
+ # spot: first snapshot
257
476
  #
258
477
  # {
259
478
  # "id": "d83b78ce-98be-4dc2-b847-12fe471b5bc5",
@@ -262,7 +481,7 @@ class bingx(ccxt.async_support.bingx):
262
481
  # "timestamp": 1690214699854
263
482
  # }
264
483
  #
265
- # subsequent updates
484
+ # spot: subsequent updates
266
485
  #
267
486
  # {
268
487
  # "code": 0,
@@ -280,9 +499,7 @@ class bingx(ccxt.async_support.bingx):
280
499
  # "success": True
281
500
  # }
282
501
  #
283
- #
284
- # swap
285
- # first snapshot
502
+ # linear swap: first snapshot
286
503
  #
287
504
  # {
288
505
  # "id": "2aed93b1-6e1e-4038-aeba-f5eeaec2ca48",
@@ -292,8 +509,7 @@ class bingx(ccxt.async_support.bingx):
292
509
  # "data": null
293
510
  # }
294
511
  #
295
- # subsequent updates
296
- #
512
+ # linear swap: subsequent updates
297
513
  #
298
514
  # {
299
515
  # "code": 0,
@@ -310,13 +526,40 @@ class bingx(ccxt.async_support.bingx):
310
526
  # ]
311
527
  # }
312
528
  #
529
+ # inverse swap: first snapshot
530
+ #
531
+ # {
532
+ # "code": 0,
533
+ # "id": "a2e482ca-f71b-42f8-a83a-8ff85a713e64",
534
+ # "msg": "SUCCESS",
535
+ # "timestamp": 1722920589426
536
+ # }
537
+ #
538
+ # inverse swap: subsequent updates
539
+ #
540
+ # {
541
+ # "code": 0,
542
+ # "dataType": "BTC-USD@trade",
543
+ # "data": {
544
+ # "e": "trade",
545
+ # "E": 1722920589665,
546
+ # "s": "BTC-USD",
547
+ # "t": "39125001",
548
+ # "p": "55360.0",
549
+ # "q": "1",
550
+ # "T": 1722920589582,
551
+ # "m": False
552
+ # }
553
+ # }
554
+ #
313
555
  data = self.safe_value(message, 'data', [])
314
- messageHash = self.safe_string(message, 'dataType')
315
- marketId = messageHash.split('@')[0]
556
+ rawHash = self.safe_string(message, 'dataType')
557
+ marketId = rawHash.split('@')[0]
316
558
  isSwap = client.url.find('swap') >= 0
317
559
  marketType = 'swap' if isSwap else 'spot'
318
560
  market = self.safe_market(marketId, None, None, marketType)
319
561
  symbol = market['symbol']
562
+ messageHash = 'trade::' + symbol
320
563
  trades = None
321
564
  if isinstance(data, list):
322
565
  trades = self.parse_trades(data, market)
@@ -334,8 +577,11 @@ class bingx(ccxt.async_support.bingx):
334
577
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
335
578
  """
336
579
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
337
- :see: https://bingx-api.github.io/docs/#/spot/socket/market.html#Subscribe%20Market%20Depth%20Data
338
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data
580
+
581
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20Market%20Depth%20Data
582
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data
583
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Limited%20Depth
584
+
339
585
  :param str symbol: unified symbol of the market to fetch the order book for
340
586
  :param int [limit]: the maximum amount of order book entries to return
341
587
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -343,40 +589,56 @@ class bingx(ccxt.async_support.bingx):
343
589
  """
344
590
  await self.load_markets()
345
591
  market = self.market(symbol)
346
- marketType, query = self.handle_market_type_and_params('watchOrderBook', market, params)
347
- if limit is None:
348
- limit = 100
592
+ marketType = None
593
+ subType = None
594
+ url = None
595
+ marketType, params = self.handle_market_type_and_params('watchOrderBook', market, params)
596
+ subType, params = self.handle_sub_type_and_params('watchOrderBook', market, params, 'linear')
597
+ if marketType == 'swap':
598
+ url = self.safe_string(self.urls['api']['ws'], subType)
349
599
  else:
350
- if marketType == 'swap':
351
- if (limit != 5) and (limit != 10) and (limit != 20) and (limit != 50) and (limit != 100):
352
- raise BadRequest(self.id + ' watchOrderBook()(swap) only supports limit 5, 10, 20, 50, and 100')
353
- elif marketType == 'spot':
354
- if (limit != 20) and (limit != 100):
355
- raise BadRequest(self.id + ' watchOrderBook()(spot) only supports limit 20, and 100')
356
- url = self.safe_value(self.urls['api']['ws'], marketType)
357
- if url is None:
358
- raise BadRequest(self.id + ' watchOrderBook is not supported for ' + marketType + ' markets.')
359
- messageHash = market['id'] + '@depth' + str(limit)
600
+ url = self.safe_string(self.urls['api']['ws'], marketType)
601
+ limit = self.get_order_book_limit_by_market_type(marketType, limit)
602
+ channelName = 'depth' + str(limit)
603
+ interval = None
604
+ if marketType != 'spot':
605
+ if not market['inverse']:
606
+ interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', 500)
607
+ self.check_required_argument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000])
608
+ channelName = channelName + '@' + str(interval) + 'ms'
609
+ subscriptionHash = market['id'] + '@' + channelName
610
+ messageHash = self.get_message_hash('orderbook', market['symbol'])
360
611
  uuid = self.uuid()
361
- request = {
612
+ request: dict = {
362
613
  'id': uuid,
363
- 'dataType': messageHash,
614
+ 'dataType': subscriptionHash,
364
615
  }
365
616
  if marketType == 'swap':
366
617
  request['reqType'] = 'sub'
367
- orderbook = await self.watch(url, messageHash, self.deep_extend(request, query), messageHash)
618
+ subscriptionArgs: dict = {}
619
+ if market['inverse']:
620
+ subscriptionArgs = {
621
+ 'count': limit,
622
+ 'params': params,
623
+ }
624
+ else:
625
+ subscriptionArgs = {
626
+ 'level': limit,
627
+ 'interval': interval,
628
+ 'params': params,
629
+ }
630
+ orderbook = await self.watch(url, messageHash, self.deep_extend(request, params), subscriptionHash, subscriptionArgs)
368
631
  return orderbook.limit()
369
632
 
370
633
  def handle_delta(self, bookside, delta):
371
- price = self.safe_float(delta, 0)
372
- amount = self.safe_float(delta, 1)
634
+ price = self.safe_float_2(delta, 0, 'p')
635
+ amount = self.safe_float_2(delta, 1, 'a')
373
636
  bookside.store(price, amount)
374
637
 
375
638
  def handle_order_book(self, client: Client, message):
376
639
  #
377
640
  # spot
378
641
  #
379
- #
380
642
  # {
381
643
  # "code": 0,
382
644
  # "dataType": "BTC-USDT@depth20",
@@ -394,12 +656,11 @@ class bingx(ccxt.async_support.bingx):
394
656
  # "success": True
395
657
  # }
396
658
  #
397
- # swap
398
- #
659
+ # linear swap
399
660
  #
400
661
  # {
401
662
  # "code": 0,
402
- # "dataType": "BTC-USDT@depth20",
663
+ # "dataType": "BTC-USDT@depth20@100ms", #or "all@depth20@100ms"
403
664
  # "data": {
404
665
  # "bids": [
405
666
  # ['28852.9', "34.2621"],
@@ -408,24 +669,63 @@ class bingx(ccxt.async_support.bingx):
408
669
  # "asks": [
409
670
  # ['28864.9', "23.4079"],
410
671
  # ...
411
- # ]
672
+ # ],
673
+ # "symbol": "BTC-USDT", # self key exists only in "all" subscription
412
674
  # }
413
675
  # }
414
676
  #
415
- data = self.safe_value(message, 'data', [])
416
- messageHash = self.safe_string(message, 'dataType')
417
- marketId = messageHash.split('@')[0]
677
+ # inverse swap
678
+ #
679
+ # {
680
+ # "code": 0,
681
+ # "dataType": "BTC-USD@depth100",
682
+ # "data": {
683
+ # {
684
+ # "symbol": "BTC-USD",
685
+ # "bids": [
686
+ # {"p": "58074.2", "a": "1.422318", "v": "826.0"},
687
+ # ...
688
+ # ],
689
+ # "asks": [
690
+ # {"p": "62878.0", "a": "0.001590", "v": "1.0"},
691
+ # ...
692
+ # ],
693
+ # "aggPrecision": "0.1",
694
+ # "timestamp": 1723705093529
695
+ # }
696
+ # }
697
+ # }
698
+ #
699
+ data = self.safe_dict(message, 'data', {})
700
+ dataType = self.safe_string(message, 'dataType')
701
+ parts = dataType.split('@')
702
+ firstPart = parts[0]
703
+ isAllEndpoint = (firstPart == 'all')
704
+ marketId = self.safe_string(data, 'symbol', firstPart)
418
705
  isSwap = client.url.find('swap') >= 0
419
706
  marketType = 'swap' if isSwap else 'spot'
420
707
  market = self.safe_market(marketId, None, None, marketType)
421
708
  symbol = market['symbol']
422
- orderbook = self.safe_value(self.orderbooks, symbol)
423
- if orderbook is None:
424
- orderbook = self.order_book()
425
- snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
709
+ if self.safe_value(self.orderbooks, symbol) is None:
710
+ # limit = [5, 10, 20, 50, 100]
711
+ subscriptionHash = dataType
712
+ subscription = client.subscriptions[subscriptionHash]
713
+ limit = self.safe_integer(subscription, 'limit')
714
+ self.orderbooks[symbol] = self.order_book({}, limit)
715
+ orderbook = self.orderbooks[symbol]
716
+ snapshot = None
717
+ if market['inverse']:
718
+ snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 'p', 'a')
719
+ else:
720
+ snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
426
721
  orderbook.reset(snapshot)
427
722
  self.orderbooks[symbol] = orderbook
723
+ messageHash = self.get_message_hash('orderbook', symbol)
428
724
  client.resolve(orderbook, messageHash)
725
+ # resolve for "all"
726
+ if isAllEndpoint:
727
+ messageHashForAll = self.get_message_hash('orderbook')
728
+ client.resolve(orderbook, messageHashForAll)
429
729
 
430
730
  def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
431
731
  #
@@ -440,8 +740,10 @@ class bingx(ccxt.async_support.bingx):
440
740
  # }
441
741
  #
442
742
  # for spot, opening-time(t) is used instead of closing-time(T), to be compatible with fetchOHLCV
443
- # for swap,(T) is the opening time
743
+ # for linear swap,(T) is the opening time
444
744
  timestamp = 't' if (market['spot']) else 'T'
745
+ if market['swap']:
746
+ timestamp = 't' if (market['inverse']) else 'T'
445
747
  return [
446
748
  self.safe_integer(ohlcv, timestamp),
447
749
  self.safe_number(ohlcv, 'o'),
@@ -453,7 +755,7 @@ class bingx(ccxt.async_support.bingx):
453
755
 
454
756
  def handle_ohlcv(self, client: Client, message):
455
757
  #
456
- # spot
758
+ # spot:
457
759
  #
458
760
  # {
459
761
  # "code": 0,
@@ -479,7 +781,8 @@ class bingx(ccxt.async_support.bingx):
479
781
  # "success": True
480
782
  # }
481
783
  #
482
- # swap
784
+ # linear swap:
785
+ #
483
786
  # {
484
787
  # "code": 0,
485
788
  # "dataType": "BTC-USDT@kline_1m",
@@ -496,36 +799,74 @@ class bingx(ccxt.async_support.bingx):
496
799
  # ]
497
800
  # }
498
801
  #
499
- data = self.safe_value(message, 'data', [])
500
- candles = None
501
- if isinstance(data, list):
502
- candles = data
503
- else:
504
- candles = [self.safe_value(data, 'K', [])]
505
- messageHash = self.safe_string(message, 'dataType')
506
- timeframeId = messageHash.split('_')[1]
507
- marketId = messageHash.split('@')[0]
802
+ # inverse swap:
803
+ #
804
+ # {
805
+ # "code": 0,
806
+ # "timestamp": 1723769354547,
807
+ # "dataType": "BTC-USD@kline_1m",
808
+ # "data": {
809
+ # "t": 1723769340000,
810
+ # "o": 57485.1,
811
+ # "c": 57468,
812
+ # "l": 57464.9,
813
+ # "h": 57485.1,
814
+ # "a": 0.189663,
815
+ # "v": 109,
816
+ # "u": 92,
817
+ # "s": "BTC-USD"
818
+ # }
819
+ # }
820
+ #
508
821
  isSwap = client.url.find('swap') >= 0
822
+ dataType = self.safe_string(message, 'dataType')
823
+ parts = dataType.split('@')
824
+ firstPart = parts[0]
825
+ isAllEndpoint = (firstPart == 'all')
826
+ marketId = self.safe_string(message, 's', firstPart)
509
827
  marketType = 'swap' if isSwap else 'spot'
510
828
  market = self.safe_market(marketId, None, None, marketType)
829
+ candles = None
830
+ if isSwap:
831
+ if market['inverse']:
832
+ candles = [self.safe_dict(message, 'data', {})]
833
+ else:
834
+ candles = self.safe_list(message, 'data', [])
835
+ else:
836
+ data = self.safe_dict(message, 'data', {})
837
+ candles = [self.safe_dict(data, 'K', {})]
511
838
  symbol = market['symbol']
512
839
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
513
- stored = self.safe_value(self.ohlcvs[symbol], timeframeId)
514
- if stored is None:
515
- limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
516
- stored = ArrayCacheByTimestamp(limit)
517
- self.ohlcvs[symbol][timeframeId] = stored
840
+ rawTimeframe = dataType.split('_')[1]
841
+ marketOptions = self.safe_dict(self.options, marketType)
842
+ timeframes = self.safe_dict(marketOptions, 'timeframes', {})
843
+ unifiedTimeframe = self.find_timeframe(rawTimeframe, timeframes)
844
+ if self.safe_value(self.ohlcvs[symbol], rawTimeframe) is None:
845
+ subscriptionHash = dataType
846
+ subscription = client.subscriptions[subscriptionHash]
847
+ limit = self.safe_integer(subscription, 'limit')
848
+ self.ohlcvs[symbol][unifiedTimeframe] = ArrayCacheByTimestamp(limit)
849
+ stored = self.ohlcvs[symbol][unifiedTimeframe]
518
850
  for i in range(0, len(candles)):
519
851
  candle = candles[i]
520
852
  parsed = self.parse_ws_ohlcv(candle, market)
521
853
  stored.append(parsed)
522
- client.resolve(stored, messageHash)
854
+ resolveData = [symbol, unifiedTimeframe, stored]
855
+ messageHash = self.get_message_hash('ohlcv', symbol, unifiedTimeframe)
856
+ client.resolve(resolveData, messageHash)
857
+ # resolve for "all"
858
+ if isAllEndpoint:
859
+ messageHashForAll = self.get_message_hash('ohlcv', None, unifiedTimeframe)
860
+ client.resolve(resolveData, messageHashForAll)
523
861
 
524
862
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
525
863
  """
526
864
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
527
- :see: https://bingx-api.github.io/docs/#/spot/socket/market.html#K%E7%BA%BF%20Streams
528
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20K-Line%20Data
865
+
866
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#K-line%20Streams
867
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data
868
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Latest%20Trading%20Pair%20K-Line
869
+
529
870
  :param str symbol: unified symbol of the market to fetch OHLCV data for
530
871
  :param str timeframe: the length of time each candle represents
531
872
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -535,33 +876,49 @@ class bingx(ccxt.async_support.bingx):
535
876
  """
536
877
  await self.load_markets()
537
878
  market = self.market(symbol)
538
- marketType, query = self.handle_market_type_and_params('watchOHLCV', market, params)
539
- url = self.safe_value(self.urls['api']['ws'], marketType)
879
+ marketType = None
880
+ subType = None
881
+ url = None
882
+ marketType, params = self.handle_market_type_and_params('watchOHLCV', market, params)
883
+ subType, params = self.handle_sub_type_and_params('watchOHLCV', market, params, 'linear')
884
+ if marketType == 'swap':
885
+ url = self.safe_string(self.urls['api']['ws'], subType)
886
+ else:
887
+ url = self.safe_string(self.urls['api']['ws'], marketType)
540
888
  if url is None:
541
889
  raise BadRequest(self.id + ' watchOHLCV is not supported for ' + marketType + ' markets.')
542
890
  options = self.safe_value(self.options, marketType, {})
543
891
  timeframes = self.safe_value(options, 'timeframes', {})
544
- interval = self.safe_string(timeframes, timeframe, timeframe)
545
- messageHash = market['id'] + '@kline_' + interval
892
+ rawTimeframe = self.safe_string(timeframes, timeframe, timeframe)
893
+ messageHash = self.get_message_hash('ohlcv', market['symbol'], timeframe)
894
+ subscriptionHash = market['id'] + '@kline_' + rawTimeframe
546
895
  uuid = self.uuid()
547
- request = {
896
+ request: dict = {
548
897
  'id': uuid,
549
- 'dataType': messageHash,
898
+ 'dataType': subscriptionHash,
550
899
  }
551
900
  if marketType == 'swap':
552
901
  request['reqType'] = 'sub'
553
- ohlcv = await self.watch(url, messageHash, self.extend(request, query), messageHash)
902
+ subscriptionArgs: dict = {
903
+ 'interval': rawTimeframe,
904
+ 'params': params,
905
+ }
906
+ result = await self.watch(url, messageHash, self.extend(request, params), subscriptionHash, subscriptionArgs)
907
+ ohlcv = result[2]
554
908
  if self.newUpdates:
555
909
  limit = ohlcv.getLimit(symbol, limit)
556
910
  return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
557
911
 
558
912
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
559
913
  """
560
- :see: https://bingx-api.github.io/docs/#/spot/socket/account.html#Subscription%20order%20update%20data
561
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
562
914
  watches information on multiple orders made by the user
563
- :param str symbol: unified market symbol of the market orders were made in
564
- :param int [since]: the earliest time in ms to fetch orders for
915
+
916
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
917
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
918
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
919
+
920
+ :param str [symbol]: unified market symbol of the market orders are made in
921
+ :param int [since]: the earliest time in ms to watch orders for
565
922
  :param int [limit]: the maximum number of order structures to retrieve
566
923
  :param dict [params]: extra parameters specific to the exchange API endpoint
567
924
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -569,11 +926,13 @@ class bingx(ccxt.async_support.bingx):
569
926
  await self.load_markets()
570
927
  await self.authenticate()
571
928
  type = None
929
+ subType = None
572
930
  market = None
573
931
  if symbol is not None:
574
932
  market = self.market(symbol)
575
933
  symbol = market['symbol']
576
934
  type, params = self.handle_market_type_and_params('watchOrders', market, params)
935
+ subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
577
936
  isSpot = (type == 'spot')
578
937
  spotHash = 'spot:private'
579
938
  swapHash = 'swap:private'
@@ -583,14 +942,21 @@ class bingx(ccxt.async_support.bingx):
583
942
  messageHash = spotMessageHash if isSpot else swapMessageHash
584
943
  if market is not None:
585
944
  messageHash += ':' + symbol
586
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
587
- request = None
588
945
  uuid = self.uuid()
589
- if isSpot:
946
+ baseUrl = None
947
+ request = None
948
+ if type == 'swap':
949
+ if subType == 'inverse':
950
+ raise NotSupported(self.id + ' watchOrders is not supported for inverse swap markets yet')
951
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
952
+ else:
953
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
590
954
  request = {
591
955
  'id': uuid,
956
+ 'reqType': 'sub',
592
957
  'dataType': 'spot.executionReport',
593
958
  }
959
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
594
960
  orders = await self.watch(url, messageHash, request, subscriptionHash)
595
961
  if self.newUpdates:
596
962
  limit = orders.getLimit(symbol, limit)
@@ -598,40 +964,52 @@ class bingx(ccxt.async_support.bingx):
598
964
 
599
965
  async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
600
966
  """
601
- :see: https://bingx-api.github.io/docs/#/spot/socket/account.html#Subscription%20order%20update%20data
602
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
603
967
  watches information on multiple trades made by the user
604
- :param str symbol: unified market symbol of the market trades were made in
605
- :param int [since]: the earliest time in ms to trades orders for
606
- :param int [limit]: the maximum number of trades structures to retrieve
968
+
969
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
970
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
971
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
972
+
973
+ :param str [symbol]: unified market symbol of the market the trades are made in
974
+ :param int [since]: the earliest time in ms to watch trades for
975
+ :param int [limit]: the maximum number of trade structures to retrieve
607
976
  :param dict [params]: extra parameters specific to the exchange API endpoint
608
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
977
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
609
978
  """
610
979
  await self.load_markets()
611
980
  await self.authenticate()
612
981
  type = None
982
+ subType = None
613
983
  market = None
614
984
  if symbol is not None:
615
985
  market = self.market(symbol)
616
986
  symbol = market['symbol']
617
- type, params = self.handle_market_type_and_params('watchOrders', market, params)
987
+ type, params = self.handle_market_type_and_params('watchMyTrades', market, params)
988
+ subType, params = self.handle_sub_type_and_params('watchMyTrades', market, params, 'linear')
618
989
  isSpot = (type == 'spot')
619
- spotSubHash = 'spot:private'
620
- swapSubHash = 'swap:private'
621
- subscriptionHash = spotSubHash if isSpot else swapSubHash
990
+ spotHash = 'spot:private'
991
+ swapHash = 'swap:private'
992
+ subscriptionHash = spotHash if isSpot else swapHash
622
993
  spotMessageHash = 'spot:mytrades'
623
994
  swapMessageHash = 'swap:mytrades'
624
995
  messageHash = spotMessageHash if isSpot else swapMessageHash
625
996
  if market is not None:
626
997
  messageHash += ':' + symbol
627
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
628
- request = None
629
998
  uuid = self.uuid()
630
- if isSpot:
999
+ baseUrl = None
1000
+ request = None
1001
+ if type == 'swap':
1002
+ if subType == 'inverse':
1003
+ raise NotSupported(self.id + ' watchMyTrades is not supported for inverse swap markets yet')
1004
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
1005
+ else:
1006
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
631
1007
  request = {
632
1008
  'id': uuid,
1009
+ 'reqType': 'sub',
633
1010
  'dataType': 'spot.executionReport',
634
1011
  }
1012
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
635
1013
  trades = await self.watch(url, messageHash, request, subscriptionHash)
636
1014
  if self.newUpdates:
637
1015
  limit = trades.getLimit(symbol, limit)
@@ -639,16 +1017,21 @@ class bingx(ccxt.async_support.bingx):
639
1017
 
640
1018
  async def watch_balance(self, params={}) -> Balances:
641
1019
  """
642
- :see: https://bingx-api.github.io/docs/#/spot/socket/account.html#Subscription%20order%20update%20data
643
- :see: https://bingx-api.github.io/docs/#/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
644
1020
  query for balance and get the amount of funds available for trading or funds locked in orders
1021
+
1022
+ https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20account%20balance%20push
1023
+ https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
1024
+ https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Account%20balance%20and%20position%20update%20push
1025
+
645
1026
  :param dict [params]: extra parameters specific to the exchange API endpoint
646
1027
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
647
1028
  """
648
1029
  await self.load_markets()
649
1030
  await self.authenticate()
650
1031
  type = None
1032
+ subType = None
651
1033
  type, params = self.handle_market_type_and_params('watchBalance', None, params)
1034
+ subType, params = self.handle_sub_type_and_params('watchBalance', None, params, 'linear')
652
1035
  isSpot = (type == 'spot')
653
1036
  spotSubHash = 'spot:balance'
654
1037
  swapSubHash = 'swap:private'
@@ -656,16 +1039,22 @@ class bingx(ccxt.async_support.bingx):
656
1039
  swapMessageHash = 'swap:balance'
657
1040
  messageHash = spotMessageHash if isSpot else swapMessageHash
658
1041
  subscriptionHash = spotSubHash if isSpot else swapSubHash
659
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
660
1042
  request = None
1043
+ baseUrl = None
661
1044
  uuid = self.uuid()
662
- if type == 'spot':
1045
+ if type == 'swap':
1046
+ if subType == 'inverse':
1047
+ raise NotSupported(self.id + ' watchBalance is not supported for inverse swap markets yet')
1048
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
1049
+ else:
1050
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
663
1051
  request = {
664
1052
  'id': uuid,
665
1053
  'dataType': 'ACCOUNT_UPDATE',
666
1054
  }
1055
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
667
1056
  client = self.client(url)
668
- self.set_balance_cache(client, type, subscriptionHash, params)
1057
+ self.set_balance_cache(client, type, subType, subscriptionHash, params)
669
1058
  fetchBalanceSnapshot = None
670
1059
  awaitBalanceSnapshot = None
671
1060
  fetchBalanceSnapshot, params = self.handle_option_and_params(params, 'watchBalance', 'fetchBalanceSnapshot', True)
@@ -674,7 +1063,7 @@ class bingx(ccxt.async_support.bingx):
674
1063
  await client.future(type + ':fetchBalanceSnapshot')
675
1064
  return await self.watch(url, messageHash, request, subscriptionHash)
676
1065
 
677
- def set_balance_cache(self, client: Client, type, subscriptionHash, params):
1066
+ def set_balance_cache(self, client: Client, type, subType, subscriptionHash, params):
678
1067
  if subscriptionHash in client.subscriptions:
679
1068
  return
680
1069
  fetchBalanceSnapshot = self.handle_option_and_params(params, 'watchBalance', 'fetchBalanceSnapshot', True)
@@ -682,12 +1071,12 @@ class bingx(ccxt.async_support.bingx):
682
1071
  messageHash = type + ':fetchBalanceSnapshot'
683
1072
  if not (messageHash in client.futures):
684
1073
  client.future(messageHash)
685
- self.spawn(self.load_balance_snapshot, client, messageHash, type)
1074
+ self.spawn(self.load_balance_snapshot, client, messageHash, type, subType)
686
1075
  else:
687
1076
  self.balance[type] = {}
688
1077
 
689
- async def load_balance_snapshot(self, client, messageHash, type):
690
- response = await self.fetch_balance({'type': type})
1078
+ async def load_balance_snapshot(self, client, messageHash, type, subType):
1079
+ response = await self.fetch_balance({'type': type, 'subType': subType})
691
1080
  self.balance[type] = self.extend(response, self.safe_value(self.balance, type, {}))
692
1081
  # don't remove the future from the .futures cache
693
1082
  future = client.futures[messageHash]
@@ -721,7 +1110,7 @@ class bingx(ccxt.async_support.bingx):
721
1110
  try:
722
1111
  await self.userAuthPrivatePutUserDataStream({'listenKey': listenKey}) # self.extend the expiry
723
1112
  except Exception as error:
724
- types = ['spot', 'swap']
1113
+ types = ['spot', 'linear', 'inverse']
725
1114
  for i in range(0, len(types)):
726
1115
  type = types[i]
727
1116
  url = self.urls['api']['ws'][type] + '?listenKey=' + listenKey
@@ -928,13 +1317,16 @@ class bingx(ccxt.async_support.bingx):
928
1317
  # }
929
1318
  #
930
1319
  isSpot = ('dataType' in message)
931
- result = self.safe_value_2(message, 'data', 'o', {})
1320
+ result = self.safe_dict_2(message, 'data', 'o', {})
932
1321
  cachedTrades = self.myTrades
933
1322
  if cachedTrades is None:
934
1323
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
935
1324
  cachedTrades = ArrayCacheBySymbolById(limit)
936
1325
  self.myTrades = cachedTrades
937
- parsed = self.parse_trade(result)
1326
+ type = 'spot' if isSpot else 'swap'
1327
+ marketId = self.safe_string(result, 's')
1328
+ market = self.safe_market(marketId, None, '-', type)
1329
+ parsed = self.parse_trade(result, market)
938
1330
  symbol = parsed['symbol']
939
1331
  spotHash = 'spot:mytrades'
940
1332
  swapHash = 'swap:mytrades'
@@ -980,10 +1372,12 @@ class bingx(ccxt.async_support.bingx):
980
1372
  # }
981
1373
  # }
982
1374
  #
983
- a = self.safe_value(message, 'a', {})
984
- data = self.safe_value(a, 'B', [])
1375
+ a = self.safe_dict(message, 'a', {})
1376
+ data = self.safe_list(a, 'B', [])
985
1377
  timestamp = self.safe_integer_2(message, 'T', 'E')
986
1378
  type = 'swap' if ('P' in a) else 'spot'
1379
+ if not (type in self.balance):
1380
+ self.balance[type] = {}
987
1381
  self.balance[type]['info'] = data
988
1382
  self.balance[type]['timestamp'] = timestamp
989
1383
  self.balance[type]['datetime'] = self.iso8601(timestamp)
@@ -991,11 +1385,10 @@ class bingx(ccxt.async_support.bingx):
991
1385
  balance = data[i]
992
1386
  currencyId = self.safe_string(balance, 'a')
993
1387
  code = self.safe_currency_code(currencyId)
994
- account = self.balance[type][code] if (code in self.balance[type]) else self.account()
1388
+ account = self.account()
1389
+ account['info'] = balance
1390
+ account['used'] = self.safe_string(balance, 'lk')
995
1391
  account['free'] = self.safe_string(balance, 'wb')
996
- balanceChange = self.safe_string(balance, 'bc')
997
- if account['used'] is not None:
998
- account['used'] = Precise.string_sub(self.safe_string(account, 'used'), balanceChange)
999
1392
  self.balance[type][code] = account
1000
1393
  self.balance[type] = self.safe_balance(self.balance[type])
1001
1394
  client.resolve(self.balance[type], type + ':balance')