ccxt-ir 4.3.46.0.1__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 (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/pro/bitget.py ADDED
@@ -0,0 +1,1692 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
+ import hashlib
9
+ from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
10
+ from ccxt.async_support.base.ws.client import Client
11
+ from typing import List
12
+ from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import ArgumentsRequired
15
+ from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import RateLimitExceeded
17
+ from ccxt.base.errors import InvalidNonce
18
+ from ccxt.base.precise import Precise
19
+
20
+
21
+ class bitget(ccxt.async_support.bitget):
22
+
23
+ def describe(self):
24
+ return self.deep_extend(super(bitget, self).describe(), {
25
+ 'has': {
26
+ 'ws': True,
27
+ 'createOrderWs': False,
28
+ 'editOrderWs': False,
29
+ 'fetchOpenOrdersWs': False,
30
+ 'fetchOrderWs': False,
31
+ 'cancelOrderWs': False,
32
+ 'cancelOrdersWs': False,
33
+ 'cancelAllOrdersWs': False,
34
+ 'watchBalance': True,
35
+ 'watchMyTrades': True,
36
+ 'watchOHLCV': True,
37
+ 'watchOHLCVForSymbols': False,
38
+ 'watchOrderBook': True,
39
+ 'watchOrderBookForSymbols': True,
40
+ 'watchOrders': True,
41
+ 'watchTicker': True,
42
+ 'watchTickers': True,
43
+ 'watchTrades': True,
44
+ 'watchTradesForSymbols': True,
45
+ 'watchPositions': True,
46
+ },
47
+ 'urls': {
48
+ 'api': {
49
+ 'ws': {
50
+ 'public': 'wss://ws.bitget.com/v2/ws/public',
51
+ 'private': 'wss://ws.bitget.com/v2/ws/private',
52
+ },
53
+ },
54
+ },
55
+ 'options': {
56
+ 'tradesLimit': 1000,
57
+ 'OHLCVLimit': 1000,
58
+ # WS timeframes differ from REST timeframes
59
+ 'timeframes': {
60
+ '1m': '1m',
61
+ '5m': '5m',
62
+ '15m': '15m',
63
+ '30m': '30m',
64
+ '1h': '1H',
65
+ '4h': '4H',
66
+ '6h': '6H',
67
+ '12h': '12H',
68
+ '1d': '1D',
69
+ '1w': '1W',
70
+ },
71
+ },
72
+ 'streaming': {
73
+ 'ping': self.ping,
74
+ },
75
+ 'exceptions': {
76
+ 'ws': {
77
+ 'exact': {
78
+ '30001': BadRequest, # {"event":"error","code":30001,"msg":"instType:sp,channel:candleNone,instId:BTCUSDT doesn't exist"}
79
+ '30002': AuthenticationError, # illegal request
80
+ '30003': BadRequest, # invalid op
81
+ '30004': AuthenticationError, # requires login
82
+ '30005': AuthenticationError, # login failed
83
+ '30006': RateLimitExceeded, # too many requests
84
+ '30007': RateLimitExceeded, # request over limit,connection close
85
+ '30011': AuthenticationError, # invalid ACCESS_KEY
86
+ '30012': AuthenticationError, # invalid ACCESS_PASSPHRASE
87
+ '30013': AuthenticationError, # invalid ACCESS_TIMESTAMP
88
+ '30014': BadRequest, # Request timestamp expired
89
+ '30015': AuthenticationError, # {event: 'error', code: 30015, msg: 'Invalid sign'}
90
+ '30016': BadRequest, # {event: 'error', code: 30016, msg: 'Param error'}
91
+ },
92
+ 'broad': {},
93
+ },
94
+ },
95
+ })
96
+
97
+ def get_inst_type(self, market, params={}):
98
+ instType = None
99
+ if market is None:
100
+ instType, params = self.handleProductTypeAndParams(None, params)
101
+ elif (market['swap']) or (market['future']):
102
+ instType, params = self.handleProductTypeAndParams(market, params)
103
+ else:
104
+ instType = 'SPOT'
105
+ instypeAux = None
106
+ instypeAux, params = self.handle_option_and_params(params, 'getInstType', 'instType', instType)
107
+ instType = instypeAux
108
+ return [instType, params]
109
+
110
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
111
+ """
112
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
113
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
114
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
115
+ :param str symbol: unified symbol of the market to watch the ticker for
116
+ :param dict [params]: extra parameters specific to the exchange API endpoint
117
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
118
+ """
119
+ await self.load_markets()
120
+ market = self.market(symbol)
121
+ symbol = market['symbol']
122
+ messageHash = 'ticker:' + symbol
123
+ instType = None
124
+ instType, params = self.get_inst_type(market, params)
125
+ args: dict = {
126
+ 'instType': instType,
127
+ 'channel': 'ticker',
128
+ 'instId': market['id'],
129
+ }
130
+ return await self.watch_public(messageHash, args, params)
131
+
132
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
133
+ """
134
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
135
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
136
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
137
+ :param str[] symbols: unified symbol of the market to watch the tickers for
138
+ :param dict [params]: extra parameters specific to the exchange API endpoint
139
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
140
+ """
141
+ await self.load_markets()
142
+ symbols = self.market_symbols(symbols, None, False)
143
+ market = self.market(symbols[0])
144
+ instType = None
145
+ instType, params = self.get_inst_type(market, params)
146
+ topics = []
147
+ messageHashes = []
148
+ for i in range(0, len(symbols)):
149
+ symbol = symbols[i]
150
+ marketInner = self.market(symbol)
151
+ args: dict = {
152
+ 'instType': instType,
153
+ 'channel': 'ticker',
154
+ 'instId': marketInner['id'],
155
+ }
156
+ topics.append(args)
157
+ messageHashes.append('ticker:' + symbol)
158
+ tickers = await self.watch_public_multiple(messageHashes, topics, params)
159
+ if self.newUpdates:
160
+ result: dict = {}
161
+ result[tickers['symbol']] = tickers
162
+ return result
163
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
164
+
165
+ def handle_ticker(self, client: Client, message):
166
+ #
167
+ # {
168
+ # "action": "snapshot",
169
+ # "arg": {
170
+ # "instType": "SPOT",
171
+ # "channel": "ticker",
172
+ # "instId": "BTCUSDT"
173
+ # },
174
+ # "data": [
175
+ # {
176
+ # "instId": "BTCUSDT",
177
+ # "lastPr": "43528.19",
178
+ # "open24h": "42267.78",
179
+ # "high24h": "44490.00",
180
+ # "low24h": "41401.53",
181
+ # "change24h": "0.03879",
182
+ # "bidPr": "43528",
183
+ # "askPr": "43528.01",
184
+ # "bidSz": "0.0334",
185
+ # "askSz": "0.1917",
186
+ # "baseVolume": "15002.4216",
187
+ # "quoteVolume": "648006446.7164",
188
+ # "openUtc": "44071.18",
189
+ # "changeUtc24h": "-0.01232",
190
+ # "ts": "1701842994338"
191
+ # }
192
+ # ],
193
+ # "ts": 1701842994341
194
+ # }
195
+ #
196
+ ticker = self.parse_ws_ticker(message)
197
+ symbol = ticker['symbol']
198
+ self.tickers[symbol] = ticker
199
+ messageHash = 'ticker:' + symbol
200
+ client.resolve(ticker, messageHash)
201
+
202
+ def parse_ws_ticker(self, message, market=None):
203
+ #
204
+ # spot
205
+ #
206
+ # {
207
+ # "action": "snapshot",
208
+ # "arg": {
209
+ # "instType": "SPOT",
210
+ # "channel": "ticker",
211
+ # "instId": "BTCUSDT"
212
+ # },
213
+ # "data": [
214
+ # {
215
+ # "instId": "BTCUSDT",
216
+ # "lastPr": "43528.19",
217
+ # "open24h": "42267.78",
218
+ # "high24h": "44490.00",
219
+ # "low24h": "41401.53",
220
+ # "change24h": "0.03879",
221
+ # "bidPr": "43528",
222
+ # "askPr": "43528.01",
223
+ # "bidSz": "0.0334",
224
+ # "askSz": "0.1917",
225
+ # "baseVolume": "15002.4216",
226
+ # "quoteVolume": "648006446.7164",
227
+ # "openUtc": "44071.18",
228
+ # "changeUtc24h": "-0.01232",
229
+ # "ts": "1701842994338"
230
+ # }
231
+ # ],
232
+ # "ts": 1701842994341
233
+ # }
234
+ #
235
+ # contract
236
+ #
237
+ # {
238
+ # "action": "snapshot",
239
+ # "arg": {
240
+ # "instType": "USDT-FUTURES",
241
+ # "channel": "ticker",
242
+ # "instId": "BTCUSDT"
243
+ # },
244
+ # "data": [
245
+ # {
246
+ # "instId": "BTCUSDT",
247
+ # "lastPr": "43480.4",
248
+ # "bidPr": "43476.3",
249
+ # "askPr": "43476.8",
250
+ # "bidSz": "0.1",
251
+ # "askSz": "3.055",
252
+ # "open24h": "42252.3",
253
+ # "high24h": "44518.2",
254
+ # "low24h": "41387.0",
255
+ # "change24h": "0.03875",
256
+ # "fundingRate": "0.000096",
257
+ # "nextFundingTime": "1701849600000",
258
+ # "markPrice": "43476.4",
259
+ # "indexPrice": "43478.4",
260
+ # "holdingAmount": "50670.787",
261
+ # "baseVolume": "120187.104",
262
+ # "quoteVolume": "5167385048.693",
263
+ # "openUtc": "44071.4",
264
+ # "symbolType": "1",
265
+ # "symbol": "BTCUSDT",
266
+ # "deliveryPrice": "0",
267
+ # "ts": "1701843962811"
268
+ # }
269
+ # ],
270
+ # "ts": 1701843962812
271
+ # }
272
+ #
273
+ arg = self.safe_value(message, 'arg', {})
274
+ data = self.safe_value(message, 'data', [])
275
+ ticker = self.safe_value(data, 0, {})
276
+ timestamp = self.safe_integer(ticker, 'ts')
277
+ instType = self.safe_string(arg, 'instType')
278
+ marketType = 'spot' if (instType == 'SPOT') else 'contract'
279
+ marketId = self.safe_string(ticker, 'instId')
280
+ market = self.safe_market(marketId, market, None, marketType)
281
+ close = self.safe_string(ticker, 'lastPr')
282
+ changeDecimal = self.safe_string(ticker, 'change24h')
283
+ change = Precise.string_mul(changeDecimal, '100')
284
+ return self.safe_ticker({
285
+ 'symbol': market['symbol'],
286
+ 'timestamp': timestamp,
287
+ 'datetime': self.iso8601(timestamp),
288
+ 'high': self.safe_string(ticker, 'high24h'),
289
+ 'low': self.safe_string(ticker, 'low24h'),
290
+ 'bid': self.safe_string(ticker, 'bidPr'),
291
+ 'bidVolume': self.safe_string(ticker, 'bidSz'),
292
+ 'ask': self.safe_string(ticker, 'askPr'),
293
+ 'askVolume': self.safe_string(ticker, 'askSz'),
294
+ 'vwap': None,
295
+ 'open': self.safe_string(ticker, 'open24h'),
296
+ 'close': close,
297
+ 'last': close,
298
+ 'previousClose': None,
299
+ 'change': None,
300
+ 'percentage': change,
301
+ 'average': None,
302
+ 'baseVolume': self.safe_string(ticker, 'baseVolume'),
303
+ 'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
304
+ 'info': ticker,
305
+ }, market)
306
+
307
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
308
+ """
309
+ watches historical candlestick data containing the open, high, low, close price, and the volume of a market
310
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Candlesticks-Channel
311
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Candlesticks-Channel
312
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
313
+ :param str timeframe: the length of time each candle represents
314
+ :param int [since]: timestamp in ms of the earliest candle to fetch
315
+ :param int [limit]: the maximum amount of candles to fetch
316
+ :param dict [params]: extra parameters specific to the exchange API endpoint
317
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
318
+ """
319
+ await self.load_markets()
320
+ market = self.market(symbol)
321
+ symbol = market['symbol']
322
+ timeframes = self.safe_value(self.options, 'timeframes')
323
+ interval = self.safe_string(timeframes, timeframe)
324
+ messageHash = 'candles:' + timeframe + ':' + symbol
325
+ instType = None
326
+ instType, params = self.get_inst_type(market, params)
327
+ args: dict = {
328
+ 'instType': instType,
329
+ 'channel': 'candle' + interval,
330
+ 'instId': market['id'],
331
+ }
332
+ ohlcv = await self.watch_public(messageHash, args, params)
333
+ if self.newUpdates:
334
+ limit = ohlcv.getLimit(symbol, limit)
335
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
336
+
337
+ def handle_ohlcv(self, client: Client, message):
338
+ #
339
+ # {
340
+ # "action": "snapshot",
341
+ # "arg": {
342
+ # "instType": "SPOT",
343
+ # "channel": "candle1m",
344
+ # "instId": "BTCUSDT"
345
+ # },
346
+ # "data": [
347
+ # [
348
+ # "1701871620000",
349
+ # "44080.23",
350
+ # "44080.23",
351
+ # "44028.5",
352
+ # "44028.51",
353
+ # "9.9287",
354
+ # "437404.105512",
355
+ # "437404.105512"
356
+ # ],
357
+ # [
358
+ # "1701871680000",
359
+ # "44028.51",
360
+ # "44108.11",
361
+ # "44028.5",
362
+ # "44108.11",
363
+ # "17.139",
364
+ # "755436.870643",
365
+ # "755436.870643"
366
+ # ],
367
+ # ],
368
+ # "ts": 1701901610417
369
+ # }
370
+ #
371
+ arg = self.safe_value(message, 'arg', {})
372
+ instType = self.safe_string(arg, 'instType')
373
+ marketType = 'spot' if (instType == 'SPOT') else 'contract'
374
+ marketId = self.safe_string(arg, 'instId')
375
+ market = self.safe_market(marketId, None, None, marketType)
376
+ symbol = market['symbol']
377
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
378
+ channel = self.safe_string(arg, 'channel')
379
+ interval = channel.replace('candle', '')
380
+ timeframes = self.safe_value(self.options, 'timeframes')
381
+ timeframe = self.find_timeframe(interval, timeframes)
382
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
383
+ if stored is None:
384
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
385
+ stored = ArrayCacheByTimestamp(limit)
386
+ self.ohlcvs[symbol][timeframe] = stored
387
+ data = self.safe_value(message, 'data', [])
388
+ for i in range(0, len(data)):
389
+ parsed = self.parse_ws_ohlcv(data[i], market)
390
+ stored.append(parsed)
391
+ messageHash = 'candles:' + timeframe + ':' + symbol
392
+ client.resolve(stored, messageHash)
393
+
394
+ def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
395
+ #
396
+ # [
397
+ # "1701871620000", # timestamp
398
+ # "44080.23", # open
399
+ # "44080.23", # high
400
+ # "44028.5", # low
401
+ # "44028.51", # close
402
+ # "9.9287", # base volume
403
+ # "437404.105512", # quote volume
404
+ # "437404.105512" # USDT volume
405
+ # ]
406
+ #
407
+ volumeIndex = 6 if (market['inverse']) else 5
408
+ return [
409
+ self.safe_integer(ohlcv, 0),
410
+ self.safe_number(ohlcv, 1),
411
+ self.safe_number(ohlcv, 2),
412
+ self.safe_number(ohlcv, 3),
413
+ self.safe_number(ohlcv, 4),
414
+ self.safe_number(ohlcv, volumeIndex),
415
+ ]
416
+
417
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
418
+ """
419
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
420
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Depth-Channel
421
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Order-Book-Channel
422
+ :param str symbol: unified symbol of the market to fetch the order book for
423
+ :param int [limit]: the maximum amount of order book entries to return
424
+ :param dict [params]: extra parameters specific to the exchange API endpoint
425
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
426
+ """
427
+ return await self.watch_order_book_for_symbols([symbol], limit, params)
428
+
429
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
430
+ """
431
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
432
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Depth-Channel
433
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/Order-Book-Channel
434
+ :param str[] symbols: unified array of symbols
435
+ :param int [limit]: the maximum amount of order book entries to return
436
+ :param dict [params]: extra parameters specific to the exchange API endpoint
437
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
438
+ """
439
+ await self.load_markets()
440
+ symbols = self.market_symbols(symbols)
441
+ channel = 'books'
442
+ incrementalFeed = True
443
+ if (limit == 1) or (limit == 5) or (limit == 15):
444
+ channel += str(limit)
445
+ incrementalFeed = False
446
+ topics = []
447
+ messageHashes = []
448
+ for i in range(0, len(symbols)):
449
+ symbol = symbols[i]
450
+ market = self.market(symbol)
451
+ instType = None
452
+ instType, params = self.get_inst_type(market, params)
453
+ args: dict = {
454
+ 'instType': instType,
455
+ 'channel': channel,
456
+ 'instId': market['id'],
457
+ }
458
+ topics.append(args)
459
+ messageHashes.append('orderbook:' + symbol)
460
+ orderbook = await self.watch_public_multiple(messageHashes, topics, params)
461
+ if incrementalFeed:
462
+ return orderbook.limit()
463
+ else:
464
+ return orderbook
465
+
466
+ def handle_order_book(self, client: Client, message):
467
+ #
468
+ # {
469
+ # "action":"snapshot",
470
+ # "arg":{
471
+ # "instType":"SPOT",
472
+ # "channel":"books5",
473
+ # "instId":"BTCUSDT"
474
+ # },
475
+ # "data":[
476
+ # {
477
+ # "asks":[
478
+ # ["21041.11","0.0445"],
479
+ # ["21041.16","0.0411"],
480
+ # ["21041.21","0.0421"],
481
+ # ["21041.26","0.0811"],
482
+ # ["21041.65","1.9465"]
483
+ # ],
484
+ # "bids":[
485
+ # ["21040.76","0.0417"],
486
+ # ["21040.71","0.0434"],
487
+ # ["21040.66","0.1141"],
488
+ # ["21040.61","0.3004"],
489
+ # ["21040.60","1.3357"]
490
+ # ],
491
+ # "checksum": -1367582038,
492
+ # "ts":"1656413855484"
493
+ # }
494
+ # ]
495
+ # }
496
+ #
497
+ arg = self.safe_value(message, 'arg')
498
+ channel = self.safe_string(arg, 'channel')
499
+ instType = self.safe_string(arg, 'instType')
500
+ marketType = 'spot' if (instType == 'SPOT') else 'contract'
501
+ marketId = self.safe_string(arg, 'instId')
502
+ market = self.safe_market(marketId, None, None, marketType)
503
+ symbol = market['symbol']
504
+ messageHash = 'orderbook:' + symbol
505
+ data = self.safe_value(message, 'data')
506
+ rawOrderBook = self.safe_value(data, 0)
507
+ timestamp = self.safe_integer(rawOrderBook, 'ts')
508
+ incrementalBook = channel == 'books'
509
+ if incrementalBook:
510
+ # storedOrderBook = self.safe_value(self.orderbooks, symbol)
511
+ if not (symbol in self.orderbooks):
512
+ # ob = self.order_book({})
513
+ ob = self.counted_order_book({})
514
+ ob['symbol'] = symbol
515
+ self.orderbooks[symbol] = ob
516
+ storedOrderBook = self.orderbooks[symbol]
517
+ asks = self.safe_value(rawOrderBook, 'asks', [])
518
+ bids = self.safe_value(rawOrderBook, 'bids', [])
519
+ self.handle_deltas(storedOrderBook['asks'], asks)
520
+ self.handle_deltas(storedOrderBook['bids'], bids)
521
+ storedOrderBook['timestamp'] = timestamp
522
+ storedOrderBook['datetime'] = self.iso8601(timestamp)
523
+ checksum = self.safe_bool(self.options, 'checksum', True)
524
+ isSnapshot = self.safe_string(message, 'action') == 'snapshot' # snapshot does not have a checksum
525
+ if not isSnapshot and checksum:
526
+ storedAsks = storedOrderBook['asks']
527
+ storedBids = storedOrderBook['bids']
528
+ asksLength = len(storedAsks)
529
+ bidsLength = len(storedBids)
530
+ payloadArray = []
531
+ for i in range(0, 25):
532
+ if i < bidsLength:
533
+ payloadArray.append(storedBids[i][2][0])
534
+ payloadArray.append(storedBids[i][2][1])
535
+ if i < asksLength:
536
+ payloadArray.append(storedAsks[i][2][0])
537
+ payloadArray.append(storedAsks[i][2][1])
538
+ payload = ':'.join(payloadArray)
539
+ calculatedChecksum = self.crc32(payload, True)
540
+ responseChecksum = self.safe_integer(rawOrderBook, 'checksum')
541
+ if calculatedChecksum != responseChecksum:
542
+ error = InvalidNonce(self.id + ' invalid checksum')
543
+ del client.subscriptions[messageHash]
544
+ del self.orderbooks[symbol]
545
+ client.reject(error, messageHash)
546
+ return
547
+ else:
548
+ orderbook = self.order_book({})
549
+ parsedOrderbook = self.parse_order_book(rawOrderBook, symbol, timestamp)
550
+ orderbook.reset(parsedOrderbook)
551
+ self.orderbooks[symbol] = orderbook
552
+ client.resolve(self.orderbooks[symbol], messageHash)
553
+
554
+ def handle_delta(self, bookside, delta):
555
+ bidAsk = self.parse_bid_ask(delta, 0, 1)
556
+ # we store the string representations in the orderbook for checksum calculation
557
+ # self simplifies the code for generating checksums do not need to do any complex number transformations
558
+ bidAsk.append(delta)
559
+ bookside.storeArray(bidAsk)
560
+
561
+ def handle_deltas(self, bookside, deltas):
562
+ for i in range(0, len(deltas)):
563
+ self.handle_delta(bookside, deltas[i])
564
+
565
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
566
+ """
567
+ get the list of most recent trades for a particular symbol
568
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Trades-Channel
569
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/New-Trades-Channel
570
+ :param str symbol: unified symbol of the market to fetch trades for
571
+ :param int [since]: timestamp in ms of the earliest trade to fetch
572
+ :param int [limit]: the maximum amount of trades to fetch
573
+ :param dict [params]: extra parameters specific to the exchange API endpoint
574
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
575
+ """
576
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
577
+
578
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
579
+ """
580
+ get the list of most recent trades for a particular symbol
581
+ :see: https://www.bitget.com/api-doc/spot/websocket/public/Trades-Channel
582
+ :see: https://www.bitget.com/api-doc/contract/websocket/public/New-Trades-Channel
583
+ :param str symbol: unified symbol of the market to fetch trades for
584
+ :param int [since]: timestamp in ms of the earliest trade to fetch
585
+ :param int [limit]: the maximum amount of trades to fetch
586
+ :param dict [params]: extra parameters specific to the exchange API endpoint
587
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
588
+ """
589
+ symbolsLength = len(symbols)
590
+ if symbolsLength == 0:
591
+ raise ArgumentsRequired(self.id + ' watchTradesForSymbols() requires a non-empty array of symbols')
592
+ await self.load_markets()
593
+ symbols = self.market_symbols(symbols)
594
+ topics = []
595
+ messageHashes = []
596
+ for i in range(0, len(symbols)):
597
+ symbol = symbols[i]
598
+ market = self.market(symbol)
599
+ instType = None
600
+ instType, params = self.get_inst_type(market, params)
601
+ args: dict = {
602
+ 'instType': instType,
603
+ 'channel': 'trade',
604
+ 'instId': market['id'],
605
+ }
606
+ topics.append(args)
607
+ messageHashes.append('trade:' + symbol)
608
+ trades = await self.watch_public_multiple(messageHashes, topics, params)
609
+ if self.newUpdates:
610
+ first = self.safe_value(trades, 0)
611
+ tradeSymbol = self.safe_string(first, 'symbol')
612
+ limit = trades.getLimit(tradeSymbol, limit)
613
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
614
+
615
+ def handle_trades(self, client: Client, message):
616
+ #
617
+ # {
618
+ # "action": "snapshot",
619
+ # "arg": {"instType": "SPOT", "channel": "trade", "instId": "BTCUSDT"},
620
+ # "data": [
621
+ # {
622
+ # "ts": "1701910980366",
623
+ # "price": "43854.01",
624
+ # "size": "0.0535",
625
+ # "side": "buy",
626
+ # "tradeId": "1116461060594286593"
627
+ # },
628
+ # ],
629
+ # "ts": 1701910980730
630
+ # }
631
+ #
632
+ arg = self.safe_value(message, 'arg', {})
633
+ instType = self.safe_string(arg, 'instType')
634
+ marketType = 'spot' if (instType == 'SPOT') else 'contract'
635
+ marketId = self.safe_string(arg, 'instId')
636
+ market = self.safe_market(marketId, None, None, marketType)
637
+ symbol = market['symbol']
638
+ stored = self.safe_value(self.trades, symbol)
639
+ if stored is None:
640
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
641
+ stored = ArrayCache(limit)
642
+ self.trades[symbol] = stored
643
+ data = self.safe_list(message, 'data', [])
644
+ length = len(data)
645
+ # fix chronological order by reversing
646
+ for i in range(0, length):
647
+ index = length - i - 1
648
+ rawTrade = data[index]
649
+ parsed = self.parse_ws_trade(rawTrade, market)
650
+ stored.append(parsed)
651
+ messageHash = 'trade:' + symbol
652
+ client.resolve(stored, messageHash)
653
+
654
+ def parse_ws_trade(self, trade, market=None):
655
+ #
656
+ # {
657
+ # "ts": "1701910980366",
658
+ # "price": "43854.01",
659
+ # "size": "0.0535",
660
+ # "side": "buy",
661
+ # "tradeId": "1116461060594286593"
662
+ # }
663
+ # swap private
664
+ #
665
+ # {
666
+ # "orderId": "1169142761031114781",
667
+ # "tradeId": "1169142761312637004",
668
+ # "symbol": "LTCUSDT",
669
+ # "orderType": "market",
670
+ # "side": "buy",
671
+ # "price": "80.87",
672
+ # "baseVolume": "0.1",
673
+ # "quoteVolume": "8.087",
674
+ # "profit": "0",
675
+ # "tradeSide": "open",
676
+ # "posMode": "hedge_mode",
677
+ # "tradeScope": "taker",
678
+ # "feeDetail": [
679
+ # {
680
+ # "feeCoin": "USDT",
681
+ # "deduction": "no",
682
+ # "totalDeductionFee": "0",
683
+ # "totalFee": "-0.0048522"
684
+ # }
685
+ # ],
686
+ # "cTime": "1714471276596",
687
+ # "uTime": "1714471276596"
688
+ # }
689
+ # spot private
690
+ # {
691
+ # "orderId": "1169142457356959747",
692
+ # "tradeId": "1169142457636958209",
693
+ # "symbol": "LTCUSDT",
694
+ # "orderType": "market",
695
+ # "side": "buy",
696
+ # "priceAvg": "81.069",
697
+ # "size": "0.074",
698
+ # "amount": "5.999106",
699
+ # "tradeScope": "taker",
700
+ # "feeDetail": [
701
+ # {
702
+ # "feeCoin": "LTC",
703
+ # "deduction": "no",
704
+ # "totalDeductionFee": "0",
705
+ # "totalFee": "0.000074"
706
+ # }
707
+ # ],
708
+ # "cTime": "1714471204194",
709
+ # "uTime": "1714471204194"
710
+ # }
711
+ #
712
+ instId = self.safe_string_2(trade, 'symbol', 'instId')
713
+ posMode = self.safe_string(trade, 'posMode')
714
+ defaultType = 'contract' if (posMode is not None) else 'spot'
715
+ if market is None:
716
+ market = self.safe_market(instId, None, None, defaultType)
717
+ timestamp = self.safe_integer_n(trade, ['uTime', 'cTime', 'ts'])
718
+ feeDetail = self.safe_list(trade, 'feeDetail', [])
719
+ first = self.safe_dict(feeDetail, 0)
720
+ fee = None
721
+ if first is not None:
722
+ feeCurrencyId = self.safe_string(first, 'feeCoin')
723
+ feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
724
+ fee = {
725
+ 'cost': Precise.string_abs(self.safe_string(first, 'totalFee')),
726
+ 'currency': feeCurrencyCode,
727
+ }
728
+ return self.safe_trade({
729
+ 'info': trade,
730
+ 'id': self.safe_string(trade, 'tradeId'),
731
+ 'order': self.safe_string(trade, 'orderId'),
732
+ 'timestamp': timestamp,
733
+ 'datetime': self.iso8601(timestamp),
734
+ 'symbol': market['symbol'],
735
+ 'type': self.safe_string(trade, 'orderType'),
736
+ 'side': self.safe_string(trade, 'side'),
737
+ 'takerOrMaker': self.safe_string(trade, 'tradeScope'),
738
+ 'price': self.safe_string_2(trade, 'priceAvg', 'price'),
739
+ 'amount': self.safe_string_2(trade, 'size', 'baseVolume'),
740
+ 'cost': self.safe_string_2(trade, 'amount', 'quoteVolume'),
741
+ 'fee': fee,
742
+ }, market)
743
+
744
+ async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
745
+ """
746
+ watch all open positions
747
+ :see: https://www.bitget.com/api-doc/contract/websocket/private/Positions-Channel
748
+ :param str[]|None symbols: list of unified market symbols
749
+ :param dict params: extra parameters specific to the exchange API endpoint
750
+ :param str [params.instType]: one of 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES', default is 'USDT-FUTURES'
751
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
752
+ """
753
+ await self.load_markets()
754
+ market = None
755
+ messageHash = ''
756
+ subscriptionHash = 'positions'
757
+ instType = 'USDT-FUTURES'
758
+ symbols = self.market_symbols(symbols)
759
+ if not self.is_empty(symbols):
760
+ market = self.get_market_from_symbols(symbols)
761
+ instType, params = self.get_inst_type(market, params)
762
+ messageHash = instType + ':positions' + messageHash
763
+ args: dict = {
764
+ 'instType': instType,
765
+ 'channel': 'positions',
766
+ 'instId': 'default',
767
+ }
768
+ newPositions = await self.watch_private(messageHash, subscriptionHash, args, params)
769
+ if self.newUpdates:
770
+ return newPositions
771
+ return self.filter_by_symbols_since_limit(newPositions, symbols, since, limit, True)
772
+
773
+ def handle_positions(self, client: Client, message):
774
+ #
775
+ # {
776
+ # "action": "snapshot",
777
+ # "arg": {
778
+ # "instType": "USDT-FUTURES",
779
+ # "channel": "positions",
780
+ # "instId": "default"
781
+ # },
782
+ # "data": [
783
+ # {
784
+ # "posId": "926036334386778112",
785
+ # "instId": "BTCUSDT",
786
+ # "marginCoin": "USDT",
787
+ # "marginSize": "2.19245",
788
+ # "marginMode": "crossed",
789
+ # "holdSide": "long",
790
+ # "posMode": "hedge_mode",
791
+ # "total": "0.001",
792
+ # "available": "0.001",
793
+ # "frozen": "0",
794
+ # "openPriceAvg": "43849",
795
+ # "leverage": 20,
796
+ # "achievedProfits": "0",
797
+ # "unrealizedPL": "-0.0032",
798
+ # "unrealizedPLR": "-0.00145955438",
799
+ # "liquidationPrice": "17629.684814834",
800
+ # "keepMarginRate": "0.004",
801
+ # "marginRate": "0.007634649185",
802
+ # "cTime": "1652331666985",
803
+ # "uTime": "1701913016923",
804
+ # "autoMargin": "off"
805
+ # },
806
+ # ...
807
+ # ]
808
+ # "ts": 1701913043767
809
+ # }
810
+ #
811
+ arg = self.safe_value(message, 'arg', {})
812
+ instType = self.safe_string(arg, 'instType', '')
813
+ if self.positions is None:
814
+ self.positions = {}
815
+ if not (instType in self.positions):
816
+ self.positions[instType] = ArrayCacheBySymbolBySide()
817
+ cache = self.positions[instType]
818
+ rawPositions = self.safe_value(message, 'data', [])
819
+ dataLength = len(rawPositions)
820
+ if dataLength == 0:
821
+ return
822
+ newPositions = []
823
+ for i in range(0, len(rawPositions)):
824
+ rawPosition = rawPositions[i]
825
+ marketId = self.safe_string(rawPosition, 'instId')
826
+ market = self.safe_market(marketId, None, None, 'contract')
827
+ position = self.parse_ws_position(rawPosition, market)
828
+ newPositions.append(position)
829
+ cache.append(position)
830
+ messageHashes = self.find_message_hashes(client, instType + ':positions::')
831
+ for i in range(0, len(messageHashes)):
832
+ messageHash = messageHashes[i]
833
+ parts = messageHash.split('::')
834
+ symbolsString = parts[1]
835
+ symbols = symbolsString.split(',')
836
+ positions = self.filter_by_array(newPositions, 'symbol', symbols, False)
837
+ if not self.is_empty(positions):
838
+ client.resolve(positions, messageHash)
839
+ client.resolve(newPositions, instType + ':positions')
840
+
841
+ def parse_ws_position(self, position, market=None):
842
+ #
843
+ # {
844
+ # "posId": "926036334386778112",
845
+ # "instId": "BTCUSDT",
846
+ # "marginCoin": "USDT",
847
+ # "marginSize": "2.19245",
848
+ # "marginMode": "crossed",
849
+ # "holdSide": "long",
850
+ # "posMode": "hedge_mode",
851
+ # "total": "0.001",
852
+ # "available": "0.001",
853
+ # "frozen": "0",
854
+ # "openPriceAvg": "43849",
855
+ # "leverage": 20,
856
+ # "achievedProfits": "0",
857
+ # "unrealizedPL": "-0.0032",
858
+ # "unrealizedPLR": "-0.00145955438",
859
+ # "liquidationPrice": "17629.684814834",
860
+ # "keepMarginRate": "0.004",
861
+ # "marginRate": "0.007634649185",
862
+ # "cTime": "1652331666985",
863
+ # "uTime": "1701913016923",
864
+ # "autoMargin": "off"
865
+ # }
866
+ #
867
+ marketId = self.safe_string(position, 'instId')
868
+ marginModeId = self.safe_string(position, 'marginMode')
869
+ marginMode = self.get_supported_mapping(marginModeId, {
870
+ 'crossed': 'cross',
871
+ 'isolated': 'isolated',
872
+ })
873
+ hedgedId = self.safe_string(position, 'posMode')
874
+ hedged = True if (hedgedId == 'hedge_mode') else False
875
+ timestamp = self.safe_integer_2(position, 'uTime', 'cTime')
876
+ percentageDecimal = self.safe_string(position, 'unrealizedPLR')
877
+ percentage = Precise.string_mul(percentageDecimal, '100')
878
+ contractSize = None
879
+ if market is not None:
880
+ contractSize = market['contractSize']
881
+ return self.safe_position({
882
+ 'info': position,
883
+ 'id': self.safe_string(position, 'posId'),
884
+ 'symbol': self.safe_symbol(marketId, market, None, 'contract'),
885
+ 'notional': None,
886
+ 'marginMode': marginMode,
887
+ 'liquidationPrice': self.safe_number(position, 'liquidationPrice'),
888
+ 'entryPrice': self.safe_number(position, 'openPriceAvg'),
889
+ 'unrealizedPnl': self.safe_number(position, 'unrealizedPL'),
890
+ 'percentage': self.parse_number(percentage),
891
+ 'contracts': self.safe_number(position, 'total'),
892
+ 'contractSize': contractSize,
893
+ 'markPrice': None,
894
+ 'side': self.safe_string(position, 'holdSide'),
895
+ 'hedged': hedged,
896
+ 'timestamp': timestamp,
897
+ 'datetime': self.iso8601(timestamp),
898
+ 'maintenanceMargin': None,
899
+ 'maintenanceMarginPercentage': self.safe_number(position, 'keepMarginRate'),
900
+ 'collateral': None,
901
+ 'initialMargin': None,
902
+ 'initialMarginPercentage': None,
903
+ 'leverage': self.safe_number(position, 'leverage'),
904
+ 'marginRatio': self.safe_number(position, 'marginRate'),
905
+ })
906
+
907
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
908
+ """
909
+ watches information on multiple orders made by the user
910
+ :see: https://www.bitget.com/api-doc/spot/websocket/private/Order-Channel
911
+ :see: https://www.bitget.com/api-doc/contract/websocket/private/Order-Channel
912
+ :see: https://www.bitget.com/api-doc/contract/websocket/private/Plan-Order-Channel
913
+ :see: https://www.bitget.com/api-doc/margin/cross/websocket/private/Cross-Orders
914
+ :see: https://www.bitget.com/api-doc/margin/isolated/websocket/private/Isolate-Orders
915
+ :param str symbol: unified market symbol of the market orders were made in
916
+ :param int [since]: the earliest time in ms to fetch orders for
917
+ :param int [limit]: the maximum number of order structures to retrieve
918
+ :param dict [params]: extra parameters specific to the exchange API endpoint
919
+ :param boolean [params.stop]: *contract only* set to True for watching trigger orders
920
+ :param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders]
921
+ :param str [params.type]: 'spot', 'swap'
922
+ :param str [params.subType]: 'linear', 'inverse'
923
+ :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
924
+ """
925
+ await self.load_markets()
926
+ market = None
927
+ marketId = None
928
+ isTrigger = None
929
+ isTrigger, params = self.is_trigger_order(params)
930
+ messageHash = 'triggerOrder' if (isTrigger) else 'order'
931
+ subscriptionHash = 'order:trades'
932
+ if symbol is not None:
933
+ market = self.market(symbol)
934
+ symbol = market['symbol']
935
+ marketId = market['id']
936
+ messageHash = messageHash + ':' + symbol
937
+ productType = self.safe_string(params, 'productType')
938
+ type = None
939
+ type, params = self.handle_market_type_and_params('watchOrders', market, params)
940
+ subType = None
941
+ subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
942
+ if (type == 'spot' or type == 'margin') and (symbol is None):
943
+ raise ArgumentsRequired(self.id + ' watchOrders requires a symbol argument for ' + type + ' markets.')
944
+ if (productType is None) and (type != 'spot') and (symbol is None):
945
+ messageHash = messageHash + ':' + subType
946
+ elif productType == 'USDT-FUTURES':
947
+ messageHash = messageHash + ':linear'
948
+ elif productType == 'COIN-FUTURES':
949
+ messageHash = messageHash + ':inverse'
950
+ elif productType == 'USDC-FUTURES':
951
+ messageHash = messageHash + ':usdcfutures' # non unified channel
952
+ instType = None
953
+ instType, params = self.get_inst_type(market, params)
954
+ if type == 'spot':
955
+ subscriptionHash = subscriptionHash + ':' + symbol
956
+ if isTrigger:
957
+ subscriptionHash = subscriptionHash + ':stop' # we don't want to re-use the same subscription hash for stop orders
958
+ instId = marketId if (type == 'spot' or type == 'margin') else 'default' # different from other streams here the 'rest' id is required for spot markets, contract markets require default here
959
+ channel = 'orders-algo' if isTrigger else 'orders'
960
+ marginMode = None
961
+ marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
962
+ if marginMode is not None:
963
+ instType = 'MARGIN'
964
+ messageHash = messageHash + ':' + marginMode
965
+ if marginMode == 'isolated':
966
+ channel = 'orders-isolated'
967
+ else:
968
+ channel = 'orders-crossed'
969
+ subscriptionHash = subscriptionHash + ':' + instType
970
+ args: dict = {
971
+ 'instType': instType,
972
+ 'channel': channel,
973
+ 'instId': instId,
974
+ }
975
+ orders = await self.watch_private(messageHash, subscriptionHash, args, params)
976
+ if self.newUpdates:
977
+ limit = orders.getLimit(symbol, limit)
978
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
979
+
980
+ def handle_order(self, client: Client, message):
981
+ #
982
+ # spot
983
+ #
984
+ # {
985
+ # "action": "snapshot",
986
+ # "arg": {"instType": "SPOT", "channel": "orders", "instId": "BTCUSDT"},
987
+ # "data": [
988
+ # # see all examples in parseWsOrder
989
+ # ],
990
+ # "ts": 1701923297285
991
+ # }
992
+ #
993
+ # contract
994
+ #
995
+ # {
996
+ # "action": "snapshot",
997
+ # "arg": {"instType": "USDT-FUTURES", "channel": "orders", "instId": "default"},
998
+ # "data": [
999
+ # # see all examples in parseWsOrder
1000
+ # ],
1001
+ # "ts": 1701920595879
1002
+ # }
1003
+ #
1004
+ # isolated and cross margin
1005
+ #
1006
+ # {
1007
+ # "action": "snapshot",
1008
+ # "arg": {"instType": "MARGIN", "channel": "orders-crossed", "instId": "BTCUSDT"},
1009
+ # "data": [
1010
+ # # see examples in parseWsOrder
1011
+ # ],
1012
+ # "ts": 1701923982497
1013
+ # }
1014
+ #
1015
+ arg = self.safe_dict(message, 'arg', {})
1016
+ channel = self.safe_string(arg, 'channel')
1017
+ instType = self.safe_string(arg, 'instType')
1018
+ argInstId = self.safe_string(arg, 'instId')
1019
+ marketType = None
1020
+ if instType == 'SPOT':
1021
+ marketType = 'spot'
1022
+ elif instType == 'MARGIN':
1023
+ marketType = 'spot'
1024
+ else:
1025
+ marketType = 'contract'
1026
+ isLinearSwap = (instType == 'USDT-FUTURES')
1027
+ isInverseSwap = (instType == 'COIN-FUTURES')
1028
+ isUSDCFutures = (instType == 'USDC-FUTURES')
1029
+ data = self.safe_value(message, 'data', [])
1030
+ if self.orders is None:
1031
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
1032
+ self.orders = ArrayCacheBySymbolById(limit)
1033
+ self.triggerOrders = ArrayCacheBySymbolById(limit)
1034
+ isTrigger = (channel == 'orders-algo') or (channel == 'ordersAlgo')
1035
+ stored = self.triggerOrders if isTrigger else self.orders
1036
+ messageHash = 'triggerOrder' if isTrigger else 'order'
1037
+ marketSymbols: dict = {}
1038
+ for i in range(0, len(data)):
1039
+ order = data[i]
1040
+ marketId = self.safe_string(order, 'instId', argInstId)
1041
+ market = self.safe_market(marketId, None, None, marketType)
1042
+ parsed = self.parse_ws_order(order, market)
1043
+ stored.append(parsed)
1044
+ symbol = parsed['symbol']
1045
+ marketSymbols[symbol] = True
1046
+ keys = list(marketSymbols.keys())
1047
+ for i in range(0, len(keys)):
1048
+ symbol = keys[i]
1049
+ innerMessageHash = messageHash + ':' + symbol
1050
+ if channel == 'orders-crossed':
1051
+ innerMessageHash = innerMessageHash + ':cross'
1052
+ elif channel == 'orders-isolated':
1053
+ innerMessageHash = innerMessageHash + ':isolated'
1054
+ client.resolve(stored, innerMessageHash)
1055
+ client.resolve(stored, messageHash)
1056
+ if isLinearSwap:
1057
+ client.resolve(stored, 'order:linear')
1058
+ if isInverseSwap:
1059
+ client.resolve(stored, 'order:inverse')
1060
+ if isUSDCFutures:
1061
+ client.resolve(stored, 'order:usdcfutures')
1062
+
1063
+ def parse_ws_order(self, order, market=None):
1064
+ #
1065
+ # spot
1066
+ #
1067
+ # {
1068
+ # instId: 'EOSUSDT',
1069
+ # orderId: '1171779081105780739',
1070
+ # price: '0.81075', # limit price, field not present for market orders
1071
+ # clientOid: 'a2330139-1d04-4d78-98be-07de3cfd1055',
1072
+ # notional: '5.675250', # self is not cost! but notional
1073
+ # newSize: '7.0000', # self is not cost! quanity(for limit order or market sell) or cost(for market buy order)
1074
+ # size: '5.6752', # self is not cost, neither quanity, but notional! self field for "spot" can be ignored at all
1075
+ # # Note: for limit order(even filled) we don't have cost value in response, only in market order
1076
+ # orderType: 'limit', # limit, market
1077
+ # force: 'gtc',
1078
+ # side: 'buy',
1079
+ # accBaseVolume: '0.0000', # in case of 'filled', self would be set(for limit orders, self is the only indicator of the amount filled)
1080
+ # priceAvg: '0.00000', # in case of 'filled', self would be set
1081
+ # status: 'live', # live, filled, partially_filled
1082
+ # cTime: '1715099824215',
1083
+ # uTime: '1715099824215',
1084
+ # feeDetail: [],
1085
+ # enterPointSource: 'API'
1086
+ # #### trigger order has these additional fields: ####
1087
+ # "triggerPrice": "35100",
1088
+ # "price": "35100", # self is same price
1089
+ # "executePrice": "35123", # self is limit price
1090
+ # "triggerType": "fill_price",
1091
+ # "planType": "amount",
1092
+ # #### in case order had a partial fill: ####
1093
+ # fillPrice: '35123',
1094
+ # tradeId: '1171775539946528779',
1095
+ # baseVolume: '7', # field present in market order
1096
+ # fillTime: '1715098979937',
1097
+ # fillFee: '-0.0069987',
1098
+ # fillFeeCoin: 'BTC',
1099
+ # tradeScope: 'T',
1100
+ # }
1101
+ #
1102
+ # contract
1103
+ #
1104
+ # {
1105
+ # accBaseVolume: '0', # total amount filled during lifetime for order
1106
+ # cTime: '1715065875539',
1107
+ # clientOid: '1171636690041344003',
1108
+ # enterPointSource: 'API',
1109
+ # feeDetail: [{
1110
+ # "feeCoin": "USDT",
1111
+ # "fee": "-0.162003"
1112
+ # }],
1113
+ # force: 'gtc',
1114
+ # instId: 'SEOSSUSDT',
1115
+ # leverage: '10',
1116
+ # marginCoin: 'USDT',
1117
+ # marginMode: 'crossed',
1118
+ # notionalUsd: '10.4468',
1119
+ # orderId: '1171636690028761089',
1120
+ # orderType: 'market',
1121
+ # posMode: 'hedge_mode', # one_way_mode, hedge_mode
1122
+ # posSide: 'short', # short, long, net
1123
+ # price: '0', # zero for market order
1124
+ # reduceOnly: 'no',
1125
+ # side: 'sell',
1126
+ # size: '13', # self is contracts amount
1127
+ # status: 'live', # live, filled, cancelled
1128
+ # tradeSide: 'open',
1129
+ # uTime: '1715065875539'
1130
+ # #### when filled order is incoming, these additional fields are present too: ###
1131
+ # baseVolume: '9', # amount filled for the incoming update/trade
1132
+ # accBaseVolume: '13', # i.e. 9 has been filled from 13 amount(self value is same as 'size')
1133
+ # fillFee: '-0.0062712',
1134
+ # fillFeeCoin: 'SUSDT',
1135
+ # fillNotionalUsd: '10.452',
1136
+ # fillPrice: '0.804',
1137
+ # fillTime: '1715065875605',
1138
+ # pnl: '0',
1139
+ # priceAvg: '0.804',
1140
+ # tradeId: '1171636690314407937',
1141
+ # tradeScope: 'T',
1142
+ # #### trigger order has these additional fields:
1143
+ # "triggerPrice": "0.800000000",
1144
+ # "price": "0.800000000", # <-- self is same price, actual limit-price is not present in initial response
1145
+ # "triggerType": "mark_price",
1146
+ # "triggerTime": "1715082796679",
1147
+ # "planType": "pl",
1148
+ # "actualSize": "0.000000000",
1149
+ # "stopSurplusTriggerType": "fill_price",
1150
+ # "stopLossTriggerType": "fill_price",
1151
+ # }
1152
+ #
1153
+ # isolated and cross margin
1154
+ #
1155
+ # {
1156
+ # enterPointSource: "web",
1157
+ # feeDetail: [
1158
+ # {
1159
+ # feeCoin: "AAVE",
1160
+ # deduction: "no",
1161
+ # totalDeductionFee: "0",
1162
+ # totalFee: "-0.00010740",
1163
+ # },
1164
+ # ],
1165
+ # force: "gtc",
1166
+ # orderType: "limit",
1167
+ # price: "93.170000000",
1168
+ # fillPrice: "93.170000000",
1169
+ # baseSize: "0.110600000", # total amount of order
1170
+ # quoteSize: "10.304602000", # total cost of order(independently if order is filled or pending)
1171
+ # baseVolume: "0.107400000", # filled amount of order(during order's lifecycle, and not for self specific incoming update)
1172
+ # fillTotalAmount: "10.006458000", # filled cost of order(during order's lifecycle, and not for self specific incoming update)
1173
+ # side: "buy",
1174
+ # status: "partially_filled",
1175
+ # cTime: "1717875017306",
1176
+ # clientOid: "b57afe789a06454e9c560a2aab7f7201",
1177
+ # loanType: "auto-loan",
1178
+ # orderId: "1183419084588060673",
1179
+ # }
1180
+ #
1181
+ isSpot = not ('posMode' in order)
1182
+ isMargin = ('loanType' in order)
1183
+ marketId = self.safe_string(order, 'instId')
1184
+ market = self.safe_market(marketId, market)
1185
+ timestamp = self.safe_integer(order, 'cTime')
1186
+ symbol = market['symbol']
1187
+ rawStatus = self.safe_string(order, 'status')
1188
+ orderFee = self.safe_value(order, 'feeDetail', [])
1189
+ fee = self.safe_value(orderFee, 0)
1190
+ feeAmount = self.safe_string(fee, 'fee')
1191
+ feeObject = None
1192
+ if feeAmount is not None:
1193
+ feeCurrency = self.safe_string(fee, 'feeCoin')
1194
+ feeObject = {
1195
+ 'cost': self.parse_number(Precise.string_abs(feeAmount)),
1196
+ 'currency': self.safe_currency_code(feeCurrency),
1197
+ }
1198
+ triggerPrice = self.safe_number(order, 'triggerPrice')
1199
+ isTriggerOrder = (triggerPrice is not None)
1200
+ price = None
1201
+ if not isTriggerOrder:
1202
+ price = self.safe_number(order, 'price')
1203
+ elif isSpot and isTriggerOrder:
1204
+ # for spot trigger order, limit price is self
1205
+ price = self.safe_number(order, 'executePrice')
1206
+ avgPrice = self.omit_zero(self.safe_string_2(order, 'priceAvg', 'fillPrice'))
1207
+ side = self.safe_string(order, 'side')
1208
+ type = self.safe_string(order, 'orderType')
1209
+ accBaseVolume = self.omit_zero(self.safe_string(order, 'accBaseVolume'))
1210
+ newSizeValue = self.omit_zero(self.safe_string(order, 'newSize'))
1211
+ isMarketOrder = (type == 'market')
1212
+ isBuy = (side == 'buy')
1213
+ totalAmount = None
1214
+ filledAmount = None
1215
+ cost = None
1216
+ remaining = None
1217
+ totalFilled = self.safe_string(order, 'accBaseVolume')
1218
+ if isSpot:
1219
+ if isMargin:
1220
+ totalAmount = self.safe_string(order, 'baseSize')
1221
+ totalFilled = self.safe_string(order, 'baseVolume')
1222
+ cost = self.safe_string(order, 'fillTotalAmount')
1223
+ else:
1224
+ partialFillAmount = self.safe_string(order, 'baseVolume')
1225
+ if partialFillAmount is not None:
1226
+ filledAmount = partialFillAmount
1227
+ else:
1228
+ filledAmount = totalFilled
1229
+ if isMarketOrder:
1230
+ if isBuy:
1231
+ totalAmount = accBaseVolume
1232
+ cost = newSizeValue
1233
+ else:
1234
+ totalAmount = newSizeValue
1235
+ # we don't have cost for market-sell order
1236
+ else:
1237
+ totalAmount = self.safe_string(order, 'newSize')
1238
+ # we don't have cost for limit order
1239
+ else:
1240
+ # baseVolume should not be used for "amount" for contracts !
1241
+ filledAmount = self.safe_string(order, 'baseVolume')
1242
+ totalAmount = self.safe_string(order, 'size')
1243
+ cost = self.safe_string(order, 'fillNotionalUsd')
1244
+ remaining = Precise.string_sub(totalAmount, totalFilled)
1245
+ return self.safe_order({
1246
+ 'info': order,
1247
+ 'symbol': symbol,
1248
+ 'id': self.safe_string(order, 'orderId'),
1249
+ 'clientOrderId': self.safe_string(order, 'clientOid'),
1250
+ 'timestamp': timestamp,
1251
+ 'datetime': self.iso8601(timestamp),
1252
+ 'lastTradeTimestamp': self.safe_integer(order, 'uTime'),
1253
+ 'type': type,
1254
+ 'timeInForce': self.safe_string_upper(order, 'force'),
1255
+ 'postOnly': None,
1256
+ 'side': side,
1257
+ 'price': price,
1258
+ 'triggerPrice': triggerPrice,
1259
+ 'amount': totalAmount,
1260
+ 'cost': cost,
1261
+ 'average': avgPrice,
1262
+ 'filled': filledAmount,
1263
+ 'remaining': remaining,
1264
+ 'status': self.parse_ws_order_status(rawStatus),
1265
+ 'fee': feeObject,
1266
+ 'trades': None,
1267
+ }, market)
1268
+
1269
+ def parse_ws_order_status(self, status):
1270
+ statuses: dict = {
1271
+ 'live': 'open',
1272
+ 'partially_filled': 'open',
1273
+ 'filled': 'closed',
1274
+ 'cancelled': 'canceled',
1275
+ 'not_trigger': 'open',
1276
+ }
1277
+ return self.safe_string(statuses, status, status)
1278
+
1279
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1280
+ """
1281
+ watches trades made by the user
1282
+ :see: https://www.bitget.com/api-doc/contract/websocket/private/Order-Channel
1283
+ :param str symbol: unified market symbol
1284
+ :param int [since]: the earliest time in ms to fetch trades for
1285
+ :param int [limit]: the maximum number of trades structures to retrieve
1286
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1287
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1288
+ """
1289
+ await self.load_markets()
1290
+ market = None
1291
+ messageHash = 'myTrades'
1292
+ if symbol is not None:
1293
+ market = self.market(symbol)
1294
+ symbol = market['symbol']
1295
+ messageHash = messageHash + ':' + symbol
1296
+ instType = None
1297
+ instType, params = self.get_inst_type(market, params)
1298
+ subscriptionHash = 'fill:' + instType
1299
+ args: dict = {
1300
+ 'instType': instType,
1301
+ 'channel': 'fill',
1302
+ 'instId': 'default',
1303
+ }
1304
+ trades = await self.watch_private(messageHash, subscriptionHash, args, params)
1305
+ if self.newUpdates:
1306
+ limit = trades.getLimit(symbol, limit)
1307
+ return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
1308
+
1309
+ def handle_my_trades(self, client: Client, message):
1310
+ #
1311
+ # spot
1312
+ # {
1313
+ # "action": "snapshot",
1314
+ # "arg": {
1315
+ # "instType": "SPOT",
1316
+ # "channel": "fill",
1317
+ # "instId": "default"
1318
+ # },
1319
+ # "data": [
1320
+ # {
1321
+ # "orderId": "1169142457356959747",
1322
+ # "tradeId": "1169142457636958209",
1323
+ # "symbol": "LTCUSDT",
1324
+ # "orderType": "market",
1325
+ # "side": "buy",
1326
+ # "priceAvg": "81.069",
1327
+ # "size": "0.074",
1328
+ # "amount": "5.999106",
1329
+ # "tradeScope": "taker",
1330
+ # "feeDetail": [
1331
+ # {
1332
+ # "feeCoin": "LTC",
1333
+ # "deduction": "no",
1334
+ # "totalDeductionFee": "0",
1335
+ # "totalFee": "0.000074"
1336
+ # }
1337
+ # ],
1338
+ # "cTime": "1714471204194",
1339
+ # "uTime": "1714471204194"
1340
+ # }
1341
+ # ],
1342
+ # "ts": 1714471204270
1343
+ # }
1344
+ # swap
1345
+ # {
1346
+ # "action": "snapshot",
1347
+ # "arg": {
1348
+ # "instType": "USDT-FUTURES",
1349
+ # "channel": "fill",
1350
+ # "instId": "default"
1351
+ # },
1352
+ # "data": [
1353
+ # {
1354
+ # "orderId": "1169142761031114781",
1355
+ # "tradeId": "1169142761312637004",
1356
+ # "symbol": "LTCUSDT",
1357
+ # "orderType": "market",
1358
+ # "side": "buy",
1359
+ # "price": "80.87",
1360
+ # "baseVolume": "0.1",
1361
+ # "quoteVolume": "8.087",
1362
+ # "profit": "0",
1363
+ # "tradeSide": "open",
1364
+ # "posMode": "hedge_mode",
1365
+ # "tradeScope": "taker",
1366
+ # "feeDetail": [
1367
+ # {
1368
+ # "feeCoin": "USDT",
1369
+ # "deduction": "no",
1370
+ # "totalDeductionFee": "0",
1371
+ # "totalFee": "-0.0048522"
1372
+ # }
1373
+ # ],
1374
+ # "cTime": "1714471276596",
1375
+ # "uTime": "1714471276596"
1376
+ # }
1377
+ # ],
1378
+ # "ts": 1714471276629
1379
+ # }
1380
+ #
1381
+ if self.myTrades is None:
1382
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
1383
+ self.myTrades = ArrayCache(limit)
1384
+ stored = self.myTrades
1385
+ data = self.safe_list(message, 'data', [])
1386
+ length = len(data)
1387
+ messageHash = 'myTrades'
1388
+ for i in range(0, length):
1389
+ trade = data[i]
1390
+ parsed = self.parse_ws_trade(trade)
1391
+ stored.append(parsed)
1392
+ symbol = parsed['symbol']
1393
+ symbolSpecificMessageHash = 'myTrades:' + symbol
1394
+ client.resolve(stored, symbolSpecificMessageHash)
1395
+ client.resolve(stored, messageHash)
1396
+
1397
+ async def watch_balance(self, params={}) -> Balances:
1398
+ """
1399
+ watch balance and get the amount of funds available for trading or funds locked in orders
1400
+ :see: https://www.bitget.com/api-doc/spot/websocket/private/Account-Channel
1401
+ :see: https://www.bitget.com/api-doc/contract/websocket/private/Account-Channel
1402
+ :see: https://www.bitget.com/api-doc/margin/cross/websocket/private/Margin-Cross-Account-Assets
1403
+ :see: https://www.bitget.com/api-doc/margin/isolated/websocket/private/Margin-isolated-account-assets
1404
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1405
+ :param str [params.type]: spot or contract if not provided self.options['defaultType'] is used
1406
+ :param str [params.instType]: one of 'SPOT', 'MARGIN', 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
1407
+ :param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin balances
1408
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1409
+ """
1410
+ type = None
1411
+ type, params = self.handle_market_type_and_params('watchBalance', None, params)
1412
+ marginMode = None
1413
+ marginMode, params = self.handle_margin_mode_and_params('watchBalance', params)
1414
+ instType = None
1415
+ channel = 'account'
1416
+ if (type == 'swap') or (type == 'future'):
1417
+ instType = 'USDT-FUTURES'
1418
+ elif marginMode is not None:
1419
+ instType = 'MARGIN'
1420
+ if marginMode == 'isolated':
1421
+ channel = 'account-isolated'
1422
+ else:
1423
+ channel = 'account-crossed'
1424
+ else:
1425
+ instType = 'SPOT'
1426
+ instType, params = self.handle_option_and_params(params, 'watchBalance', 'instType', instType)
1427
+ args: dict = {
1428
+ 'instType': instType,
1429
+ 'channel': channel,
1430
+ 'coin': 'default',
1431
+ }
1432
+ messageHash = 'balance:' + instType.lower()
1433
+ return await self.watch_private(messageHash, messageHash, args, params)
1434
+
1435
+ def handle_balance(self, client: Client, message):
1436
+ #
1437
+ # spot
1438
+ #
1439
+ # {
1440
+ # "action": "snapshot",
1441
+ # "arg": {"instType": "SPOT", "channel": "account", "coin": "default"},
1442
+ # "data": [
1443
+ # {
1444
+ # "coin": "USDT",
1445
+ # "available": "19.1430952856087",
1446
+ # "frozen": "7",
1447
+ # "locked": "0",
1448
+ # "limitAvailable": "0",
1449
+ # "uTime": "1701931970487"
1450
+ # },
1451
+ # ],
1452
+ # "ts": 1701931970487
1453
+ # }
1454
+ #
1455
+ # swap
1456
+ #
1457
+ # {
1458
+ # "action": "snapshot",
1459
+ # "arg": {"instType": "USDT-FUTURES", "channel": "account", "coin": "default"},
1460
+ # "data": [
1461
+ # {
1462
+ # "marginCoin": "USDT",
1463
+ # "frozen": "5.36581500",
1464
+ # "available": "26.14309528",
1465
+ # "maxOpenPosAvailable": "20.77728028",
1466
+ # "maxTransferOut": "20.77728028",
1467
+ # "equity": "26.14309528",
1468
+ # "usdtEquity": "26.143095285166"
1469
+ # }
1470
+ # ],
1471
+ # "ts": 1701932570822
1472
+ # }
1473
+ #
1474
+ # margin
1475
+ #
1476
+ # {
1477
+ # "action": "snapshot",
1478
+ # "arg": {"instType": "MARGIN", "channel": "account-crossed", "coin": "default"},
1479
+ # "data": [
1480
+ # {
1481
+ # "uTime": "1701933110544",
1482
+ # "id": "1096916799926710272",
1483
+ # "coin": "USDT",
1484
+ # "available": "16.24309528",
1485
+ # "borrow": "0.00000000",
1486
+ # "frozen": "9.90000000",
1487
+ # "interest": "0.00000000",
1488
+ # "coupon": "0.00000000"
1489
+ # }
1490
+ # ],
1491
+ # "ts": 1701933110544
1492
+ # }
1493
+ #
1494
+ data = self.safe_value(message, 'data', [])
1495
+ for i in range(0, len(data)):
1496
+ rawBalance = data[i]
1497
+ currencyId = self.safe_string_2(rawBalance, 'coin', 'marginCoin')
1498
+ code = self.safe_currency_code(currencyId)
1499
+ account = self.balance[code] if (code in self.balance) else self.account()
1500
+ borrow = self.safe_string(rawBalance, 'borrow')
1501
+ if borrow is not None:
1502
+ interest = self.safe_string(rawBalance, 'interest')
1503
+ account['debt'] = Precise.string_add(borrow, interest)
1504
+ freeQuery = 'maxTransferOut' if ('maxTransferOut' in rawBalance) else 'available'
1505
+ account['free'] = self.safe_string(rawBalance, freeQuery)
1506
+ account['total'] = self.safe_string(rawBalance, 'equity')
1507
+ account['used'] = self.safe_string(rawBalance, 'frozen')
1508
+ self.balance[code] = account
1509
+ self.balance = self.safe_balance(self.balance)
1510
+ arg = self.safe_value(message, 'arg')
1511
+ instType = self.safe_string_lower(arg, 'instType')
1512
+ messageHash = 'balance:' + instType
1513
+ client.resolve(self.balance, messageHash)
1514
+
1515
+ async def watch_public(self, messageHash, args, params={}):
1516
+ url = self.urls['api']['ws']['public']
1517
+ request: dict = {
1518
+ 'op': 'subscribe',
1519
+ 'args': [args],
1520
+ }
1521
+ message = self.extend(request, params)
1522
+ return await self.watch(url, messageHash, message, messageHash)
1523
+
1524
+ async def watch_public_multiple(self, messageHashes, argsArray, params={}):
1525
+ url = self.urls['api']['ws']['public']
1526
+ request: dict = {
1527
+ 'op': 'subscribe',
1528
+ 'args': argsArray,
1529
+ }
1530
+ message = self.extend(request, params)
1531
+ return await self.watch_multiple(url, messageHashes, message, messageHashes)
1532
+
1533
+ async def authenticate(self, params={}):
1534
+ self.check_required_credentials()
1535
+ url = self.urls['api']['ws']['private']
1536
+ client = self.client(url)
1537
+ messageHash = 'authenticated'
1538
+ future = client.future(messageHash)
1539
+ authenticated = self.safe_value(client.subscriptions, messageHash)
1540
+ if authenticated is None:
1541
+ timestamp = str(self.seconds())
1542
+ auth = timestamp + 'GET' + '/user/verify'
1543
+ signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256, 'base64')
1544
+ operation = 'login'
1545
+ request: dict = {
1546
+ 'op': operation,
1547
+ 'args': [
1548
+ {
1549
+ 'apiKey': self.apiKey,
1550
+ 'passphrase': self.password,
1551
+ 'timestamp': timestamp,
1552
+ 'sign': signature,
1553
+ },
1554
+ ],
1555
+ }
1556
+ message = self.extend(request, params)
1557
+ self.watch(url, messageHash, message, messageHash)
1558
+ return await future
1559
+
1560
+ async def watch_private(self, messageHash, subscriptionHash, args, params={}):
1561
+ await self.authenticate()
1562
+ url = self.urls['api']['ws']['private']
1563
+ request: dict = {
1564
+ 'op': 'subscribe',
1565
+ 'args': [args],
1566
+ }
1567
+ message = self.extend(request, params)
1568
+ return await self.watch(url, messageHash, message, subscriptionHash)
1569
+
1570
+ def handle_authenticate(self, client: Client, message):
1571
+ #
1572
+ # {event: "login", code: 0}
1573
+ #
1574
+ messageHash = 'authenticated'
1575
+ future = self.safe_value(client.futures, messageHash)
1576
+ future.resolve(True)
1577
+
1578
+ def handle_error_message(self, client: Client, message):
1579
+ #
1580
+ # {event: "error", code: 30015, msg: "Invalid sign"}
1581
+ #
1582
+ event = self.safe_string(message, 'event')
1583
+ try:
1584
+ if event == 'error':
1585
+ code = self.safe_string(message, 'code')
1586
+ feedback = self.id + ' ' + self.json(message)
1587
+ self.throw_exactly_matched_exception(self.exceptions['ws']['exact'], code, feedback)
1588
+ msg = self.safe_string(message, 'msg', '')
1589
+ self.throw_broadly_matched_exception(self.exceptions['ws']['broad'], msg, feedback)
1590
+ raise ExchangeError(feedback)
1591
+ return False
1592
+ except Exception as e:
1593
+ if isinstance(e, AuthenticationError):
1594
+ messageHash = 'authenticated'
1595
+ client.reject(e, messageHash)
1596
+ if messageHash in client.subscriptions:
1597
+ del client.subscriptions[messageHash]
1598
+ else:
1599
+ # Note: if error happens on a subscribe event, user will have to close exchange to resubscribe. Issue #19041
1600
+ client.reject(e)
1601
+ return True
1602
+
1603
+ def handle_message(self, client: Client, message):
1604
+ #
1605
+ # {
1606
+ # "action": "snapshot",
1607
+ # "arg": {instType: 'SPOT', channel: "ticker", instId: "BTCUSDT"},
1608
+ # "data": [
1609
+ # {
1610
+ # "instId": "BTCUSDT",
1611
+ # "last": "21150.53",
1612
+ # "open24h": "20759.65",
1613
+ # "high24h": "21202.29",
1614
+ # "low24h": "20518.82",
1615
+ # "bestBid": "21150.500000",
1616
+ # "bestAsk": "21150.600000",
1617
+ # "baseVolume": "25402.1961",
1618
+ # "quoteVolume": "530452554.2156",
1619
+ # "ts": 1656408934044,
1620
+ # "labeId": 0
1621
+ # }
1622
+ # ]
1623
+ # }
1624
+ # pong message
1625
+ # "pong"
1626
+ #
1627
+ # login
1628
+ #
1629
+ # {event: "login", code: 0}
1630
+ #
1631
+ # subscribe
1632
+ #
1633
+ # {
1634
+ # "event": "subscribe",
1635
+ # "arg": {instType: 'SPOT', channel: "account", instId: "default"}
1636
+ # }
1637
+ #
1638
+ if self.handle_error_message(client, message):
1639
+ return
1640
+ content = self.safe_string(message, 'message')
1641
+ if content == 'pong':
1642
+ self.handle_pong(client, message)
1643
+ return
1644
+ if message == 'pong':
1645
+ self.handle_pong(client, message)
1646
+ return
1647
+ event = self.safe_string(message, 'event')
1648
+ if event == 'login':
1649
+ self.handle_authenticate(client, message)
1650
+ return
1651
+ if event == 'subscribe':
1652
+ self.handle_subscription_status(client, message)
1653
+ return
1654
+ methods: dict = {
1655
+ 'ticker': self.handle_ticker,
1656
+ 'trade': self.handle_trades,
1657
+ 'fill': self.handle_my_trades,
1658
+ 'orders': self.handle_order,
1659
+ 'ordersAlgo': self.handle_order,
1660
+ 'orders-algo': self.handle_order,
1661
+ 'orders-crossed': self.handle_order,
1662
+ 'orders-isolated': self.handle_order,
1663
+ 'account': self.handle_balance,
1664
+ 'positions': self.handle_positions,
1665
+ 'account-isolated': self.handle_balance,
1666
+ 'account-crossed': self.handle_balance,
1667
+ }
1668
+ arg = self.safe_value(message, 'arg', {})
1669
+ topic = self.safe_value(arg, 'channel', '')
1670
+ method = self.safe_value(methods, topic)
1671
+ if method is not None:
1672
+ method(client, message)
1673
+ if topic.find('candle') >= 0:
1674
+ self.handle_ohlcv(client, message)
1675
+ if topic.find('books') >= 0:
1676
+ self.handle_order_book(client, message)
1677
+
1678
+ def ping(self, client):
1679
+ return 'ping'
1680
+
1681
+ def handle_pong(self, client: Client, message):
1682
+ client.lastPong = self.milliseconds()
1683
+ return message
1684
+
1685
+ def handle_subscription_status(self, client: Client, message):
1686
+ #
1687
+ # {
1688
+ # "event": "subscribe",
1689
+ # "arg": {instType: 'SPOT', channel: "account", instId: "default"}
1690
+ # }
1691
+ #
1692
+ return message