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/ascendex.py ADDED
@@ -0,0 +1,3330 @@
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
+ from ccxt.base.exchange import Exchange
7
+ from ccxt.abstract.ascendex import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Account, Balances, Currencies, Currency, Int, Leverage, Leverages, LeverageTier, LeverageTiers, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import AccountSuspended
15
+ from ccxt.base.errors import ArgumentsRequired
16
+ from ccxt.base.errors import BadRequest
17
+ from ccxt.base.errors import BadSymbol
18
+ from ccxt.base.errors import InsufficientFunds
19
+ from ccxt.base.errors import InvalidOrder
20
+ from ccxt.base.errors import NotSupported
21
+ from ccxt.base.decimal_to_precision import TICK_SIZE
22
+ from ccxt.base.precise import Precise
23
+
24
+
25
+ class ascendex(Exchange, ImplicitAPI):
26
+
27
+ def describe(self):
28
+ return self.deep_extend(super(ascendex, self).describe(), {
29
+ 'id': 'ascendex',
30
+ 'name': 'AscendEX',
31
+ 'countries': ['SG'], # Singapore
32
+ # 8 requests per minute = 0.13333 per second => rateLimit = 750
33
+ # testing 400 works
34
+ 'rateLimit': 400,
35
+ 'certified': False,
36
+ 'pro': True,
37
+ # new metainfo interface
38
+ 'has': {
39
+ 'CORS': None,
40
+ 'spot': True,
41
+ 'margin': True,
42
+ 'swap': True,
43
+ 'future': False,
44
+ 'option': False,
45
+ 'addMargin': True,
46
+ 'cancelAllOrders': True,
47
+ 'cancelOrder': True,
48
+ 'createOrder': True,
49
+ 'createOrders': True,
50
+ 'createPostOnlyOrder': True,
51
+ 'createReduceOnlyOrder': True,
52
+ 'createStopLimitOrder': True,
53
+ 'createStopMarketOrder': True,
54
+ 'createStopOrder': True,
55
+ 'fetchAccounts': True,
56
+ 'fetchBalance': True,
57
+ 'fetchClosedOrders': True,
58
+ 'fetchCurrencies': True,
59
+ 'fetchDepositAddress': True,
60
+ 'fetchDepositAddresses': False,
61
+ 'fetchDepositAddressesByNetwork': False,
62
+ 'fetchDeposits': True,
63
+ 'fetchDepositsWithdrawals': True,
64
+ 'fetchDepositWithdrawFee': 'emulated',
65
+ 'fetchDepositWithdrawFees': True,
66
+ 'fetchFundingHistory': True,
67
+ 'fetchFundingRate': 'emulated',
68
+ 'fetchFundingRateHistory': False,
69
+ 'fetchFundingRates': True,
70
+ 'fetchIndexOHLCV': False,
71
+ 'fetchLeverage': 'emulated',
72
+ 'fetchLeverages': True,
73
+ 'fetchLeverageTiers': True,
74
+ 'fetchMarginMode': 'emulated',
75
+ 'fetchMarginModes': True,
76
+ 'fetchMarketLeverageTiers': 'emulated',
77
+ 'fetchMarkets': True,
78
+ 'fetchMarkOHLCV': False,
79
+ 'fetchOHLCV': True,
80
+ 'fetchOpenInterest': False,
81
+ 'fetchOpenInterestHistory': False,
82
+ 'fetchOpenOrders': True,
83
+ 'fetchOrder': True,
84
+ 'fetchOrderBook': True,
85
+ 'fetchOrders': False,
86
+ 'fetchPosition': False,
87
+ 'fetchPositionMode': False,
88
+ 'fetchPositions': True,
89
+ 'fetchPositionsRisk': False,
90
+ 'fetchPremiumIndexOHLCV': False,
91
+ 'fetchTicker': True,
92
+ 'fetchTickers': True,
93
+ 'fetchTime': True,
94
+ 'fetchTrades': True,
95
+ 'fetchTradingFee': False,
96
+ 'fetchTradingFees': True,
97
+ 'fetchTransactionFee': False,
98
+ 'fetchTransactionFees': False,
99
+ 'fetchTransactions': 'emulated',
100
+ 'fetchTransfer': False,
101
+ 'fetchTransfers': False,
102
+ 'fetchWithdrawal': False,
103
+ 'fetchWithdrawals': True,
104
+ 'reduceMargin': True,
105
+ 'sandbox': True,
106
+ 'setLeverage': True,
107
+ 'setMarginMode': True,
108
+ 'setPositionMode': False,
109
+ 'transfer': True,
110
+ },
111
+ 'timeframes': {
112
+ '1m': '1',
113
+ '5m': '5',
114
+ '15m': '15',
115
+ '30m': '30',
116
+ '1h': '60',
117
+ '2h': '120',
118
+ '4h': '240',
119
+ '6h': '360',
120
+ '12h': '720',
121
+ '1d': '1d',
122
+ '1w': '1w',
123
+ '1M': '1m',
124
+ },
125
+ 'version': 'v2',
126
+ 'urls': {
127
+ 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg',
128
+ 'api': {
129
+ 'rest': 'https://ascendex.com',
130
+ },
131
+ 'test': {
132
+ 'rest': 'https://api-test.ascendex-sandbox.com',
133
+ },
134
+ 'www': 'https://ascendex.com',
135
+ 'doc': [
136
+ 'https://ascendex.github.io/ascendex-pro-api/#ascendex-pro-api-documentation',
137
+ ],
138
+ 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate',
139
+ 'referral': {
140
+ 'url': 'https://ascendex.com/en-us/register?inviteCode=EL6BXBQM',
141
+ 'discount': 0.25,
142
+ },
143
+ },
144
+ 'api': {
145
+ 'v1': {
146
+ 'public': {
147
+ 'get': {
148
+ 'assets': 1,
149
+ 'products': 1,
150
+ 'ticker': 1,
151
+ 'barhist/info': 1,
152
+ 'barhist': 1,
153
+ 'depth': 1,
154
+ 'trades': 1,
155
+ 'cash/assets': 1, # not documented
156
+ 'cash/products': 1, # not documented
157
+ 'margin/assets': 1, # not documented
158
+ 'margin/products': 1, # not documented
159
+ 'futures/collateral': 1,
160
+ 'futures/contracts': 1,
161
+ 'futures/ref-px': 1,
162
+ 'futures/market-data': 1,
163
+ 'futures/funding-rates': 1,
164
+ 'risk-limit-info': 1,
165
+ 'exchange-info': 1,
166
+ },
167
+ },
168
+ 'private': {
169
+ 'get': {
170
+ 'info': 1,
171
+ 'wallet/transactions': 1,
172
+ 'wallet/deposit/address': 1,
173
+ 'data/balance/snapshot': 1,
174
+ 'data/balance/history': 1,
175
+ },
176
+ 'accountCategory': {
177
+ 'get': {
178
+ 'balance': 1,
179
+ 'order/open': 1,
180
+ 'order/status': 1,
181
+ 'order/hist/current': 1,
182
+ 'risk': 1,
183
+ },
184
+ 'post': {
185
+ 'order': 1,
186
+ 'order/batch': 1,
187
+ },
188
+ 'delete': {
189
+ 'order': 1,
190
+ 'order/all': 1,
191
+ 'order/batch': 1,
192
+ },
193
+ },
194
+ 'accountGroup': {
195
+ 'get': {
196
+ 'cash/balance': 1,
197
+ 'margin/balance': 1,
198
+ 'margin/risk': 1,
199
+ 'futures/collateral-balance': 1,
200
+ 'futures/position': 1,
201
+ 'futures/risk': 1,
202
+ 'futures/funding-payments': 1,
203
+ 'order/hist': 1,
204
+ 'spot/fee': 1,
205
+ },
206
+ 'post': {
207
+ 'transfer': 1,
208
+ 'futures/transfer/deposit': 1,
209
+ 'futures/transfer/withdraw': 1,
210
+ },
211
+ },
212
+ },
213
+ },
214
+ 'v2': {
215
+ 'public': {
216
+ 'get': {
217
+ 'assets': 1,
218
+ 'futures/contract': 1,
219
+ 'futures/collateral': 1,
220
+ 'futures/pricing-data': 1,
221
+ 'futures/ticker': 1,
222
+ 'risk-limit-info': 1,
223
+ },
224
+ },
225
+ 'private': {
226
+ 'data': {
227
+ 'get': {
228
+ 'order/hist': 1,
229
+ },
230
+ },
231
+ 'get': {
232
+ 'account/info': 1,
233
+ },
234
+ 'accountGroup': {
235
+ 'get': {
236
+ 'order/hist': 1,
237
+ 'futures/position': 1,
238
+ 'futures/free-margin': 1,
239
+ 'futures/order/hist/current': 1,
240
+ 'futures/funding-payments': 1,
241
+ 'futures/order/open': 1,
242
+ 'futures/order/status': 1,
243
+ },
244
+ 'post': {
245
+ 'futures/isolated-position-margin': 1,
246
+ 'futures/margin-type': 1,
247
+ 'futures/leverage': 1,
248
+ 'futures/transfer/deposit': 1,
249
+ 'futures/transfer/withdraw': 1,
250
+ 'futures/order': 1,
251
+ 'futures/order/batch': 1,
252
+ 'futures/order/open': 1,
253
+ 'subuser/subuser-transfer': 1,
254
+ 'subuser/subuser-transfer-hist': 1,
255
+ },
256
+ 'delete': {
257
+ 'futures/order': 1,
258
+ 'futures/order/batch': 1,
259
+ 'futures/order/all': 1,
260
+ },
261
+ },
262
+ },
263
+ },
264
+ },
265
+ 'fees': {
266
+ 'trading': {
267
+ 'feeSide': 'get',
268
+ 'tierBased': True,
269
+ 'percentage': True,
270
+ 'taker': self.parse_number('0.002'),
271
+ 'maker': self.parse_number('0.002'),
272
+ },
273
+ },
274
+ 'precisionMode': TICK_SIZE,
275
+ 'options': {
276
+ 'account-category': 'cash', # 'cash', 'margin', 'futures' # obsolete
277
+ 'account-group': None,
278
+ 'fetchClosedOrders': {
279
+ 'method': 'v2PrivateDataGetOrderHist', # 'v1PrivateAccountCategoryGetOrderHistCurrent'
280
+ },
281
+ 'defaultType': 'spot', # 'spot', 'margin', 'swap'
282
+ 'accountsByType': {
283
+ 'spot': 'cash',
284
+ 'swap': 'futures',
285
+ 'margin': 'margin',
286
+ },
287
+ 'transfer': {
288
+ 'fillResponseFromRequest': True,
289
+ },
290
+ 'networks': {
291
+ 'BSC': 'BEP20 ' + '(BSC)',
292
+ 'ARB': 'arbitrum',
293
+ 'SOL': 'Solana',
294
+ 'AVAX': 'avalanche C chain',
295
+ 'OMNI': 'Omni',
296
+ 'TRC': 'TRC20',
297
+ 'TRX': 'TRC20',
298
+ 'ERC': 'ERC20',
299
+ },
300
+ 'networksById': {
301
+ 'BEP20(BSC)': 'BSC',
302
+ 'arbitrum': 'ARB',
303
+ 'Solana': 'SOL',
304
+ 'avalanche C chain': 'AVAX',
305
+ 'Omni': 'OMNI',
306
+ 'TRC20': 'TRC20',
307
+ 'ERC20': 'ERC20',
308
+ 'GO20': 'GO20',
309
+ 'BEP2': 'BEP2',
310
+ 'Bitcoin': 'BTC',
311
+ 'Bitcoin ABC': 'BCH',
312
+ 'Litecoin': 'LTC',
313
+ 'Matic Network': 'MATIC',
314
+ 'xDai': 'STAKE',
315
+ 'Akash': 'AKT',
316
+ },
317
+ },
318
+ 'exceptions': {
319
+ 'exact': {
320
+ # not documented
321
+ '1900': BadRequest, # {"code":1900,"message":"Invalid Http Request Input"}
322
+ '2100': AuthenticationError, # {"code":2100,"message":"ApiKeyFailure"}
323
+ '5002': BadSymbol, # {"code":5002,"message":"Invalid Symbol"}
324
+ '6001': BadSymbol, # {"code":6001,"message":"Trading is disabled on symbol."}
325
+ '6010': InsufficientFunds, # {'code': 6010, 'message': 'Not enough balance.'}
326
+ '60060': InvalidOrder, # {'code': 60060, 'message': 'The order is already filled or canceled.'}
327
+ '600503': InvalidOrder, # {"code":600503,"message":"Notional is too small."}
328
+ # documented
329
+ '100001': BadRequest, # INVALID_HTTP_INPUT Http request is invalid
330
+ '100002': BadRequest, # DATA_NOT_AVAILABLE Some required data is missing
331
+ '100003': BadRequest, # KEY_CONFLICT The same key exists already
332
+ '100004': BadRequest, # INVALID_REQUEST_DATA The HTTP request contains invalid field or argument
333
+ '100005': BadRequest, # INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument
334
+ '100006': BadRequest, # INVALID_ARGUMENT The arugment is invalid
335
+ '100007': BadRequest, # ENCRYPTION_ERROR Something wrong with data encryption
336
+ '100008': BadSymbol, # SYMBOL_ERROR Symbol does not exist or not valid for the request
337
+ '100009': AuthenticationError, # AUTHORIZATION_NEEDED Authorization is require for the API access or request
338
+ '100010': BadRequest, # INVALID_OPERATION The action is invalid or not allowed for the account
339
+ '100011': BadRequest, # INVALID_TIMESTAMP Not a valid timestamp
340
+ '100012': BadRequest, # INVALID_STR_FORMAT str format does not
341
+ '100013': BadRequest, # INVALID_NUM_FORMAT Invalid number input
342
+ '100101': ExchangeError, # UNKNOWN_ERROR Some unknown error
343
+ '150001': BadRequest, # INVALID_JSON_FORMAT Require a valid json object
344
+ '200001': AuthenticationError, # AUTHENTICATION_FAILED Authorization failed
345
+ '200002': ExchangeError, # TOO_MANY_ATTEMPTS Tried and failed too many times
346
+ '200003': ExchangeError, # ACCOUNT_NOT_FOUND Account not exist
347
+ '200004': ExchangeError, # ACCOUNT_NOT_SETUP Account not setup properly
348
+ '200005': ExchangeError, # ACCOUNT_ALREADY_EXIST Account already exist
349
+ '200006': ExchangeError, # ACCOUNT_ERROR Some error related with error
350
+ '200007': ExchangeError, # CODE_NOT_FOUND
351
+ '200008': ExchangeError, # CODE_EXPIRED Code expired
352
+ '200009': ExchangeError, # CODE_MISMATCH Code does not match
353
+ '200010': AuthenticationError, # PASSWORD_ERROR Wrong assword
354
+ '200011': ExchangeError, # CODE_GEN_FAILED Do not generate required code promptly
355
+ '200012': ExchangeError, # FAKE_COKE_VERIFY
356
+ '200013': ExchangeError, # SECURITY_ALERT Provide security alert message
357
+ '200014': PermissionDenied, # RESTRICTED_ACCOUNT Account is restricted for certain activity, such, or withdraw.
358
+ '200015': PermissionDenied, # PERMISSION_DENIED No enough permission for the operation
359
+ '300001': InvalidOrder, # INVALID_PRICE Order price is invalid
360
+ '300002': InvalidOrder, # INVALID_QTY Order size is invalid
361
+ '300003': InvalidOrder, # INVALID_SIDE Order side is invalid
362
+ '300004': InvalidOrder, # INVALID_NOTIONAL Notional is too small or too large
363
+ '300005': InvalidOrder, # INVALID_TYPE Order typs is invalid
364
+ '300006': InvalidOrder, # INVALID_ORDER_ID Order id is invalid
365
+ '300007': InvalidOrder, # INVALID_TIME_IN_FORCE Time In Force in order request is invalid
366
+ '300008': InvalidOrder, # INVALID_ORDER_PARAMETER Some order parameter is invalid
367
+ '300009': InvalidOrder, # TRADING_VIOLATION Trading violation on account or asset
368
+ '300011': InsufficientFunds, # INVALID_BALANCE No enough account or asset balance for the trading
369
+ '300012': BadSymbol, # INVALID_PRODUCT Not a valid product supported by exchange
370
+ '300013': InvalidOrder, # INVALID_BATCH_ORDER Some or all orders are invalid in batch order request
371
+ '300014': InvalidOrder, # {"code":300014,"message":"Order price doesn't conform to the required tick size: 0.1","reason":"TICK_SIZE_VIOLATION"}
372
+ '300020': InvalidOrder, # TRADING_RESTRICTED There is some trading restriction on account or asset
373
+ '300021': AccountSuspended, # {"code":300021,"message":"Trading disabled for self account.","reason":"TRADING_DISABLED"}
374
+ '300031': InvalidOrder, # NO_MARKET_PRICE No market price for market type order trading
375
+ '310001': InsufficientFunds, # INVALID_MARGIN_BALANCE No enough margin balance
376
+ '310002': InvalidOrder, # INVALID_MARGIN_ACCOUNT Not a valid account for margin trading
377
+ '310003': InvalidOrder, # MARGIN_TOO_RISKY Leverage is too high
378
+ '310004': BadSymbol, # INVALID_MARGIN_ASSET This asset does not support margin trading
379
+ '310005': InvalidOrder, # INVALID_REFERENCE_PRICE There is no valid reference price
380
+ '510001': ExchangeError, # SERVER_ERROR Something wrong with server.
381
+ '900001': ExchangeError, # HUMAN_CHALLENGE Human change do not pass
382
+ },
383
+ 'broad': {},
384
+ },
385
+ 'commonCurrencies': {
386
+ 'BOND': 'BONDED',
387
+ 'BTCBEAR': 'BEAR',
388
+ 'BTCBULL': 'BULL',
389
+ 'BYN': 'BeyondFi',
390
+ 'PLN': 'Pollen',
391
+ },
392
+ })
393
+
394
+ def get_account(self, params={}):
395
+ # get current or provided bitmax sub-account
396
+ account = self.safe_value(params, 'account', self.options['account'])
397
+ lowercaseAccount = account.lower()
398
+ return self.capitalize(lowercaseAccount)
399
+
400
+ def fetch_currencies(self, params={}) -> Currencies:
401
+ """
402
+ fetches all available currencies on an exchange
403
+ :param dict [params]: extra parameters specific to the exchange API endpoint
404
+ :returns dict: an associative dictionary of currencies
405
+ """
406
+ assets = self.v1PublicGetAssets(params)
407
+ #
408
+ # {
409
+ # "code":0,
410
+ # "data":[
411
+ # {
412
+ # "assetCode" : "LTCBULL",
413
+ # "assetName" : "3X Long LTC Token",
414
+ # "precisionScale" : 9,
415
+ # "nativeScale" : 4,
416
+ # "withdrawalFee" : "0.2",
417
+ # "minWithdrawalAmt" : "1.0",
418
+ # "status" : "Normal"
419
+ # },
420
+ # ]
421
+ # }
422
+ #
423
+ margin = self.v1PublicGetMarginAssets(params)
424
+ #
425
+ # {
426
+ # "code":0,
427
+ # "data":[
428
+ # {
429
+ # "assetCode":"BTT",
430
+ # "borrowAssetCode":"BTT-B",
431
+ # "interestAssetCode":"BTT-I",
432
+ # "nativeScale":0,
433
+ # "numConfirmations":1,
434
+ # "withdrawFee":"100.0",
435
+ # "minWithdrawalAmt":"1000.0",
436
+ # "statusCode":"Normal",
437
+ # "statusMessage":"",
438
+ # "interestRate":"0.001"
439
+ # }
440
+ # ]
441
+ # }
442
+ #
443
+ cash = self.v1PublicGetCashAssets(params)
444
+ #
445
+ # {
446
+ # "code":0,
447
+ # "data":[
448
+ # {
449
+ # "assetCode":"LTCBULL",
450
+ # "nativeScale":4,
451
+ # "numConfirmations":20,
452
+ # "withdrawFee":"0.2",
453
+ # "minWithdrawalAmt":"1.0",
454
+ # "statusCode":"Normal",
455
+ # "statusMessage":""
456
+ # }
457
+ # ]
458
+ # }
459
+ #
460
+ assetsData = self.safe_value(assets, 'data', [])
461
+ marginData = self.safe_value(margin, 'data', [])
462
+ cashData = self.safe_value(cash, 'data', [])
463
+ assetsById = self.index_by(assetsData, 'assetCode')
464
+ marginById = self.index_by(marginData, 'assetCode')
465
+ cashById = self.index_by(cashData, 'assetCode')
466
+ dataById = self.deep_extend(assetsById, marginById, cashById)
467
+ ids = list(dataById.keys())
468
+ result: dict = {}
469
+ for i in range(0, len(ids)):
470
+ id = ids[i]
471
+ currency = dataById[id]
472
+ code = self.safe_currency_code(id)
473
+ scale = self.safe_string_2(currency, 'precisionScale', 'nativeScale')
474
+ precision = self.parse_number(self.parse_precision(scale))
475
+ fee = self.safe_number_2(currency, 'withdrawFee', 'withdrawalFee')
476
+ status = self.safe_string_2(currency, 'status', 'statusCode')
477
+ active = (status == 'Normal')
478
+ marginInside = ('borrowAssetCode' in currency)
479
+ result[code] = {
480
+ 'id': id,
481
+ 'code': code,
482
+ 'info': currency,
483
+ 'type': None,
484
+ 'margin': marginInside,
485
+ 'name': self.safe_string(currency, 'assetName'),
486
+ 'active': active,
487
+ 'deposit': None,
488
+ 'withdraw': None,
489
+ 'fee': fee,
490
+ 'precision': precision,
491
+ 'limits': {
492
+ 'amount': {
493
+ 'min': precision,
494
+ 'max': None,
495
+ },
496
+ 'withdraw': {
497
+ 'min': self.safe_number(currency, 'minWithdrawalAmt'),
498
+ 'max': None,
499
+ },
500
+ },
501
+ 'networks': {},
502
+ }
503
+ return result
504
+
505
+ def fetch_markets(self, params={}) -> List[Market]:
506
+ """
507
+ retrieves data on all markets for ascendex
508
+ :param dict [params]: extra parameters specific to the exchange API endpoint
509
+ :returns dict[]: an array of objects representing market data
510
+ """
511
+ products = self.v1PublicGetProducts(params)
512
+ #
513
+ # {
514
+ # "code": 0,
515
+ # "data": [
516
+ # {
517
+ # "symbol": "LBA/BTC",
518
+ # "baseAsset": "LBA",
519
+ # "quoteAsset": "BTC",
520
+ # "status": "Normal",
521
+ # "minNotional": "0.000625",
522
+ # "maxNotional": "6.25",
523
+ # "marginTradable": False,
524
+ # "commissionType": "Quote",
525
+ # "commissionReserveRate": "0.001",
526
+ # "tickSize": "0.000000001",
527
+ # "lotSize": "1"
528
+ # },
529
+ # ]
530
+ # }
531
+ #
532
+ cash = self.v1PublicGetCashProducts(params)
533
+ #
534
+ # {
535
+ # "code": 0,
536
+ # "data": [
537
+ # {
538
+ # "symbol": "QTUM/BTC",
539
+ # "displayName": "QTUM/BTC",
540
+ # "domain": "BTC",
541
+ # "tradingStartTime": 1569506400000,
542
+ # "collapseDecimals": "0.0001,0.000001,0.00000001",
543
+ # "minQty": "0.000000001",
544
+ # "maxQty": "1000000000",
545
+ # "minNotional": "0.000625",
546
+ # "maxNotional": "12.5",
547
+ # "statusCode": "Normal",
548
+ # "statusMessage": "",
549
+ # "tickSize": "0.00000001",
550
+ # "useTick": False,
551
+ # "lotSize": "0.1",
552
+ # "useLot": False,
553
+ # "commissionType": "Quote",
554
+ # "commissionReserveRate": "0.001",
555
+ # "qtyScale": 1,
556
+ # "priceScale": 8,
557
+ # "notionalScale": 4
558
+ # }
559
+ # ]
560
+ # }
561
+ #
562
+ perpetuals = self.v2PublicGetFuturesContract(params)
563
+ #
564
+ # {
565
+ # "code": 0,
566
+ # "data": [
567
+ # {
568
+ # "symbol": "BTC-PERP",
569
+ # "status": "Normal",
570
+ # "displayName": "BTCUSDT",
571
+ # "settlementAsset": "USDT",
572
+ # "underlying": "BTC/USDT",
573
+ # "tradingStartTime": 1579701600000,
574
+ # "priceFilter": {
575
+ # "minPrice": "1",
576
+ # "maxPrice": "1000000",
577
+ # "tickSize": "1"
578
+ # },
579
+ # "lotSizeFilter": {
580
+ # "minQty": "0.0001",
581
+ # "maxQty": "1000000000",
582
+ # "lotSize": "0.0001"
583
+ # },
584
+ # "commissionType": "Quote",
585
+ # "commissionReserveRate": "0.001",
586
+ # "marketOrderPriceMarkup": "0.03",
587
+ # "marginRequirements": [
588
+ # {
589
+ # "positionNotionalLowerBound": "0",
590
+ # "positionNotionalUpperBound": "50000",
591
+ # "initialMarginRate": "0.01",
592
+ # "maintenanceMarginRate": "0.006"
593
+ # },
594
+ # ...
595
+ # ]
596
+ # }
597
+ # ]
598
+ # }
599
+ #
600
+ productsData = self.safe_value(products, 'data', [])
601
+ productsById = self.index_by(productsData, 'symbol')
602
+ cashData = self.safe_value(cash, 'data', [])
603
+ perpetualsData = self.safe_value(perpetuals, 'data', [])
604
+ cashAndPerpetualsData = self.array_concat(cashData, perpetualsData)
605
+ cashAndPerpetualsById = self.index_by(cashAndPerpetualsData, 'symbol')
606
+ dataById = self.deep_extend(productsById, cashAndPerpetualsById)
607
+ ids = list(dataById.keys())
608
+ result = []
609
+ for i in range(0, len(ids)):
610
+ id = ids[i]
611
+ market = dataById[id]
612
+ settleId = self.safe_value(market, 'settlementAsset')
613
+ settle = self.safe_currency_code(settleId)
614
+ status = self.safe_string(market, 'status')
615
+ domain = self.safe_string(market, 'domain')
616
+ active = False
617
+ if ((status == 'Normal') or (status == 'InternalTrading')) and (domain != 'LeveragedETF'):
618
+ active = True
619
+ spot = settle is None
620
+ swap = not spot
621
+ linear = True if swap else None
622
+ minQty = self.safe_number(market, 'minQty')
623
+ maxQty = self.safe_number(market, 'maxQty')
624
+ minPrice = self.safe_number(market, 'tickSize')
625
+ maxPrice: Num = None
626
+ underlying = self.safe_string_2(market, 'underlying', 'symbol')
627
+ parts = underlying.split('/')
628
+ baseId = self.safe_string(parts, 0)
629
+ quoteId = self.safe_string(parts, 1)
630
+ base = self.safe_currency_code(baseId)
631
+ quote = self.safe_currency_code(quoteId)
632
+ symbol = base + '/' + quote
633
+ if swap:
634
+ lotSizeFilter = self.safe_value(market, 'lotSizeFilter')
635
+ minQty = self.safe_number(lotSizeFilter, 'minQty')
636
+ maxQty = self.safe_number(lotSizeFilter, 'maxQty')
637
+ priceFilter = self.safe_value(market, 'priceFilter')
638
+ minPrice = self.safe_number(priceFilter, 'minPrice')
639
+ maxPrice = self.safe_number(priceFilter, 'maxPrice')
640
+ symbol = base + '/' + quote + ':' + settle
641
+ fee = self.safe_number(market, 'commissionReserveRate')
642
+ marginTradable = self.safe_bool(market, 'marginTradable', False)
643
+ result.append({
644
+ 'id': id,
645
+ 'symbol': symbol,
646
+ 'base': base,
647
+ 'quote': quote,
648
+ 'settle': settle,
649
+ 'baseId': baseId,
650
+ 'quoteId': quoteId,
651
+ 'settleId': settleId,
652
+ 'type': 'swap' if swap else 'spot',
653
+ 'spot': spot,
654
+ 'margin': marginTradable if spot else None,
655
+ 'swap': swap,
656
+ 'future': False,
657
+ 'option': False,
658
+ 'active': active,
659
+ 'contract': swap,
660
+ 'linear': linear,
661
+ 'inverse': not linear if swap else None,
662
+ 'taker': fee,
663
+ 'maker': fee,
664
+ 'contractSize': self.parse_number('1') if swap else None,
665
+ 'expiry': None,
666
+ 'expiryDatetime': None,
667
+ 'strike': None,
668
+ 'optionType': None,
669
+ 'precision': {
670
+ 'amount': self.safe_number(market, 'lotSize'),
671
+ 'price': self.safe_number(market, 'tickSize'),
672
+ },
673
+ 'limits': {
674
+ 'leverage': {
675
+ 'min': None,
676
+ 'max': None,
677
+ },
678
+ 'amount': {
679
+ 'min': minQty,
680
+ 'max': maxQty,
681
+ },
682
+ 'price': {
683
+ 'min': minPrice,
684
+ 'max': maxPrice,
685
+ },
686
+ 'cost': {
687
+ 'min': self.safe_number(market, 'minNotional'),
688
+ 'max': self.safe_number(market, 'maxNotional'),
689
+ },
690
+ },
691
+ 'created': self.safe_integer(market, 'tradingStartTime'),
692
+ 'info': market,
693
+ })
694
+ return result
695
+
696
+ def fetch_time(self, params={}):
697
+ """
698
+ fetches the current integer timestamp in milliseconds from the ascendex server
699
+ :param dict [params]: extra parameters specific to the exchange API endpoint
700
+ :returns int: the current integer timestamp in milliseconds from the ascendex server
701
+ """
702
+ request: dict = {
703
+ 'requestTime': self.milliseconds(),
704
+ }
705
+ response = self.v1PublicGetExchangeInfo(self.extend(request, params))
706
+ #
707
+ # {
708
+ # "code": 0,
709
+ # "data": {
710
+ # "requestTimeEcho": 1656560463601,
711
+ # "requestReceiveAt": 1656560464331,
712
+ # "latency": 730
713
+ # }
714
+ # }
715
+ #
716
+ data = self.safe_value(response, 'data')
717
+ return self.safe_integer(data, 'requestReceiveAt')
718
+
719
+ def fetch_accounts(self, params={}) -> List[Account]:
720
+ """
721
+ fetch all the accounts associated with a profile
722
+ :param dict [params]: extra parameters specific to the exchange API endpoint
723
+ :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
724
+ """
725
+ accountGroup = self.safe_string(self.options, 'account-group')
726
+ response = None
727
+ if accountGroup is None:
728
+ response = self.v1PrivateGetInfo(params)
729
+ #
730
+ # {
731
+ # "code":0,
732
+ # "data":{
733
+ # "email":"igor.kroitor@gmail.com",
734
+ # "accountGroup":8,
735
+ # "viewPermission":true,
736
+ # "tradePermission":true,
737
+ # "transferPermission":true,
738
+ # "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"],
739
+ # "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"],
740
+ # "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"],
741
+ # "userUID":"U6491137460"
742
+ # }
743
+ # }
744
+ #
745
+ data = self.safe_value(response, 'data', {})
746
+ accountGroup = self.safe_string(data, 'accountGroup')
747
+ self.options['account-group'] = accountGroup
748
+ return [
749
+ {
750
+ 'id': accountGroup,
751
+ 'type': None,
752
+ 'code': None,
753
+ 'info': response,
754
+ },
755
+ ]
756
+
757
+ def parse_balance(self, response) -> Balances:
758
+ result: dict = {
759
+ 'info': response,
760
+ 'timestamp': None,
761
+ 'datetime': None,
762
+ }
763
+ balances = self.safe_value(response, 'data', [])
764
+ for i in range(0, len(balances)):
765
+ balance = balances[i]
766
+ code = self.safe_currency_code(self.safe_string(balance, 'asset'))
767
+ account = self.account()
768
+ account['free'] = self.safe_string(balance, 'availableBalance')
769
+ account['total'] = self.safe_string(balance, 'totalBalance')
770
+ result[code] = account
771
+ return self.safe_balance(result)
772
+
773
+ def parse_margin_balance(self, response):
774
+ result: dict = {
775
+ 'info': response,
776
+ 'timestamp': None,
777
+ 'datetime': None,
778
+ }
779
+ balances = self.safe_value(response, 'data', [])
780
+ for i in range(0, len(balances)):
781
+ balance = balances[i]
782
+ code = self.safe_currency_code(self.safe_string(balance, 'asset'))
783
+ account = self.account()
784
+ account['free'] = self.safe_string(balance, 'availableBalance')
785
+ account['total'] = self.safe_string(balance, 'totalBalance')
786
+ debt = self.safe_string(balance, 'borrowed')
787
+ interest = self.safe_string(balance, 'interest')
788
+ account['debt'] = Precise.string_add(debt, interest)
789
+ result[code] = account
790
+ return self.safe_balance(result)
791
+
792
+ def parse_swap_balance(self, response):
793
+ result: dict = {
794
+ 'info': response,
795
+ 'timestamp': None,
796
+ 'datetime': None,
797
+ }
798
+ data = self.safe_value(response, 'data', {})
799
+ collaterals = self.safe_value(data, 'collaterals', [])
800
+ for i in range(0, len(collaterals)):
801
+ balance = collaterals[i]
802
+ code = self.safe_currency_code(self.safe_string(balance, 'asset'))
803
+ account = self.account()
804
+ account['total'] = self.safe_string(balance, 'balance')
805
+ result[code] = account
806
+ return self.safe_balance(result)
807
+
808
+ def fetch_balance(self, params={}) -> Balances:
809
+ """
810
+ query for balance and get the amount of funds available for trading or funds locked in orders
811
+ :see: https://ascendex.github.io/ascendex-pro-api/#cash-account-balance
812
+ :see: https://ascendex.github.io/ascendex-pro-api/#margin-account-balance
813
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
814
+ :param dict [params]: extra parameters specific to the exchange API endpoint
815
+ :param str [params.type]: wallet type, 'spot', 'margin', or 'swap'
816
+ :param str [params.marginMode]: 'cross' or None, for spot margin trading, value of 'isolated' is invalid
817
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
818
+ """
819
+ self.load_markets()
820
+ self.load_accounts()
821
+ marketType = None
822
+ marginMode = None
823
+ marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
824
+ marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
825
+ isMargin = self.safe_bool(params, 'margin', False)
826
+ isCross = marginMode == 'cross'
827
+ marketType = 'margin' if (isMargin or isCross) else marketType
828
+ params = self.omit(params, 'margin')
829
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
830
+ accountCategory = self.safe_string(accountsByType, marketType, 'cash')
831
+ account = self.safe_value(self.accounts, 0, {})
832
+ accountGroup = self.safe_string(account, 'id')
833
+ request: dict = {
834
+ 'account-group': accountGroup,
835
+ }
836
+ if (marginMode == 'isolated') and (marketType != 'swap'):
837
+ raise BadRequest(self.id + ' does not supported isolated margin trading')
838
+ if (accountCategory == 'cash') or (accountCategory == 'margin'):
839
+ request['account-category'] = accountCategory
840
+ response = None
841
+ if (marketType == 'spot') or (marketType == 'margin'):
842
+ response = self.v1PrivateAccountCategoryGetBalance(self.extend(request, params))
843
+ elif marketType == 'swap':
844
+ response = self.v2PrivateAccountGroupGetFuturesPosition(self.extend(request, params))
845
+ else:
846
+ raise NotSupported(self.id + ' fetchBalance() is not currently supported for ' + marketType + ' markets')
847
+ #
848
+ # cash
849
+ #
850
+ # {
851
+ # "code": 0,
852
+ # "data": [
853
+ # {
854
+ # "asset": "BCHSV",
855
+ # "totalBalance": "64.298000048",
856
+ # "availableBalance": "64.298000048",
857
+ # },
858
+ # ]
859
+ # }
860
+ #
861
+ # margin
862
+ #
863
+ # {
864
+ # "code": 0,
865
+ # "data": [
866
+ # {
867
+ # "asset": "BCHSV",
868
+ # "totalBalance": "64.298000048",
869
+ # "availableBalance": "64.298000048",
870
+ # "borrowed": "0",
871
+ # "interest": "0",
872
+ # },
873
+ # ]
874
+ # }
875
+ #
876
+ # swap
877
+ #
878
+ # {
879
+ # "code": 0,
880
+ # "data": {
881
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
882
+ # "ac": "FUTURES",
883
+ # "collaterals": [
884
+ # {"asset":"ADA","balance":"0.355803","referencePrice":"1.05095","discountFactor":"0.9"},
885
+ # {"asset":"USDT","balance":"0.000014519","referencePrice":"1","discountFactor":"1"}
886
+ # ],
887
+ # }j
888
+ # }
889
+ #
890
+ if marketType == 'swap':
891
+ return self.parse_swap_balance(response)
892
+ elif marketType == 'margin':
893
+ return self.parse_margin_balance(response)
894
+ else:
895
+ return self.parse_balance(response)
896
+
897
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
898
+ """
899
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
900
+ :param str symbol: unified symbol of the market to fetch the order book for
901
+ :param int [limit]: the maximum amount of order book entries to return
902
+ :param dict [params]: extra parameters specific to the exchange API endpoint
903
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
904
+ """
905
+ self.load_markets()
906
+ market = self.market(symbol)
907
+ request: dict = {
908
+ 'symbol': market['id'],
909
+ }
910
+ response = self.v1PublicGetDepth(self.extend(request, params))
911
+ #
912
+ # {
913
+ # "code":0,
914
+ # "data":{
915
+ # "m":"depth-snapshot",
916
+ # "symbol":"BTC-PERP",
917
+ # "data":{
918
+ # "ts":1590223998202,
919
+ # "seqnum":115444921,
920
+ # "asks":[
921
+ # ["9207.5","18.2383"],
922
+ # ["9207.75","18.8235"],
923
+ # ["9208","10.7873"],
924
+ # ],
925
+ # "bids":[
926
+ # ["9207.25","0.4009"],
927
+ # ["9207","0.003"],
928
+ # ["9206.5","0.003"],
929
+ # ]
930
+ # }
931
+ # }
932
+ # }
933
+ #
934
+ data = self.safe_value(response, 'data', {})
935
+ orderbook = self.safe_value(data, 'data', {})
936
+ timestamp = self.safe_integer(orderbook, 'ts')
937
+ result = self.parse_order_book(orderbook, symbol, timestamp)
938
+ result['nonce'] = self.safe_integer(orderbook, 'seqnum')
939
+ return result
940
+
941
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
942
+ #
943
+ # {
944
+ # "symbol":"QTUM/BTC",
945
+ # "open":"0.00016537",
946
+ # "close":"0.00019077",
947
+ # "high":"0.000192",
948
+ # "low":"0.00016537",
949
+ # "volume":"846.6",
950
+ # "ask":["0.00018698","26.2"],
951
+ # "bid":["0.00018408","503.7"],
952
+ # "type":"spot"
953
+ # }
954
+ #
955
+ timestamp = None
956
+ marketId = self.safe_string(ticker, 'symbol')
957
+ type = self.safe_string(ticker, 'type')
958
+ delimiter = '/' if (type == 'spot') else None
959
+ symbol = self.safe_symbol(marketId, market, delimiter)
960
+ close = self.safe_string(ticker, 'close')
961
+ bid = self.safe_value(ticker, 'bid', [])
962
+ ask = self.safe_value(ticker, 'ask', [])
963
+ open = self.safe_string(ticker, 'open')
964
+ return self.safe_ticker({
965
+ 'symbol': symbol,
966
+ 'timestamp': timestamp,
967
+ 'datetime': None,
968
+ 'high': self.safe_string(ticker, 'high'),
969
+ 'low': self.safe_string(ticker, 'low'),
970
+ 'bid': self.safe_string(bid, 0),
971
+ 'bidVolume': self.safe_string(bid, 1),
972
+ 'ask': self.safe_string(ask, 0),
973
+ 'askVolume': self.safe_string(ask, 1),
974
+ 'vwap': None,
975
+ 'open': open,
976
+ 'close': close,
977
+ 'last': close,
978
+ 'previousClose': None, # previous day close
979
+ 'change': None,
980
+ 'percentage': None,
981
+ 'average': None,
982
+ 'baseVolume': self.safe_string(ticker, 'volume'),
983
+ 'quoteVolume': None,
984
+ 'info': ticker,
985
+ }, market)
986
+
987
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
988
+ """
989
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
990
+ :param str symbol: unified symbol of the market to fetch the ticker for
991
+ :param dict [params]: extra parameters specific to the exchange API endpoint
992
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
993
+ """
994
+ self.load_markets()
995
+ market = self.market(symbol)
996
+ request: dict = {
997
+ 'symbol': market['id'],
998
+ }
999
+ response = self.v1PublicGetTicker(self.extend(request, params))
1000
+ #
1001
+ # {
1002
+ # "code":0,
1003
+ # "data":{
1004
+ # "symbol":"BTC-PERP", # or "BTC/USDT"
1005
+ # "open":"9073",
1006
+ # "close":"9185.75",
1007
+ # "high":"9185.75",
1008
+ # "low":"9185.75",
1009
+ # "volume":"576.8334",
1010
+ # "ask":["9185.75","15.5863"],
1011
+ # "bid":["9185.5","0.003"],
1012
+ # "type":"derivatives", # or "spot"
1013
+ # }
1014
+ # }
1015
+ #
1016
+ data = self.safe_dict(response, 'data', {})
1017
+ return self.parse_ticker(data, market)
1018
+
1019
+ def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1020
+ """
1021
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1022
+ :see: https://ascendex.github.io/ascendex-pro-api/#ticker
1023
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#ticker
1024
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1025
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1026
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1027
+ """
1028
+ self.load_markets()
1029
+ request: dict = {}
1030
+ market = None
1031
+ if symbols is not None:
1032
+ symbol = self.safe_value(symbols, 0)
1033
+ market = self.market(symbol)
1034
+ marketIds = self.market_ids(symbols)
1035
+ request['symbol'] = ','.join(marketIds)
1036
+ type = None
1037
+ type, params = self.handle_market_type_and_params('fetchTickers', market, params)
1038
+ response = None
1039
+ if type == 'spot':
1040
+ response = self.v1PublicGetTicker(self.extend(request, params))
1041
+ else:
1042
+ response = self.v2PublicGetFuturesTicker(self.extend(request, params))
1043
+ #
1044
+ # {
1045
+ # "code":0,
1046
+ # "data":[
1047
+ # {
1048
+ # "symbol":"QTUM/BTC",
1049
+ # "open":"0.00016537",
1050
+ # "close":"0.00019077",
1051
+ # "high":"0.000192",
1052
+ # "low":"0.00016537",
1053
+ # "volume":"846.6",
1054
+ # "ask":["0.00018698","26.2"],
1055
+ # "bid":["0.00018408","503.7"],
1056
+ # "type":"spot"
1057
+ # }
1058
+ # ]
1059
+ # }
1060
+ #
1061
+ data = self.safe_value(response, 'data', [])
1062
+ if not isinstance(data, list):
1063
+ return self.parse_tickers([data], symbols)
1064
+ return self.parse_tickers(data, symbols)
1065
+
1066
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1067
+ #
1068
+ # {
1069
+ # "m":"bar",
1070
+ # "s":"BTC/USDT",
1071
+ # "data":{
1072
+ # "i":"1",
1073
+ # "ts":1590228000000,
1074
+ # "o":"9139.59",
1075
+ # "c":"9131.94",
1076
+ # "h":"9139.99",
1077
+ # "l":"9121.71",
1078
+ # "v":"25.20648"
1079
+ # }
1080
+ # }
1081
+ #
1082
+ data = self.safe_value(ohlcv, 'data', {})
1083
+ return [
1084
+ self.safe_integer(data, 'ts'),
1085
+ self.safe_number(data, 'o'),
1086
+ self.safe_number(data, 'h'),
1087
+ self.safe_number(data, 'l'),
1088
+ self.safe_number(data, 'c'),
1089
+ self.safe_number(data, 'v'),
1090
+ ]
1091
+
1092
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1093
+ """
1094
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1095
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1096
+ :param str timeframe: the length of time each candle represents
1097
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1098
+ :param int [limit]: the maximum amount of candles to fetch
1099
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1100
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1101
+ """
1102
+ self.load_markets()
1103
+ market = self.market(symbol)
1104
+ request: dict = {
1105
+ 'symbol': market['id'],
1106
+ 'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1107
+ }
1108
+ # if since and limit are not specified
1109
+ # the exchange will return just 1 last candle by default
1110
+ duration = self.parse_timeframe(timeframe)
1111
+ options = self.safe_value(self.options, 'fetchOHLCV', {})
1112
+ defaultLimit = self.safe_integer(options, 'limit', 500)
1113
+ if since is not None:
1114
+ request['from'] = since
1115
+ if limit is None:
1116
+ limit = defaultLimit
1117
+ else:
1118
+ limit = min(limit, defaultLimit)
1119
+ request['to'] = self.sum(since, limit * duration * 1000, 1)
1120
+ elif limit is not None:
1121
+ request['n'] = limit # max 500
1122
+ response = self.v1PublicGetBarhist(self.extend(request, params))
1123
+ #
1124
+ # {
1125
+ # "code":0,
1126
+ # "data":[
1127
+ # {
1128
+ # "m":"bar",
1129
+ # "s":"BTC/USDT",
1130
+ # "data":{
1131
+ # "i":"1",
1132
+ # "ts":1590228000000,
1133
+ # "o":"9139.59",
1134
+ # "c":"9131.94",
1135
+ # "h":"9139.99",
1136
+ # "l":"9121.71",
1137
+ # "v":"25.20648"
1138
+ # }
1139
+ # }
1140
+ # ]
1141
+ # }
1142
+ #
1143
+ data = self.safe_list(response, 'data', [])
1144
+ return self.parse_ohlcvs(data, market, timeframe, since, limit)
1145
+
1146
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1147
+ #
1148
+ # public fetchTrades
1149
+ #
1150
+ # {
1151
+ # "p":"9128.5", # price
1152
+ # "q":"0.0030", # quantity
1153
+ # "ts":1590229002385, # timestamp
1154
+ # "bm":false, # if True, the buyer is the market maker, we only use self field to "define the side" of a public trade
1155
+ # "seqnum":180143985289898554
1156
+ # }
1157
+ #
1158
+ timestamp = self.safe_integer(trade, 'ts')
1159
+ priceString = self.safe_string_2(trade, 'price', 'p')
1160
+ amountString = self.safe_string(trade, 'q')
1161
+ buyerIsMaker = self.safe_bool(trade, 'bm', False)
1162
+ side = 'sell' if buyerIsMaker else 'buy'
1163
+ market = self.safe_market(None, market)
1164
+ return self.safe_trade({
1165
+ 'info': trade,
1166
+ 'timestamp': timestamp,
1167
+ 'datetime': self.iso8601(timestamp),
1168
+ 'symbol': market['symbol'],
1169
+ 'id': None,
1170
+ 'order': None,
1171
+ 'type': None,
1172
+ 'takerOrMaker': None,
1173
+ 'side': side,
1174
+ 'price': priceString,
1175
+ 'amount': amountString,
1176
+ 'cost': None,
1177
+ 'fee': None,
1178
+ }, market)
1179
+
1180
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1181
+ """
1182
+ get the list of most recent trades for a particular symbol
1183
+ :see: https://ascendex.github.io/ascendex-pro-api/#market-trades
1184
+ :param str symbol: unified symbol of the market to fetch trades for
1185
+ :param int [since]: timestamp in ms of the earliest trade to fetch
1186
+ :param int [limit]: the maximum amount of trades to fetch
1187
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1188
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1189
+ """
1190
+ self.load_markets()
1191
+ market = self.market(symbol)
1192
+ request: dict = {
1193
+ 'symbol': market['id'],
1194
+ }
1195
+ if limit is not None:
1196
+ request['n'] = limit # max 100
1197
+ response = self.v1PublicGetTrades(self.extend(request, params))
1198
+ #
1199
+ # {
1200
+ # "code":0,
1201
+ # "data":{
1202
+ # "m":"trades",
1203
+ # "symbol":"BTC-PERP",
1204
+ # "data":[
1205
+ # {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554},
1206
+ # {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587},
1207
+ # {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043}
1208
+ # ]
1209
+ # }
1210
+ # }
1211
+ #
1212
+ records = self.safe_value(response, 'data', [])
1213
+ trades = self.safe_list(records, 'data', [])
1214
+ return self.parse_trades(trades, market, since, limit)
1215
+
1216
+ def parse_order_status(self, status: Str):
1217
+ statuses: dict = {
1218
+ 'PendingNew': 'open',
1219
+ 'New': 'open',
1220
+ 'PartiallyFilled': 'open',
1221
+ 'Filled': 'closed',
1222
+ 'Canceled': 'canceled',
1223
+ 'Rejected': 'rejected',
1224
+ }
1225
+ return self.safe_string(statuses, status, status)
1226
+
1227
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1228
+ #
1229
+ # createOrder
1230
+ #
1231
+ # {
1232
+ # "id": "16e607e2b83a8bXHbAwwoqDo55c166fa",
1233
+ # "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830",
1234
+ # "orderType": "Market",
1235
+ # "symbol": "BTC/USDT",
1236
+ # "timestamp": 1573576916201
1237
+ # }
1238
+ #
1239
+ # {
1240
+ # "ac": "FUTURES",
1241
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1242
+ # "time": 1640819389454,
1243
+ # "orderId": "a17e0874ecbdU0711043490bbtcpDU5X",
1244
+ # "seqNum": -1,
1245
+ # "orderType": "Limit",
1246
+ # "execInst": "NULL_VAL",
1247
+ # "side": "Buy",
1248
+ # "symbol": "BTC-PERP",
1249
+ # "price": "30000",
1250
+ # "orderQty": "0.002",
1251
+ # "stopPrice": "0",
1252
+ # "stopBy": "ref-px",
1253
+ # "status": "Ack",
1254
+ # "lastExecTime": 1640819389454,
1255
+ # "lastQty": "0",
1256
+ # "lastPx": "0",
1257
+ # "avgFilledPx": "0",
1258
+ # "cumFilledQty": "0",
1259
+ # "fee": "0",
1260
+ # "cumFee": "0",
1261
+ # "feeAsset": "",
1262
+ # "errorCode": "",
1263
+ # "posStopLossPrice": "0",
1264
+ # "posStopLossTrigger": "market",
1265
+ # "posTakeProfitPrice": "0",
1266
+ # "posTakeProfitTrigger": "market",
1267
+ # "liquidityInd": "n"
1268
+ # }
1269
+ #
1270
+ # fetchOrder, fetchOpenOrders, fetchClosedOrders
1271
+ #
1272
+ # {
1273
+ # "symbol": "BTC/USDT",
1274
+ # "price": "8131.22",
1275
+ # "orderQty": "0.00082",
1276
+ # "orderType": "Market",
1277
+ # "avgPx": "7392.02",
1278
+ # "cumFee": "0.005152238",
1279
+ # "cumFilledQty": "0.00082",
1280
+ # "errorCode": "",
1281
+ # "feeAsset": "USDT",
1282
+ # "lastExecTime": 1575953151764,
1283
+ # "orderId": "a16eee20b6750866943712zWEDdAjt3",
1284
+ # "seqNum": 2623469,
1285
+ # "side": "Buy",
1286
+ # "status": "Filled",
1287
+ # "stopPrice": "",
1288
+ # "execInst": "NULL_VAL" # "Post"(for postOnly orders), "reduceOnly"(for reduceOnly orders)
1289
+ # }
1290
+ #
1291
+ # {
1292
+ # "orderId": "a173ad938fc3U22666567717788c3b66", # orderId
1293
+ # "seqNum": 18777366360, # sequence number
1294
+ # "accountId": "cshwSjbpPjSwHmxPdz2CPQVU9mnbzPpt", # accountId
1295
+ # "symbol": "BTC/USDT", # symbol
1296
+ # "orderType": "Limit", # order type(Limit/Market/StopMarket/StopLimit)
1297
+ # "side": "Sell", # order side(Buy/Sell)
1298
+ # "price": "11346.77", # order price
1299
+ # "stopPrice": "0", # stop price(0 by default)
1300
+ # "orderQty": "0.01", # order quantity(in base asset)
1301
+ # "status": "Canceled", # order status(Filled/Canceled/Rejected)
1302
+ # "createTime": 1596344995793, # order creation time
1303
+ # "lastExecTime": 1596344996053, # last execution time
1304
+ # "avgFillPrice": "11346.77", # average filled price
1305
+ # "fillQty": "0.01", # filled quantity(in base asset)
1306
+ # "fee": "-0.004992579", # cummulative fee. if negative, self value is the commission charged; if possitive, self value is the rebate received.
1307
+ # "feeAsset": "USDT" # fee asset
1308
+ # }
1309
+ #
1310
+ # {
1311
+ # "ac": "FUTURES",
1312
+ # "accountId": "testabcdefg",
1313
+ # "avgPx": "0",
1314
+ # "cumFee": "0",
1315
+ # "cumQty": "0",
1316
+ # "errorCode": "NULL_VAL",
1317
+ # "execInst": "NULL_VAL",
1318
+ # "feeAsset": "USDT",
1319
+ # "lastExecTime": 1584072844085,
1320
+ # "orderId": "r170d21956dd5450276356bbtcpKa74",
1321
+ # "orderQty": "1.1499",
1322
+ # "orderType": "Limit",
1323
+ # "price": "4000",
1324
+ # "sendingTime": 1584072841033,
1325
+ # "seqNum": 24105338,
1326
+ # "side": "Buy",
1327
+ # "status": "Canceled",
1328
+ # "stopPrice": "",
1329
+ # "symbol": "BTC-PERP"
1330
+ # },
1331
+ #
1332
+ status = self.parse_order_status(self.safe_string(order, 'status'))
1333
+ marketId = self.safe_string(order, 'symbol')
1334
+ symbol = self.safe_symbol(marketId, market, '/')
1335
+ timestamp = self.safe_integer_2(order, 'timestamp', 'sendingTime')
1336
+ lastTradeTimestamp = self.safe_integer(order, 'lastExecTime')
1337
+ if timestamp is None:
1338
+ timestamp = lastTradeTimestamp
1339
+ price = self.safe_string(order, 'price')
1340
+ amount = self.safe_string(order, 'orderQty')
1341
+ average = self.safe_string(order, 'avgPx')
1342
+ filled = self.safe_string_n(order, ['cumFilledQty', 'cumQty', 'fillQty'])
1343
+ id = self.safe_string(order, 'orderId')
1344
+ clientOrderId = self.safe_string(order, 'id')
1345
+ if clientOrderId is not None:
1346
+ if len(clientOrderId) < 1:
1347
+ clientOrderId = None
1348
+ rawTypeLower = self.safe_string_lower(order, 'orderType')
1349
+ type = rawTypeLower
1350
+ if rawTypeLower is not None:
1351
+ if rawTypeLower == 'stoplimit':
1352
+ type = 'limit'
1353
+ if rawTypeLower == 'stopmarket':
1354
+ type = 'market'
1355
+ side = self.safe_string_lower(order, 'side')
1356
+ feeCost = self.safe_number_2(order, 'cumFee', 'fee')
1357
+ fee = None
1358
+ if feeCost is not None:
1359
+ feeCurrencyId = self.safe_string(order, 'feeAsset')
1360
+ feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
1361
+ fee = {
1362
+ 'cost': feeCost,
1363
+ 'currency': feeCurrencyCode,
1364
+ }
1365
+ stopPrice = self.omit_zero(self.safe_string(order, 'stopPrice'))
1366
+ reduceOnly = None
1367
+ execInst = self.safe_string(order, 'execInst')
1368
+ if execInst == 'reduceOnly':
1369
+ reduceOnly = True
1370
+ postOnly = None
1371
+ if execInst == 'Post':
1372
+ postOnly = True
1373
+ return self.safe_order({
1374
+ 'info': order,
1375
+ 'id': id,
1376
+ 'clientOrderId': clientOrderId,
1377
+ 'timestamp': timestamp,
1378
+ 'datetime': self.iso8601(timestamp),
1379
+ 'lastTradeTimestamp': lastTradeTimestamp,
1380
+ 'symbol': symbol,
1381
+ 'type': type,
1382
+ 'timeInForce': None,
1383
+ 'postOnly': postOnly,
1384
+ 'reduceOnly': reduceOnly,
1385
+ 'side': side,
1386
+ 'price': price,
1387
+ 'stopPrice': stopPrice,
1388
+ 'triggerPrice': stopPrice,
1389
+ 'amount': amount,
1390
+ 'cost': None,
1391
+ 'average': average,
1392
+ 'filled': filled,
1393
+ 'remaining': None,
1394
+ 'status': status,
1395
+ 'fee': fee,
1396
+ 'trades': None,
1397
+ }, market)
1398
+
1399
+ def fetch_trading_fees(self, params={}) -> TradingFees:
1400
+ """
1401
+ fetch the trading fees for multiple markets
1402
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1403
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1404
+ """
1405
+ self.load_markets()
1406
+ self.load_accounts()
1407
+ account = self.safe_value(self.accounts, 0, {})
1408
+ accountGroup = self.safe_string(account, 'id')
1409
+ request: dict = {
1410
+ 'account-group': accountGroup,
1411
+ }
1412
+ response = self.v1PrivateAccountGroupGetSpotFee(self.extend(request, params))
1413
+ #
1414
+ # {
1415
+ # "code": "0",
1416
+ # "data": {
1417
+ # "domain": "spot",
1418
+ # "userUID": "U1479576458",
1419
+ # "vipLevel": "0",
1420
+ # "fees": [
1421
+ # {symbol: 'HT/USDT', fee: {taker: '0.001', maker: "0.001"}},
1422
+ # {symbol: 'LAMB/BTC', fee: {taker: '0.002', maker: "0.002"}},
1423
+ # {symbol: 'STOS/USDT', fee: {taker: '0.002', maker: "0.002"}},
1424
+ # ...
1425
+ # ]
1426
+ # }
1427
+ # }
1428
+ #
1429
+ data = self.safe_value(response, 'data', {})
1430
+ fees = self.safe_value(data, 'fees', [])
1431
+ result: dict = {}
1432
+ for i in range(0, len(fees)):
1433
+ fee = fees[i]
1434
+ marketId = self.safe_string(fee, 'symbol')
1435
+ symbol = self.safe_symbol(marketId, None, '/')
1436
+ takerMaker = self.safe_value(fee, 'fee', {})
1437
+ result[symbol] = {
1438
+ 'info': fee,
1439
+ 'symbol': symbol,
1440
+ 'maker': self.safe_number(takerMaker, 'maker'),
1441
+ 'taker': self.safe_number(takerMaker, 'taker'),
1442
+ 'percentage': None,
1443
+ 'tierBased': None,
1444
+ }
1445
+ return result
1446
+
1447
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1448
+ """
1449
+ * @ignore
1450
+ helper function to build request
1451
+ :param str symbol: unified symbol of the market to create an order in
1452
+ :param str type: 'market' or 'limit'
1453
+ :param str side: 'buy' or 'sell'
1454
+ :param float amount: how much you want to trade in units of the base currency
1455
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1456
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1457
+ :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1458
+ :param bool [params.postOnly]: True or False
1459
+ :param float [params.stopPrice]: the price at which a trigger order is triggered at
1460
+ :returns dict: request to be sent to the exchange
1461
+ """
1462
+ market = self.market(symbol)
1463
+ marginMode = None
1464
+ marketType = None
1465
+ marginMode, params = self.handle_margin_mode_and_params('createOrderRequest', params)
1466
+ marketType, params = self.handle_market_type_and_params('createOrderRequest', market, params)
1467
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1468
+ accountCategory = self.safe_string(accountsByType, marketType, 'cash')
1469
+ if marginMode is not None:
1470
+ accountCategory = 'margin'
1471
+ account = self.safe_value(self.accounts, 0, {})
1472
+ accountGroup = self.safe_value(account, 'id')
1473
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'id')
1474
+ request: dict = {
1475
+ 'account-group': accountGroup,
1476
+ 'account-category': accountCategory,
1477
+ 'symbol': market['id'],
1478
+ 'time': self.milliseconds(),
1479
+ 'orderQty': self.amount_to_precision(symbol, amount),
1480
+ 'orderType': type, # limit, market, stop_market, stop_limit
1481
+ 'side': side, # buy or sell,
1482
+ # 'execInst': # Post for postOnly, ReduceOnly for reduceOnly
1483
+ # 'respInst': 'ACK', # ACK, 'ACCEPT, DONE
1484
+ }
1485
+ isMarketOrder = ((type == 'market') or (type == 'stop_market'))
1486
+ isLimitOrder = ((type == 'limit') or (type == 'stop_limit'))
1487
+ timeInForce = self.safe_string(params, 'timeInForce')
1488
+ postOnly = self.is_post_only(isMarketOrder, False, params)
1489
+ reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1490
+ stopPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
1491
+ if isLimitOrder:
1492
+ request['orderPrice'] = self.price_to_precision(symbol, price)
1493
+ if timeInForce == 'IOC':
1494
+ request['timeInForce'] = 'IOC'
1495
+ if timeInForce == 'FOK':
1496
+ request['timeInForce'] = 'FOK'
1497
+ if postOnly:
1498
+ request['postOnly'] = True
1499
+ if stopPrice is not None:
1500
+ request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
1501
+ if isLimitOrder:
1502
+ request['orderType'] = 'stop_limit'
1503
+ elif isMarketOrder:
1504
+ request['orderType'] = 'stop_market'
1505
+ if clientOrderId is not None:
1506
+ request['id'] = clientOrderId
1507
+ if market['spot']:
1508
+ if accountCategory is not None:
1509
+ request['category'] = accountCategory
1510
+ else:
1511
+ request['account-category'] = accountCategory
1512
+ if reduceOnly:
1513
+ request['execInst'] = 'ReduceOnly'
1514
+ if postOnly:
1515
+ request['execInst'] = 'Post'
1516
+ params = self.omit(params, ['reduceOnly', 'triggerPrice'])
1517
+ return self.extend(request, params)
1518
+
1519
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1520
+ """
1521
+ create a trade order on the exchange
1522
+ :see: https://ascendex.github.io/ascendex-pro-api/#place-order
1523
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#new-order
1524
+ :param str symbol: unified CCXT market symbol
1525
+ :param str type: "limit" or "market"
1526
+ :param str side: "buy" or "sell"
1527
+ :param float amount: the amount of currency to trade
1528
+ :param float [price]: *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
1529
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1530
+ :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1531
+ :param bool [params.postOnly]: True or False
1532
+ :param float [params.stopPrice]: the price at which a trigger order is triggered at
1533
+ :param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice that the attached take profit order will be triggered(perpetual swap markets only)
1534
+ :param float [params.takeProfit.triggerPrice]: *swap only* take profit trigger price
1535
+ :param dict [params.stopLoss]: *stopLoss object in params* containing the triggerPrice that the attached stop loss order will be triggered(perpetual swap markets only)
1536
+ :param float [params.stopLoss.triggerPrice]: *swap only* stop loss trigger price
1537
+ :returns: `An order structure <https://docs.ccxt.com/#/?id=order-structure>`
1538
+ """
1539
+ self.load_markets()
1540
+ self.load_accounts()
1541
+ market = self.market(symbol)
1542
+ request = self.create_order_request(symbol, type, side, amount, price, params)
1543
+ response = None
1544
+ if market['swap']:
1545
+ response = self.v2PrivateAccountGroupPostFuturesOrder(request)
1546
+ else:
1547
+ response = self.v1PrivateAccountCategoryPostOrder(request)
1548
+ #
1549
+ # spot
1550
+ #
1551
+ # {
1552
+ # "code":0,
1553
+ # "data": {
1554
+ # "accountId":"cshwT8RKojkT1HoaA5UdeimR2SrmHG2I",
1555
+ # "ac":"CASH",
1556
+ # "action":"place-order",
1557
+ # "status":"Ack",
1558
+ # "info": {
1559
+ # "symbol":"TRX/USDT",
1560
+ # "orderType":"StopLimit",
1561
+ # "timestamp":1654290662172,
1562
+ # "id":"",
1563
+ # "orderId":"a1812b6840ddU8191168955av0k6Eyhj"
1564
+ # }
1565
+ # }
1566
+ # }
1567
+ #
1568
+ # swap
1569
+ #
1570
+ # {
1571
+ # "code":0,
1572
+ # "data": {
1573
+ # "meta": {
1574
+ # "id":"",
1575
+ # "action":"place-order",
1576
+ # "respInst":"ACK"
1577
+ # },
1578
+ # "order": {
1579
+ # "ac":"FUTURES",
1580
+ # "accountId":"futwT8RKojkT1HoaA5UdeimR2SrmHG2I",
1581
+ # "time":1654290969965,
1582
+ # "orderId":"a1812b6cf322U8191168955oJamfTh7b",
1583
+ # "seqNum":-1,
1584
+ # "orderType":"StopLimit",
1585
+ # "execInst":"NULL_VAL",
1586
+ # "side":"Buy",
1587
+ # "symbol":"TRX-PERP",
1588
+ # "price":"0.083",
1589
+ # "orderQty":"1",
1590
+ # "stopPrice":"0.082",
1591
+ # "stopBy":"ref-px",
1592
+ # "status":"Ack",
1593
+ # "lastExecTime":1654290969965,
1594
+ # "lastQty":"0",
1595
+ # "lastPx":"0",
1596
+ # "avgFilledPx":"0",
1597
+ # "cumFilledQty":"0",
1598
+ # "fee":"0",
1599
+ # "cumFee":"0",
1600
+ # "feeAsset":"",
1601
+ # "errorCode":"",
1602
+ # "posStopLossPrice":"0",
1603
+ # "posStopLossTrigger":"market",
1604
+ # "posTakeProfitPrice":"0",
1605
+ # "posTakeProfitTrigger":"market",
1606
+ # "liquidityInd":"n"
1607
+ # }
1608
+ # }
1609
+ # }
1610
+ #
1611
+ data = self.safe_value(response, 'data', {})
1612
+ order = self.safe_value_2(data, 'order', 'info', {})
1613
+ return self.parse_order(order, market)
1614
+
1615
+ def create_orders(self, orders: List[OrderRequest], params={}):
1616
+ """
1617
+ create a list of trade orders
1618
+ :see: https://ascendex.github.io/ascendex-pro-api/#place-batch-orders
1619
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#place-batch-orders
1620
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1621
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1622
+ :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1623
+ :param bool [params.postOnly]: True or False
1624
+ :param float [params.stopPrice]: the price at which a trigger order is triggered at
1625
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1626
+ """
1627
+ self.load_markets()
1628
+ self.load_accounts()
1629
+ ordersRequests = []
1630
+ symbol = None
1631
+ marginMode = None
1632
+ for i in range(0, len(orders)):
1633
+ rawOrder = orders[i]
1634
+ marketId = self.safe_string(rawOrder, 'symbol')
1635
+ if symbol is None:
1636
+ symbol = marketId
1637
+ else:
1638
+ if symbol != marketId:
1639
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
1640
+ type = self.safe_string(rawOrder, 'type')
1641
+ side = self.safe_string(rawOrder, 'side')
1642
+ amount = self.safe_value(rawOrder, 'amount')
1643
+ price = self.safe_value(rawOrder, 'price')
1644
+ orderParams = self.safe_value(rawOrder, 'params', {})
1645
+ marginResult = self.handle_margin_mode_and_params('createOrders', orderParams)
1646
+ currentMarginMode = marginResult[0]
1647
+ if currentMarginMode is not None:
1648
+ if marginMode is None:
1649
+ marginMode = currentMarginMode
1650
+ else:
1651
+ if marginMode != currentMarginMode:
1652
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same margin mode(isolated or cross)')
1653
+ orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
1654
+ ordersRequests.append(orderRequest)
1655
+ market = self.market(symbol)
1656
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1657
+ accountCategory = self.safe_string(accountsByType, market['type'], 'cash')
1658
+ if marginMode is not None:
1659
+ accountCategory = 'margin'
1660
+ account = self.safe_value(self.accounts, 0, {})
1661
+ accountGroup = self.safe_value(account, 'id')
1662
+ request: dict = {}
1663
+ response = None
1664
+ if market['swap']:
1665
+ raise NotSupported(self.id + ' createOrders() is not currently supported for swap markets on ascendex')
1666
+ # request['account-group'] = accountGroup
1667
+ # request['category'] = accountCategory
1668
+ # request['orders'] = ordersRequests
1669
+ # response = self.v2PrivateAccountGroupPostFuturesOrderBatch(request)
1670
+ else:
1671
+ request['account-group'] = accountGroup
1672
+ request['account-category'] = accountCategory
1673
+ request['orders'] = ordersRequests
1674
+ response = self.v1PrivateAccountCategoryPostOrderBatch(request)
1675
+ #
1676
+ # spot
1677
+ #
1678
+ # {
1679
+ # "code": 0,
1680
+ # "data": {
1681
+ # "accountId": "cshdAKBO43TKIh2kJtq7FVVb42KIePyS",
1682
+ # "ac": "CASH",
1683
+ # "action": "batch-place-order",
1684
+ # "status": "Ack",
1685
+ # "info": [
1686
+ # {
1687
+ # "symbol": "BTC/USDT",
1688
+ # "orderType": "Limit",
1689
+ # "timestamp": 1699326589344,
1690
+ # "id": "",
1691
+ # "orderId": "a18ba7c1f6efU0711043490p3HvjjN5x"
1692
+ # }
1693
+ # ]
1694
+ # }
1695
+ # }
1696
+ #
1697
+ data = self.safe_value(response, 'data', {})
1698
+ info = self.safe_list(data, 'info', [])
1699
+ return self.parse_orders(info, market)
1700
+
1701
+ def fetch_order(self, id: str, symbol: Str = None, params={}):
1702
+ """
1703
+ fetches information on an order made by the user
1704
+ :see: https://ascendex.github.io/ascendex-pro-api/#query-order
1705
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#query-order-by-id
1706
+ :param str symbol: unified symbol of the market the order was made in
1707
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1708
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1709
+ """
1710
+ self.load_markets()
1711
+ self.load_accounts()
1712
+ market = None
1713
+ if symbol is not None:
1714
+ market = self.market(symbol)
1715
+ type, query = self.handle_market_type_and_params('fetchOrder', market, params)
1716
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1717
+ accountCategory = self.safe_string(accountsByType, type, 'cash')
1718
+ account = self.safe_value(self.accounts, 0, {})
1719
+ accountGroup = self.safe_value(account, 'id')
1720
+ request: dict = {
1721
+ 'account-group': accountGroup,
1722
+ 'account-category': accountCategory,
1723
+ 'orderId': id,
1724
+ }
1725
+ response = None
1726
+ if (type == 'spot') or (type == 'margin'):
1727
+ response = self.v1PrivateAccountCategoryGetOrderStatus(self.extend(request, query))
1728
+ elif type == 'swap':
1729
+ request['account-category'] = accountCategory
1730
+ response = self.v2PrivateAccountGroupGetFuturesOrderStatus(self.extend(request, query))
1731
+ else:
1732
+ raise NotSupported(self.id + ' fetchOrder() is not currently supported for ' + type + ' markets')
1733
+ #
1734
+ # AccountCategoryGetOrderStatus
1735
+ #
1736
+ # {
1737
+ # "code": 0,
1738
+ # "accountCategory": "CASH",
1739
+ # "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1740
+ # "data": [
1741
+ # {
1742
+ # "symbol": "BTC/USDT",
1743
+ # "price": "8131.22",
1744
+ # "orderQty": "0.00082",
1745
+ # "orderType": "Market",
1746
+ # "avgPx": "7392.02",
1747
+ # "cumFee": "0.005152238",
1748
+ # "cumFilledQty": "0.00082",
1749
+ # "errorCode": "",
1750
+ # "feeAsset": "USDT",
1751
+ # "lastExecTime": 1575953151764,
1752
+ # "orderId": "a16eee20b6750866943712zWEDdAjt3",
1753
+ # "seqNum": 2623469,
1754
+ # "side": "Buy",
1755
+ # "status": "Filled",
1756
+ # "stopPrice": "",
1757
+ # "execInst": "NULL_VAL"
1758
+ # }
1759
+ # ]
1760
+ # }
1761
+ #
1762
+ # AccountGroupGetFuturesOrderStatus
1763
+ #
1764
+ # {
1765
+ # "code": 0,
1766
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1767
+ # "ac": "FUTURES",
1768
+ # "data": {
1769
+ # "ac": "FUTURES",
1770
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1771
+ # "time": 1640247020217,
1772
+ # "orderId": "r17de65747aeU0711043490bbtcp0cmt",
1773
+ # "seqNum": 28796162908,
1774
+ # "orderType": "Limit",
1775
+ # "execInst": "NULL_VAL",
1776
+ # "side": "Buy",
1777
+ # "symbol": "BTC-PERP",
1778
+ # "price": "30000",
1779
+ # "orderQty": "0.0021",
1780
+ # "stopPrice": "0",
1781
+ # "stopBy": "market",
1782
+ # "status": "New",
1783
+ # "lastExecTime": 1640247020232,
1784
+ # "lastQty": "0",
1785
+ # "lastPx": "0",
1786
+ # "avgFilledPx": "0",
1787
+ # "cumFilledQty": "0",
1788
+ # "fee": "0",
1789
+ # "cumFee": "0",
1790
+ # "feeAsset": "USDT",
1791
+ # "errorCode": "",
1792
+ # "posStopLossPrice": "0",
1793
+ # "posStopLossTrigger": "market",
1794
+ # "posTakeProfitPrice": "0",
1795
+ # "posTakeProfitTrigger": "market",
1796
+ # "liquidityInd": "n"
1797
+ # }
1798
+ # }
1799
+ #
1800
+ data = self.safe_dict(response, 'data', {})
1801
+ return self.parse_order(data, market)
1802
+
1803
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1804
+ """
1805
+ fetch all unfilled currently open orders
1806
+ :see: https://ascendex.github.io/ascendex-pro-api/#list-open-orders
1807
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#list-open-orders
1808
+ :param str symbol: unified market symbol
1809
+ :param int [since]: the earliest time in ms to fetch open orders for
1810
+ :param int [limit]: the maximum number of open orders structures to retrieve
1811
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1812
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1813
+ """
1814
+ self.load_markets()
1815
+ self.load_accounts()
1816
+ market = None
1817
+ if symbol is not None:
1818
+ market = self.market(symbol)
1819
+ symbol = market['symbol']
1820
+ account = self.safe_value(self.accounts, 0, {})
1821
+ accountGroup = self.safe_value(account, 'id')
1822
+ type, query = self.handle_market_type_and_params('fetchOpenOrders', market, params)
1823
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1824
+ accountCategory = self.safe_string(accountsByType, type, 'cash')
1825
+ request: dict = {
1826
+ 'account-group': accountGroup,
1827
+ 'account-category': accountCategory,
1828
+ }
1829
+ response = None
1830
+ if (type == 'spot') or (type == 'margin'):
1831
+ response = self.v1PrivateAccountCategoryGetOrderOpen(self.extend(request, query))
1832
+ elif type == 'swap':
1833
+ request['account-category'] = accountCategory
1834
+ response = self.v2PrivateAccountGroupGetFuturesOrderOpen(self.extend(request, query))
1835
+ else:
1836
+ raise NotSupported(self.id + ' fetchOpenOrders() is not currently supported for ' + type + ' markets')
1837
+ #
1838
+ # AccountCategoryGetOrderOpen
1839
+ #
1840
+ # {
1841
+ # "ac": "CASH",
1842
+ # "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1843
+ # "code": 0,
1844
+ # "data": [
1845
+ # {
1846
+ # "avgPx": "0", # Average filled price of the order
1847
+ # "cumFee": "0", # cumulative fee paid for self order
1848
+ # "cumFilledQty": "0", # cumulative filled quantity
1849
+ # "errorCode": "", # error code; could be empty
1850
+ # "feeAsset": "USDT", # fee asset
1851
+ # "lastExecTime": 1576019723550, # The last execution time of the order
1852
+ # "orderId": "s16ef21882ea0866943712034f36d83", # server provided orderId
1853
+ # "orderQty": "0.0083", # order quantity
1854
+ # "orderType": "Limit", # order type
1855
+ # "price": "7105", # order price
1856
+ # "seqNum": 8193258, # sequence number
1857
+ # "side": "Buy", # order side
1858
+ # "status": "New", # order status on matching engine
1859
+ # "stopPrice": "", # only available for stop market and stop limit orders; otherwise empty
1860
+ # "symbol": "BTC/USDT",
1861
+ # "execInst": "NULL_VAL" # execution instruction
1862
+ # },
1863
+ # ]
1864
+ # }
1865
+ #
1866
+ # AccountGroupGetFuturesOrderOpen
1867
+ #
1868
+ # {
1869
+ # "code": 0,
1870
+ # "data": [
1871
+ # {
1872
+ # "ac": "FUTURES",
1873
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1874
+ # "time": 1640247020217,
1875
+ # "orderId": "r17de65747aeU0711043490bbtcp0cmt",
1876
+ # "seqNum": 28796162908,
1877
+ # "orderType": "Limit",
1878
+ # "execInst": "NULL_VAL",
1879
+ # "side": "Buy",
1880
+ # "symbol": "BTC-PERP",
1881
+ # "price": "30000",
1882
+ # "orderQty": "0.0021",
1883
+ # "stopPrice": "0",
1884
+ # "stopBy": "market",
1885
+ # "status": "New",
1886
+ # "lastExecTime": 1640247020232,
1887
+ # "lastQty": "0",
1888
+ # "lastPx": "0",
1889
+ # "avgFilledPx": "0",
1890
+ # "cumFilledQty": "0",
1891
+ # "fee": "0",
1892
+ # "cumFee": "0",
1893
+ # "feeAsset": "USDT",
1894
+ # "errorCode": "",
1895
+ # "posStopLossPrice": "0",
1896
+ # "posStopLossTrigger": "market",
1897
+ # "posTakeProfitPrice": "0",
1898
+ # "posTakeProfitTrigger": "market",
1899
+ # "liquidityInd": "n"
1900
+ # }
1901
+ # ]
1902
+ # }
1903
+ #
1904
+ data = self.safe_value(response, 'data', [])
1905
+ if accountCategory == 'futures':
1906
+ return self.parse_orders(data, market, since, limit)
1907
+ # a workaround for https://github.com/ccxt/ccxt/issues/7187
1908
+ orders = []
1909
+ for i in range(0, len(data)):
1910
+ order = self.parse_order(data[i], market)
1911
+ orders.append(order)
1912
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit)
1913
+
1914
+ def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1915
+ """
1916
+ fetches information on multiple closed orders made by the user
1917
+ :see: https://ascendex.github.io/ascendex-pro-api/#list-history-orders-v2
1918
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#list-current-history-orders
1919
+ :param str symbol: unified market symbol of the market orders were made in
1920
+ :param int [since]: the earliest time in ms to fetch orders for
1921
+ :param int [limit]: the maximum number of order structures to retrieve
1922
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1923
+ :param int [params.until]: the latest time in ms to fetch orders for
1924
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1925
+ """
1926
+ self.load_markets()
1927
+ self.load_accounts()
1928
+ account = self.safe_value(self.accounts, 0, {})
1929
+ accountGroup = self.safe_value(account, 'id')
1930
+ request: dict = {
1931
+ # 'category': accountCategory,
1932
+ # 'symbol': market['id'],
1933
+ # 'orderType': 'market', # optional, string
1934
+ # 'side': 'buy', # or 'sell', optional, case insensitive.
1935
+ # 'status': 'Filled', # "Filled", "Canceled", or "Rejected"
1936
+ # 'startTime': exchange.milliseconds(),
1937
+ # 'endTime': exchange.milliseconds(),
1938
+ # 'page': 1,
1939
+ # 'pageSize': 100,
1940
+ }
1941
+ market = None
1942
+ if symbol is not None:
1943
+ market = self.market(symbol)
1944
+ request['symbol'] = market['id']
1945
+ type, query = self.handle_market_type_and_params('fetchClosedOrders', market, params)
1946
+ options = self.safe_value(self.options, 'fetchClosedOrders', {})
1947
+ defaultMethod = self.safe_string(options, 'method', 'v2PrivateDataGetOrderHist')
1948
+ method = self.get_supported_mapping(type, {
1949
+ 'spot': defaultMethod,
1950
+ 'margin': defaultMethod,
1951
+ 'swap': 'v2PrivateAccountGroupGetFuturesOrderHistCurrent',
1952
+ })
1953
+ if since is not None:
1954
+ request['startTime'] = since
1955
+ until = self.safe_string(params, 'until')
1956
+ if until is not None:
1957
+ request['endTime'] = until
1958
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1959
+ accountCategory = self.safe_string(accountsByType, type, 'cash') # margin, futures
1960
+ response = None
1961
+ if method == 'v1PrivateAccountCategoryGetOrderHistCurrent':
1962
+ request['account-group'] = accountGroup
1963
+ request['account-category'] = accountCategory
1964
+ if limit is not None:
1965
+ request['limit'] = limit
1966
+ response = self.v1PrivateAccountCategoryGetOrderHistCurrent(self.extend(request, query))
1967
+ elif method == 'v2PrivateDataGetOrderHist':
1968
+ request['account'] = accountCategory
1969
+ if limit is not None:
1970
+ request['limit'] = limit
1971
+ response = self.v2PrivateDataGetOrderHist(self.extend(request, query))
1972
+ elif method == 'v2PrivateAccountGroupGetFuturesOrderHistCurrent':
1973
+ request['account-group'] = accountGroup
1974
+ request['account-category'] = accountCategory
1975
+ if limit is not None:
1976
+ request['pageSize'] = limit
1977
+ response = self.v2PrivateAccountGroupGetFuturesOrderHistCurrent(self.extend(request, query))
1978
+ else:
1979
+ raise NotSupported(self.id + ' fetchClosedOrders() is not currently supported for ' + type + ' markets')
1980
+ #
1981
+ # accountCategoryGetOrderHistCurrent
1982
+ #
1983
+ # {
1984
+ # "code":0,
1985
+ # "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda",
1986
+ # "ac":"CASH",
1987
+ # "data":[
1988
+ # {
1989
+ # "seqNum":15561826728,
1990
+ # "orderId":"a17294d305c0U6491137460bethu7kw9",
1991
+ # "symbol":"ETH/USDT",
1992
+ # "orderType":"Limit",
1993
+ # "lastExecTime":1591635618200,
1994
+ # "price":"200",
1995
+ # "orderQty":"0.1",
1996
+ # "side":"Buy",
1997
+ # "status":"Canceled",
1998
+ # "avgPx":"0",
1999
+ # "cumFilledQty":"0",
2000
+ # "stopPrice":"",
2001
+ # "errorCode":"",
2002
+ # "cumFee":"0",
2003
+ # "feeAsset":"USDT",
2004
+ # "execInst":"NULL_VAL"
2005
+ # }
2006
+ # ]
2007
+ # }
2008
+ #
2009
+ # {
2010
+ # "code": 0,
2011
+ # "data": [
2012
+ # {
2013
+ # "orderId" : "a173ad938fc3U22666567717788c3b66", # orderId
2014
+ # "seqNum" : 18777366360, # sequence number
2015
+ # "accountId" : "cshwSjbpPjSwHmxPdz2CPQVU9mnbzPpt", # accountId
2016
+ # "symbol" : "BTC/USDT", # symbol
2017
+ # "orderType" : "Limit", # order type(Limit/Market/StopMarket/StopLimit)
2018
+ # "side" : "Sell", # order side(Buy/Sell)
2019
+ # "price" : "11346.77", # order price
2020
+ # "stopPrice" : "0", # stop price(0 by default)
2021
+ # "orderQty" : "0.01", # order quantity(in base asset)
2022
+ # "status" : "Canceled", # order status(Filled/Canceled/Rejected)
2023
+ # "createTime" : 1596344995793, # order creation time
2024
+ # "lastExecTime": 1596344996053, # last execution time
2025
+ # "avgFillPrice": "11346.77", # average filled price
2026
+ # "fillQty" : "0.01", # filled quantity(in base asset)
2027
+ # "fee" : "-0.004992579", # cummulative fee. if negative, self value is the commission charged; if possitive, self value is the rebate received.
2028
+ # "feeAsset" : "USDT" # fee asset
2029
+ # }
2030
+ # ]
2031
+ # }
2032
+ #
2033
+ # accountGroupGetFuturesOrderHistCurrent
2034
+ #
2035
+ # {
2036
+ # "code": 0,
2037
+ # "data": [
2038
+ # {
2039
+ # "ac": "FUTURES",
2040
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2041
+ # "time": 1640245777002,
2042
+ # "orderId": "r17de6444fa6U0711043490bbtcpJ2lI",
2043
+ # "seqNum": 28796124902,
2044
+ # "orderType": "Limit",
2045
+ # "execInst": "NULL_VAL",
2046
+ # "side": "Buy",
2047
+ # "symbol": "BTC-PERP",
2048
+ # "price": "30000",
2049
+ # "orderQty": "0.0021",
2050
+ # "stopPrice": "0",
2051
+ # "stopBy": "market",
2052
+ # "status": "Canceled",
2053
+ # "lastExecTime": 1640246574886,
2054
+ # "lastQty": "0",
2055
+ # "lastPx": "0",
2056
+ # "avgFilledPx": "0",
2057
+ # "cumFilledQty": "0",
2058
+ # "fee": "0",
2059
+ # "cumFee": "0",
2060
+ # "feeAsset": "USDT",
2061
+ # "errorCode": "",
2062
+ # "posStopLossPrice": "0",
2063
+ # "posStopLossTrigger": "market",
2064
+ # "posTakeProfitPrice": "0",
2065
+ # "posTakeProfitTrigger": "market",
2066
+ # "liquidityInd": "n"
2067
+ # }
2068
+ # ]
2069
+ # }
2070
+ #
2071
+ data = self.safe_value(response, 'data')
2072
+ isArray = isinstance(data, list)
2073
+ if not isArray:
2074
+ data = self.safe_value(data, 'data', [])
2075
+ return self.parse_orders(data, market, since, limit)
2076
+
2077
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
2078
+ """
2079
+ cancels an open order
2080
+ :see: https://ascendex.github.io/ascendex-pro-api/#cancel-order
2081
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#cancel-order
2082
+ :param str id: order id
2083
+ :param str symbol: unified symbol of the market the order was made in
2084
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2085
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2086
+ """
2087
+ if symbol is None:
2088
+ raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
2089
+ self.load_markets()
2090
+ self.load_accounts()
2091
+ market = self.market(symbol)
2092
+ type, query = self.handle_market_type_and_params('cancelOrder', market, params)
2093
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
2094
+ accountCategory = self.safe_string(accountsByType, type, 'cash')
2095
+ account = self.safe_value(self.accounts, 0, {})
2096
+ accountGroup = self.safe_value(account, 'id')
2097
+ request: dict = {
2098
+ 'account-group': accountGroup,
2099
+ 'account-category': accountCategory,
2100
+ 'symbol': market['id'],
2101
+ 'time': self.milliseconds(),
2102
+ 'id': 'foobar',
2103
+ }
2104
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'id')
2105
+ if clientOrderId is None:
2106
+ request['orderId'] = id
2107
+ else:
2108
+ request['id'] = clientOrderId
2109
+ params = self.omit(params, ['clientOrderId', 'id'])
2110
+ response = None
2111
+ if (type == 'spot') or (type == 'margin'):
2112
+ response = self.v1PrivateAccountCategoryDeleteOrder(self.extend(request, query))
2113
+ elif type == 'swap':
2114
+ request['account-category'] = accountCategory
2115
+ response = self.v2PrivateAccountGroupDeleteFuturesOrder(self.extend(request, query))
2116
+ else:
2117
+ raise NotSupported(self.id + ' cancelOrder() is not currently supported for ' + type + ' markets')
2118
+ #
2119
+ # AccountCategoryDeleteOrder
2120
+ #
2121
+ # {
2122
+ # "code": 0,
2123
+ # "data": {
2124
+ # "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2125
+ # "ac": "CASH",
2126
+ # "action": "cancel-order",
2127
+ # "status": "Ack",
2128
+ # "info": {
2129
+ # "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23",
2130
+ # "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc",
2131
+ # "orderType": "", # could be empty
2132
+ # "symbol": "ETH/USDT",
2133
+ # "timestamp": 1573594877822
2134
+ # }
2135
+ # }
2136
+ # }
2137
+ #
2138
+ # AccountGroupDeleteFuturesOrder
2139
+ #
2140
+ # {
2141
+ # "code": 0,
2142
+ # "data": {
2143
+ # "meta": {
2144
+ # "id": "foobar",
2145
+ # "action": "cancel-order",
2146
+ # "respInst": "ACK"
2147
+ # },
2148
+ # "order": {
2149
+ # "ac": "FUTURES",
2150
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2151
+ # "time": 1640244480476,
2152
+ # "orderId": "r17de63086f4U0711043490bbtcpPUF4",
2153
+ # "seqNum": 28795959269,
2154
+ # "orderType": "Limit",
2155
+ # "execInst": "NULL_VAL",
2156
+ # "side": "Buy",
2157
+ # "symbol": "BTC-PERP",
2158
+ # "price": "30000",
2159
+ # "orderQty": "0.0021",
2160
+ # "stopPrice": "0",
2161
+ # "stopBy": "market",
2162
+ # "status": "New",
2163
+ # "lastExecTime": 1640244480491,
2164
+ # "lastQty": "0",
2165
+ # "lastPx": "0",
2166
+ # "avgFilledPx": "0",
2167
+ # "cumFilledQty": "0",
2168
+ # "fee": "0",
2169
+ # "cumFee": "0",
2170
+ # "feeAsset": "BTCPC",
2171
+ # "errorCode": "",
2172
+ # "posStopLossPrice": "0",
2173
+ # "posStopLossTrigger": "market",
2174
+ # "posTakeProfitPrice": "0",
2175
+ # "posTakeProfitTrigger": "market",
2176
+ # "liquidityInd": "n"
2177
+ # }
2178
+ # }
2179
+ # }
2180
+ #
2181
+ data = self.safe_value(response, 'data', {})
2182
+ order = self.safe_value_2(data, 'order', 'info', {})
2183
+ return self.parse_order(order, market)
2184
+
2185
+ def cancel_all_orders(self, symbol: Str = None, params={}):
2186
+ """
2187
+ cancel all open orders
2188
+ :see: https://ascendex.github.io/ascendex-pro-api/#cancel-all-orders
2189
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#cancel-all-open-orders
2190
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
2191
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2192
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2193
+ """
2194
+ self.load_markets()
2195
+ self.load_accounts()
2196
+ market = None
2197
+ if symbol is not None:
2198
+ market = self.market(symbol)
2199
+ type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
2200
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
2201
+ accountCategory = self.safe_string(accountsByType, type, 'cash')
2202
+ account = self.safe_value(self.accounts, 0, {})
2203
+ accountGroup = self.safe_value(account, 'id')
2204
+ request: dict = {
2205
+ 'account-group': accountGroup,
2206
+ 'account-category': accountCategory,
2207
+ 'time': self.milliseconds(),
2208
+ }
2209
+ if symbol is not None:
2210
+ request['symbol'] = market['id']
2211
+ response = None
2212
+ if (type == 'spot') or (type == 'margin'):
2213
+ response = self.v1PrivateAccountCategoryDeleteOrderAll(self.extend(request, query))
2214
+ elif type == 'swap':
2215
+ request['account-category'] = accountCategory
2216
+ response = self.v2PrivateAccountGroupDeleteFuturesOrderAll(self.extend(request, query))
2217
+ else:
2218
+ raise NotSupported(self.id + ' cancelAllOrders() is not currently supported for ' + type + ' markets')
2219
+ #
2220
+ # AccountCategoryDeleteOrderAll
2221
+ #
2222
+ # {
2223
+ # "code": 0,
2224
+ # "data": {
2225
+ # "ac": "CASH",
2226
+ # "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2227
+ # "action": "cancel-all",
2228
+ # "info": {
2229
+ # "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy",
2230
+ # "orderId": "",
2231
+ # "orderType": "NULL_VAL",
2232
+ # "symbol": "",
2233
+ # "timestamp": 1574118495462
2234
+ # },
2235
+ # "status": "Ack"
2236
+ # }
2237
+ # }
2238
+ #
2239
+ # AccountGroupDeleteFuturesOrderAll
2240
+ #
2241
+ # {
2242
+ # "code": 0,
2243
+ # "data": {
2244
+ # "ac": "FUTURES",
2245
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2246
+ # "action": "cancel-all",
2247
+ # "info": {
2248
+ # "symbol":"BTC-PERP"
2249
+ # }
2250
+ # }
2251
+ # }
2252
+ #
2253
+ return response
2254
+
2255
+ def parse_deposit_address(self, depositAddress, currency: Currency = None):
2256
+ #
2257
+ # {
2258
+ # "address": "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2259
+ # "destTag": "",
2260
+ # "tagType": "",
2261
+ # "tagId": "",
2262
+ # "chainName": "ERC20",
2263
+ # "numConfirmations": 20,
2264
+ # "withdrawalFee": 1,
2265
+ # "nativeScale": 4,
2266
+ # "tips": []
2267
+ # }
2268
+ #
2269
+ address = self.safe_string(depositAddress, 'address')
2270
+ tagId = self.safe_string(depositAddress, 'tagId')
2271
+ tag = self.safe_string(depositAddress, tagId)
2272
+ self.check_address(address)
2273
+ code = None if (currency is None) else currency['code']
2274
+ chainName = self.safe_string(depositAddress, 'blockchain')
2275
+ network = self.network_id_to_code(chainName, code)
2276
+ return {
2277
+ 'currency': code,
2278
+ 'address': address,
2279
+ 'tag': tag,
2280
+ 'network': network,
2281
+ 'info': depositAddress,
2282
+ }
2283
+
2284
+ def safe_network(self, networkId):
2285
+ networksById = self.safe_dict(self.options, 'networksById')
2286
+ return self.safe_string(networksById, networkId, networkId)
2287
+
2288
+ def fetch_deposit_address(self, code: str, params={}):
2289
+ """
2290
+ fetch the deposit address for a currency associated with self account
2291
+ :see: https://ascendex.github.io/ascendex-pro-api/#query-deposit-addresses
2292
+ :param str code: unified currency code
2293
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2294
+ :param str [params.network]: unified network code for deposit chain
2295
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2296
+ """
2297
+ self.load_markets()
2298
+ currency = self.currency(code)
2299
+ networkCode = self.safe_string_2(params, 'network', 'chainName')
2300
+ networkId = self.network_code_to_id(networkCode)
2301
+ params = self.omit(params, ['chainName'])
2302
+ request: dict = {
2303
+ 'asset': currency['id'],
2304
+ 'blockchain': networkId,
2305
+ }
2306
+ response = self.v1PrivateGetWalletDepositAddress(self.extend(request, params))
2307
+ #
2308
+ # {
2309
+ # "code":0,
2310
+ # "data":{
2311
+ # "asset":"USDT",
2312
+ # "assetName":"Tether",
2313
+ # "address":[
2314
+ # {
2315
+ # "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6",
2316
+ # "destTag":"",
2317
+ # "tagType":"",
2318
+ # "tagId":"",
2319
+ # "chainName":"Omni",
2320
+ # "numConfirmations":3,
2321
+ # "withdrawalFee":4.7,
2322
+ # "nativeScale":4,
2323
+ # "tips":[]
2324
+ # },
2325
+ # {
2326
+ # "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2327
+ # "destTag":"",
2328
+ # "tagType":"",
2329
+ # "tagId":"",
2330
+ # "chainName":"ERC20",
2331
+ # "numConfirmations":20,
2332
+ # "withdrawalFee":1.0,
2333
+ # "nativeScale":4,
2334
+ # "tips":[]
2335
+ # }
2336
+ # ]
2337
+ # }
2338
+ # }
2339
+ #
2340
+ data = self.safe_dict(response, 'data', {})
2341
+ addresses = self.safe_list(data, 'address', [])
2342
+ numAddresses = len(addresses)
2343
+ address = None
2344
+ if numAddresses > 1:
2345
+ addressesByChainName = self.index_by(addresses, 'chainName')
2346
+ if networkId is None:
2347
+ chainNames = list(addressesByChainName.keys())
2348
+ chains = ', '.join(chainNames)
2349
+ raise ArgumentsRequired(self.id + ' fetchDepositAddress() returned more than one address, a chainName parameter is required, one of ' + chains)
2350
+ address = self.safe_dict(addressesByChainName, networkId, {})
2351
+ else:
2352
+ # first address
2353
+ address = self.safe_dict(addresses, 0, {})
2354
+ result = self.parse_deposit_address(address, currency)
2355
+ return self.extend(result, {
2356
+ 'info': response,
2357
+ })
2358
+
2359
+ def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2360
+ """
2361
+ fetch all deposits made to an account
2362
+ :param str code: unified currency code
2363
+ :param int [since]: the earliest time in ms to fetch deposits for
2364
+ :param int [limit]: the maximum number of deposits structures to retrieve
2365
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2366
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2367
+ """
2368
+ request: dict = {
2369
+ 'txType': 'deposit',
2370
+ }
2371
+ return self.fetch_transactions(code, since, limit, self.extend(request, params))
2372
+
2373
+ def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2374
+ """
2375
+ fetch all withdrawals made from an account
2376
+ :param str code: unified currency code
2377
+ :param int [since]: the earliest time in ms to fetch withdrawals for
2378
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
2379
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2380
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2381
+ """
2382
+ request: dict = {
2383
+ 'txType': 'withdrawal',
2384
+ }
2385
+ return self.fetch_transactions(code, since, limit, self.extend(request, params))
2386
+
2387
+ def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2388
+ """
2389
+ fetch history of deposits and withdrawals
2390
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2391
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2392
+ :param int [limit]: max number of deposit/withdrawals to return, default is None
2393
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2394
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2395
+ """
2396
+ self.load_markets()
2397
+ request: dict = {
2398
+ # 'asset': currency['id'],
2399
+ # 'page': 1,
2400
+ # 'pageSize': 20,
2401
+ # 'startTs': self.milliseconds(),
2402
+ # 'endTs': self.milliseconds(),
2403
+ # 'txType': undefned, # deposit, withdrawal
2404
+ }
2405
+ currency = None
2406
+ if code is not None:
2407
+ currency = self.currency(code)
2408
+ request['asset'] = currency['id']
2409
+ if since is not None:
2410
+ request['startTs'] = since
2411
+ if limit is not None:
2412
+ request['pageSize'] = limit
2413
+ response = self.v1PrivateGetWalletTransactions(self.extend(request, params))
2414
+ #
2415
+ # {
2416
+ # "code": 0,
2417
+ # "data": {
2418
+ # "data": [
2419
+ # {
2420
+ # "requestId": "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2421
+ # "time": 1591606166000,
2422
+ # "asset": "USDT",
2423
+ # "transactionType": "deposit",
2424
+ # "amount": "25",
2425
+ # "commission": "0",
2426
+ # "networkTransactionId": "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2427
+ # "status": "pending",
2428
+ # "numConfirmed": 8,
2429
+ # "numConfirmations": 20,
2430
+ # "destAddress": {address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722"}
2431
+ # }
2432
+ # ],
2433
+ # "page": 1,
2434
+ # "pageSize": 20,
2435
+ # "hasNext": False
2436
+ # }
2437
+ # }
2438
+ #
2439
+ data = self.safe_value(response, 'data', {})
2440
+ transactions = self.safe_list(data, 'data', [])
2441
+ return self.parse_transactions(transactions, currency, since, limit)
2442
+
2443
+ def parse_transaction_status(self, status: Str):
2444
+ statuses: dict = {
2445
+ 'reviewing': 'pending',
2446
+ 'pending': 'pending',
2447
+ 'confirmed': 'ok',
2448
+ 'rejected': 'rejected',
2449
+ }
2450
+ return self.safe_string(statuses, status, status)
2451
+
2452
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2453
+ #
2454
+ # {
2455
+ # "requestId": "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2456
+ # "time": 1591606166000,
2457
+ # "asset": "USDT",
2458
+ # "transactionType": "deposit",
2459
+ # "amount": "25",
2460
+ # "commission": "0",
2461
+ # "networkTransactionId": "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2462
+ # "status": "pending",
2463
+ # "numConfirmed": 8,
2464
+ # "numConfirmations": 20,
2465
+ # "destAddress": {
2466
+ # "address": "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2467
+ # "destTag": "..." # for currencies that have it
2468
+ # }
2469
+ # }
2470
+ #
2471
+ destAddress = self.safe_value(transaction, 'destAddress', {})
2472
+ address = self.safe_string(destAddress, 'address')
2473
+ tag = self.safe_string(destAddress, 'destTag')
2474
+ timestamp = self.safe_integer(transaction, 'time')
2475
+ currencyId = self.safe_string(transaction, 'asset')
2476
+ amountString = self.safe_string(transaction, 'amount')
2477
+ feeCostString = self.safe_string(transaction, 'commission')
2478
+ amountString = Precise.string_sub(amountString, feeCostString)
2479
+ code = self.safe_currency_code(currencyId, currency)
2480
+ return {
2481
+ 'info': transaction,
2482
+ 'id': self.safe_string(transaction, 'requestId'),
2483
+ 'txid': self.safe_string(transaction, 'networkTransactionId'),
2484
+ 'type': self.safe_string(transaction, 'transactionType'),
2485
+ 'currency': code,
2486
+ 'network': None,
2487
+ 'amount': self.parse_number(amountString),
2488
+ 'status': self.parse_transaction_status(self.safe_string(transaction, 'status')),
2489
+ 'timestamp': timestamp,
2490
+ 'datetime': self.iso8601(timestamp),
2491
+ 'address': address,
2492
+ 'addressFrom': None,
2493
+ 'addressTo': address,
2494
+ 'tag': tag,
2495
+ 'tagFrom': None,
2496
+ 'tagTo': tag,
2497
+ 'updated': None,
2498
+ 'comment': None,
2499
+ 'fee': {
2500
+ 'currency': code,
2501
+ 'cost': self.parse_number(feeCostString),
2502
+ 'rate': None,
2503
+ },
2504
+ 'internal': False,
2505
+ }
2506
+
2507
+ def fetch_positions(self, symbols: Strings = None, params={}):
2508
+ """
2509
+ fetch all open positions
2510
+ :param str[]|None symbols: list of unified market symbols
2511
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2512
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2513
+ """
2514
+ self.load_markets()
2515
+ self.load_accounts()
2516
+ account = self.safe_value(self.accounts, 0, {})
2517
+ accountGroup = self.safe_string(account, 'id')
2518
+ request: dict = {
2519
+ 'account-group': accountGroup,
2520
+ }
2521
+ response = self.v2PrivateAccountGroupGetFuturesPosition(self.extend(request, params))
2522
+ #
2523
+ # {
2524
+ # "code": 0,
2525
+ # "data": {
2526
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2527
+ # "ac": "FUTURES",
2528
+ # "collaterals": [
2529
+ # {
2530
+ # "asset": "USDT",
2531
+ # "balance": "44.570287262",
2532
+ # "referencePrice": "1",
2533
+ # "discountFactor": "1"
2534
+ # }
2535
+ # ],
2536
+ # "contracts": [
2537
+ # {
2538
+ # "symbol": "BTC-PERP",
2539
+ # "side": "LONG",
2540
+ # "position": "0.0001",
2541
+ # "referenceCost": "-3.12277254",
2542
+ # "unrealizedPnl": "-0.001700233",
2543
+ # "realizedPnl": "0",
2544
+ # "avgOpenPrice": "31209",
2545
+ # "marginType": "isolated",
2546
+ # "isolatedMargin": "1.654972977",
2547
+ # "leverage": "2",
2548
+ # "takeProfitPrice": "0",
2549
+ # "takeProfitTrigger": "market",
2550
+ # "stopLossPrice": "0",
2551
+ # "stopLossTrigger": "market",
2552
+ # "buyOpenOrderNotional": "0",
2553
+ # "sellOpenOrderNotional": "0",
2554
+ # "markPrice": "31210.723063672",
2555
+ # "indexPrice": "31223.148857925"
2556
+ # },
2557
+ # ]
2558
+ # }
2559
+ # }
2560
+ #
2561
+ data = self.safe_value(response, 'data', {})
2562
+ position = self.safe_value(data, 'contracts', [])
2563
+ result = []
2564
+ for i in range(0, len(position)):
2565
+ result.append(self.parse_position(position[i]))
2566
+ symbols = self.market_symbols(symbols)
2567
+ return self.filter_by_array_positions(result, 'symbol', symbols, False)
2568
+
2569
+ def parse_position(self, position: dict, market: Market = None):
2570
+ #
2571
+ # {
2572
+ # "symbol": "BTC-PERP",
2573
+ # "side": "LONG",
2574
+ # "position": "0.0001",
2575
+ # "referenceCost": "-3.12277254",
2576
+ # "unrealizedPnl": "-0.001700233",
2577
+ # "realizedPnl": "0",
2578
+ # "avgOpenPrice": "31209",
2579
+ # "marginType": "isolated",
2580
+ # "isolatedMargin": "1.654972977",
2581
+ # "leverage": "2",
2582
+ # "takeProfitPrice": "0",
2583
+ # "takeProfitTrigger": "market",
2584
+ # "stopLossPrice": "0",
2585
+ # "stopLossTrigger": "market",
2586
+ # "buyOpenOrderNotional": "0",
2587
+ # "sellOpenOrderNotional": "0",
2588
+ # "markPrice": "31210.723063672",
2589
+ # "indexPrice": "31223.148857925"
2590
+ # },
2591
+ #
2592
+ marketId = self.safe_string(position, 'symbol')
2593
+ market = self.safe_market(marketId, market)
2594
+ notional = self.safe_string(position, 'buyOpenOrderNotional')
2595
+ if Precise.string_eq(notional, '0'):
2596
+ notional = self.safe_string(position, 'sellOpenOrderNotional')
2597
+ marginType = self.safe_string(position, 'marginType')
2598
+ marginMode = 'cross' if (marginType == 'crossed') else 'isolated'
2599
+ collateral = None
2600
+ if marginMode == 'isolated':
2601
+ collateral = self.safe_string(position, 'isolatedMargin')
2602
+ return self.safe_position({
2603
+ 'info': position,
2604
+ 'id': None,
2605
+ 'symbol': market['symbol'],
2606
+ 'notional': self.parse_number(notional),
2607
+ 'marginMode': marginMode,
2608
+ 'liquidationPrice': None,
2609
+ 'entryPrice': self.safe_number(position, 'avgOpenPrice'),
2610
+ 'unrealizedPnl': self.safe_number(position, 'unrealizedPnl'),
2611
+ 'percentage': None,
2612
+ 'contracts': self.safe_number(position, 'position'),
2613
+ 'contractSize': self.safe_number(market, 'contractSize'),
2614
+ 'markPrice': self.safe_number(position, 'markPrice'),
2615
+ 'lastPrice': None,
2616
+ 'side': self.safe_string_lower(position, 'side'),
2617
+ 'hedged': None,
2618
+ 'timestamp': None,
2619
+ 'datetime': None,
2620
+ 'lastUpdateTimestamp': None,
2621
+ 'maintenanceMargin': None,
2622
+ 'maintenanceMarginPercentage': None,
2623
+ 'collateral': collateral,
2624
+ 'initialMargin': None,
2625
+ 'initialMarginPercentage': None,
2626
+ 'leverage': self.safe_integer(position, 'leverage'),
2627
+ 'marginRatio': None,
2628
+ 'stopLossPrice': self.safe_number(position, 'stopLossPrice'),
2629
+ 'takeProfitPrice': self.safe_number(position, 'takeProfitPrice'),
2630
+ })
2631
+
2632
+ def parse_funding_rate(self, contract, market: Market = None):
2633
+ #
2634
+ # {
2635
+ # "time": 1640061364830,
2636
+ # "symbol": "EOS-PERP",
2637
+ # "markPrice": "3.353854865",
2638
+ # "indexPrice": "3.3542",
2639
+ # "openInterest": "14242",
2640
+ # "fundingRate": "-0.000073026",
2641
+ # "nextFundingTime": 1640073600000
2642
+ # }
2643
+ #
2644
+ marketId = self.safe_string(contract, 'symbol')
2645
+ symbol = self.safe_symbol(marketId, market)
2646
+ currentTime = self.safe_integer(contract, 'time')
2647
+ nextFundingRate = self.safe_number(contract, 'fundingRate')
2648
+ nextFundingRateTimestamp = self.safe_integer(contract, 'nextFundingTime')
2649
+ return {
2650
+ 'info': contract,
2651
+ 'symbol': symbol,
2652
+ 'markPrice': self.safe_number(contract, 'markPrice'),
2653
+ 'indexPrice': self.safe_number(contract, 'indexPrice'),
2654
+ 'interestRate': self.parse_number('0'),
2655
+ 'estimatedSettlePrice': None,
2656
+ 'timestamp': currentTime,
2657
+ 'datetime': self.iso8601(currentTime),
2658
+ 'previousFundingRate': None,
2659
+ 'nextFundingRate': None,
2660
+ 'previousFundingTimestamp': None,
2661
+ 'nextFundingTimestamp': None,
2662
+ 'previousFundingDatetime': None,
2663
+ 'nextFundingDatetime': None,
2664
+ 'fundingRate': nextFundingRate,
2665
+ 'fundingTimestamp': nextFundingRateTimestamp,
2666
+ 'fundingDatetime': self.iso8601(nextFundingRateTimestamp),
2667
+ }
2668
+
2669
+ def fetch_funding_rates(self, symbols: Strings = None, params={}):
2670
+ """
2671
+ fetch the funding rate for multiple markets
2672
+ :param str[]|None symbols: list of unified market symbols
2673
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2674
+ :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
2675
+ """
2676
+ self.load_markets()
2677
+ symbols = self.market_symbols(symbols)
2678
+ response = self.v2PublicGetFuturesPricingData(params)
2679
+ #
2680
+ # {
2681
+ # "code": 0,
2682
+ # "data": {
2683
+ # "contracts": [
2684
+ # {
2685
+ # "time": 1640061364830,
2686
+ # "symbol": "EOS-PERP",
2687
+ # "markPrice": "3.353854865",
2688
+ # "indexPrice": "3.3542",
2689
+ # "openInterest": "14242",
2690
+ # "fundingRate": "-0.000073026",
2691
+ # "nextFundingTime": 1640073600000
2692
+ # },
2693
+ # ],
2694
+ # "collaterals": [
2695
+ # {
2696
+ # "asset": "USDTR",
2697
+ # "referencePrice": "1"
2698
+ # },
2699
+ # ]
2700
+ # }
2701
+ # }
2702
+ #
2703
+ data = self.safe_value(response, 'data', {})
2704
+ contracts = self.safe_value(data, 'contracts', [])
2705
+ result = self.parse_funding_rates(contracts)
2706
+ return self.filter_by_array(result, 'symbol', symbols)
2707
+
2708
+ def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2709
+ self.load_markets()
2710
+ self.load_accounts()
2711
+ market = self.market(symbol)
2712
+ account = self.safe_value(self.accounts, 0, {})
2713
+ accountGroup = self.safe_string(account, 'id')
2714
+ amount = self.amount_to_precision(symbol, amount)
2715
+ request: dict = {
2716
+ 'account-group': accountGroup,
2717
+ 'symbol': market['id'],
2718
+ 'amount': amount, # positive value for adding margin, negative for reducing
2719
+ }
2720
+ response = self.v2PrivateAccountGroupPostFuturesIsolatedPositionMargin(self.extend(request, params))
2721
+ #
2722
+ # Can only change margin for perpetual futures isolated margin positions
2723
+ #
2724
+ # {
2725
+ # "code": 0
2726
+ # }
2727
+ #
2728
+ if type == 'reduce':
2729
+ amount = Precise.string_abs(amount)
2730
+ return self.extend(self.parse_margin_modification(response, market), {
2731
+ 'amount': self.parse_number(amount),
2732
+ 'type': type,
2733
+ })
2734
+
2735
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
2736
+ #
2737
+ # addMargin/reduceMargin
2738
+ #
2739
+ # {
2740
+ # "code": 0
2741
+ # }
2742
+ #
2743
+ errorCode = self.safe_string(data, 'code')
2744
+ status = 'ok' if (errorCode == '0') else 'failed'
2745
+ return {
2746
+ 'info': data,
2747
+ 'symbol': market['symbol'],
2748
+ 'type': None,
2749
+ 'marginMode': 'isolated',
2750
+ 'amount': None,
2751
+ 'total': None,
2752
+ 'code': market['quote'],
2753
+ 'status': status,
2754
+ 'timestamp': None,
2755
+ 'datetime': None,
2756
+ }
2757
+
2758
+ def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2759
+ """
2760
+ remove margin from a position
2761
+ :param str symbol: unified market symbol
2762
+ :param float amount: the amount of margin to remove
2763
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2764
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
2765
+ """
2766
+ return self.modify_margin_helper(symbol, -amount, 'reduce', params)
2767
+
2768
+ def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2769
+ """
2770
+ add margin
2771
+ :param str symbol: unified market symbol
2772
+ :param float amount: amount of margin to add
2773
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2774
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
2775
+ """
2776
+ return self.modify_margin_helper(symbol, amount, 'add', params)
2777
+
2778
+ def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2779
+ """
2780
+ set the level of leverage for a market
2781
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#change-contract-leverage
2782
+ :param float leverage: the rate of leverage
2783
+ :param str symbol: unified market symbol
2784
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2785
+ :returns dict: response from the exchange
2786
+ """
2787
+ if symbol is None:
2788
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
2789
+ if (leverage < 1) or (leverage > 100):
2790
+ raise BadRequest(self.id + ' leverage should be between 1 and 100')
2791
+ self.load_markets()
2792
+ self.load_accounts()
2793
+ market = self.market(symbol)
2794
+ if not market['swap']:
2795
+ raise BadSymbol(self.id + ' setLeverage() supports swap contracts only')
2796
+ account = self.safe_value(self.accounts, 0, {})
2797
+ accountGroup = self.safe_string(account, 'id')
2798
+ request: dict = {
2799
+ 'account-group': accountGroup,
2800
+ 'symbol': market['id'],
2801
+ 'leverage': leverage,
2802
+ }
2803
+ return self.v2PrivateAccountGroupPostFuturesLeverage(self.extend(request, params))
2804
+
2805
+ def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
2806
+ """
2807
+ set margin mode to 'cross' or 'isolated'
2808
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#change-margin-type
2809
+ :param str marginMode: 'cross' or 'isolated'
2810
+ :param str symbol: unified market symbol
2811
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2812
+ :returns dict: response from the exchange
2813
+ """
2814
+ if symbol is None:
2815
+ raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
2816
+ marginMode = marginMode.lower()
2817
+ if marginMode == 'cross':
2818
+ marginMode = 'crossed'
2819
+ if marginMode != 'isolated' and marginMode != 'crossed':
2820
+ raise BadRequest(self.id + ' setMarginMode() marginMode argument should be isolated or cross')
2821
+ self.load_markets()
2822
+ self.load_accounts()
2823
+ market = self.market(symbol)
2824
+ account = self.safe_value(self.accounts, 0, {})
2825
+ accountGroup = self.safe_string(account, 'id')
2826
+ request: dict = {
2827
+ 'account-group': accountGroup,
2828
+ 'symbol': market['id'],
2829
+ 'marginType': marginMode,
2830
+ }
2831
+ if not market['swap']:
2832
+ raise BadSymbol(self.id + ' setMarginMode() supports swap contracts only')
2833
+ return self.v2PrivateAccountGroupPostFuturesMarginType(self.extend(request, params))
2834
+
2835
+ def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
2836
+ """
2837
+ retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
2838
+ :param str[]|None symbols: list of unified market symbols
2839
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2840
+ :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
2841
+ """
2842
+ self.load_markets()
2843
+ response = self.v2PublicGetFuturesContract(params)
2844
+ #
2845
+ # {
2846
+ # "code":0,
2847
+ # "data":[
2848
+ # {
2849
+ # "symbol":"BTC-PERP",
2850
+ # "status":"Normal",
2851
+ # "displayName":"BTCUSDT",
2852
+ # "settlementAsset":"USDT",
2853
+ # "underlying":"BTC/USDT",
2854
+ # "tradingStartTime":1579701600000,
2855
+ # "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
2856
+ # "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
2857
+ # "commissionType":"Quote",
2858
+ # "commissionReserveRate":"0.001",
2859
+ # "marketOrderPriceMarkup":"0.03",
2860
+ # "marginRequirements":[
2861
+ # {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
2862
+ # {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
2863
+ # {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
2864
+ # {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
2865
+ # {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
2866
+ # {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
2867
+ # ]
2868
+ # }
2869
+ # ]
2870
+ # }
2871
+ #
2872
+ data = self.safe_value(response, 'data')
2873
+ symbols = self.market_symbols(symbols)
2874
+ return self.parse_leverage_tiers(data, symbols, 'symbol')
2875
+
2876
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
2877
+ """
2878
+ :param dict info: Exchange market response for 1 market
2879
+ :param dict market: CCXT market
2880
+ """
2881
+ #
2882
+ # {
2883
+ # "symbol":"BTC-PERP",
2884
+ # "status":"Normal",
2885
+ # "displayName":"BTCUSDT",
2886
+ # "settlementAsset":"USDT",
2887
+ # "underlying":"BTC/USDT",
2888
+ # "tradingStartTime":1579701600000,
2889
+ # "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
2890
+ # "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
2891
+ # "commissionType":"Quote",
2892
+ # "commissionReserveRate":"0.001",
2893
+ # "marketOrderPriceMarkup":"0.03",
2894
+ # "marginRequirements":[
2895
+ # {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
2896
+ # {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
2897
+ # {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
2898
+ # {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
2899
+ # {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
2900
+ # {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
2901
+ # ]
2902
+ # }
2903
+ #
2904
+ marginRequirements = self.safe_value(info, 'marginRequirements', [])
2905
+ id = self.safe_string(info, 'symbol')
2906
+ market = self.safe_market(id, market)
2907
+ tiers = []
2908
+ for i in range(0, len(marginRequirements)):
2909
+ tier = marginRequirements[i]
2910
+ initialMarginRate = self.safe_string(tier, 'initialMarginRate')
2911
+ tiers.append({
2912
+ 'tier': self.sum(i, 1),
2913
+ 'currency': market['quote'],
2914
+ 'minNotional': self.safe_number(tier, 'positionNotionalLowerBound'),
2915
+ 'maxNotional': self.safe_number(tier, 'positionNotionalUpperBound'),
2916
+ 'maintenanceMarginRate': self.safe_number(tier, 'maintenanceMarginRate'),
2917
+ 'maxLeverage': self.parse_number(Precise.string_div('1', initialMarginRate)),
2918
+ 'info': tier,
2919
+ })
2920
+ return tiers
2921
+
2922
+ def parse_deposit_withdraw_fee(self, fee, currency: Currency = None):
2923
+ #
2924
+ # {
2925
+ # "assetCode": "USDT",
2926
+ # "assetName": "Tether",
2927
+ # "precisionScale": 9,
2928
+ # "nativeScale": 4,
2929
+ # "blockChain": [
2930
+ # {
2931
+ # "chainName": "Omni",
2932
+ # "withdrawFee": "30.0",
2933
+ # "allowDeposit": True,
2934
+ # "allowWithdraw": True,
2935
+ # "minDepositAmt": "0.0",
2936
+ # "minWithdrawal": "50.0",
2937
+ # "numConfirmations": 3
2938
+ # },
2939
+ # ]
2940
+ # }
2941
+ #
2942
+ blockChains = self.safe_value(fee, 'blockChain', [])
2943
+ blockChainsLength = len(blockChains)
2944
+ result: dict = {
2945
+ 'info': fee,
2946
+ 'withdraw': {
2947
+ 'fee': None,
2948
+ 'percentage': None,
2949
+ },
2950
+ 'deposit': {
2951
+ 'fee': None,
2952
+ 'percentage': None,
2953
+ },
2954
+ 'networks': {},
2955
+ }
2956
+ for i in range(0, blockChainsLength):
2957
+ blockChain = blockChains[i]
2958
+ networkId = self.safe_string(blockChain, 'chainName')
2959
+ currencyCode = self.safe_string(currency, 'code')
2960
+ networkCode = self.network_id_to_code(networkId, currencyCode)
2961
+ result['networks'][networkCode] = {
2962
+ 'deposit': {'fee': None, 'percentage': None},
2963
+ 'withdraw': {'fee': self.safe_number(blockChain, 'withdrawFee'), 'percentage': False},
2964
+ }
2965
+ if blockChainsLength == 1:
2966
+ result['withdraw']['fee'] = self.safe_number(blockChain, 'withdrawFee')
2967
+ result['withdraw']['percentage'] = False
2968
+ return result
2969
+
2970
+ def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
2971
+ """
2972
+ fetch deposit and withdraw fees
2973
+ :see: https://ascendex.github.io/ascendex-pro-api/#list-all-assets
2974
+ :param str[]|None codes: list of unified currency codes
2975
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2976
+ :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
2977
+ """
2978
+ self.load_markets()
2979
+ response = self.v2PublicGetAssets(params)
2980
+ data = self.safe_list(response, 'data')
2981
+ return self.parse_deposit_withdraw_fees(data, codes, 'assetCode')
2982
+
2983
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2984
+ """
2985
+ transfer currency internally between wallets on the same account
2986
+ :param str code: unified currency codeåå
2987
+ :param float amount: amount to transfer
2988
+ :param str fromAccount: account to transfer from
2989
+ :param str toAccount: account to transfer to
2990
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2991
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2992
+ """
2993
+ self.load_markets()
2994
+ self.load_accounts()
2995
+ account = self.safe_value(self.accounts, 0, {})
2996
+ accountGroup = self.safe_string(account, 'id')
2997
+ currency = self.currency(code)
2998
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
2999
+ fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
3000
+ toId = self.safe_string(accountsByType, toAccount, toAccount)
3001
+ if fromId != 'cash' and toId != 'cash':
3002
+ raise ExchangeError(self.id + ' transfer() only supports direct balance transfer between spot and swap, spot and margin')
3003
+ request: dict = {
3004
+ 'account-group': accountGroup,
3005
+ 'amount': self.currency_to_precision(code, amount),
3006
+ 'asset': currency['id'],
3007
+ 'fromAccount': fromId,
3008
+ 'toAccount': toId,
3009
+ }
3010
+ response = self.v1PrivateAccountGroupPostTransfer(self.extend(request, params))
3011
+ #
3012
+ # {"code": "0"}
3013
+ #
3014
+ transferOptions = self.safe_value(self.options, 'transfer', {})
3015
+ fillResponseFromRequest = self.safe_bool(transferOptions, 'fillResponseFromRequest', True)
3016
+ transfer = self.parse_transfer(response, currency)
3017
+ if fillResponseFromRequest:
3018
+ transfer['fromAccount'] = fromAccount
3019
+ transfer['toAccount'] = toAccount
3020
+ transfer['amount'] = amount
3021
+ transfer['currency'] = code
3022
+ return transfer
3023
+
3024
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
3025
+ #
3026
+ # {"code": "0"}
3027
+ #
3028
+ status = self.safe_string(transfer, 'code')
3029
+ currencyCode = self.safe_currency_code(None, currency)
3030
+ return {
3031
+ 'info': transfer,
3032
+ 'id': None,
3033
+ 'timestamp': None,
3034
+ 'datetime': None,
3035
+ 'currency': currencyCode,
3036
+ 'amount': None,
3037
+ 'fromAccount': None,
3038
+ 'toAccount': None,
3039
+ 'status': self.parse_transfer_status(status),
3040
+ }
3041
+
3042
+ def parse_transfer_status(self, status: Str) -> Str:
3043
+ if status == '0':
3044
+ return 'ok'
3045
+ return 'failed'
3046
+
3047
+ def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3048
+ """
3049
+ fetch the history of funding payments paid and received on self account
3050
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#funding-payment-history
3051
+ :param str [symbol]: unified market symbol
3052
+ :param int [since]: the earliest time in ms to fetch funding history for
3053
+ :param int [limit]: the maximum number of funding history structures to retrieve
3054
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3055
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3056
+ :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
3057
+ """
3058
+ self.load_markets()
3059
+ self.load_accounts()
3060
+ paginate = False
3061
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingHistory', 'paginate')
3062
+ if paginate:
3063
+ return self.fetch_paginated_call_incremental('fetchFundingHistory', symbol, since, limit, params, 'page', 25)
3064
+ account = self.safe_value(self.accounts, 0, {})
3065
+ accountGroup = self.safe_string(account, 'id')
3066
+ request: dict = {
3067
+ 'account-group': accountGroup,
3068
+ }
3069
+ market = None
3070
+ if symbol is not None:
3071
+ market = self.market(symbol)
3072
+ request['symbol'] = market['id']
3073
+ if limit is not None:
3074
+ request['pageSize'] = limit
3075
+ response = self.v2PrivateAccountGroupGetFuturesFundingPayments(self.extend(request, params))
3076
+ #
3077
+ # {
3078
+ # "code": 0,
3079
+ # "data": {
3080
+ # "data": [
3081
+ # {
3082
+ # "timestamp": 1640476800000,
3083
+ # "symbol": "BTC-PERP",
3084
+ # "paymentInUSDT": "-0.013991178",
3085
+ # "fundingRate": "0.000173497"
3086
+ # },
3087
+ # ],
3088
+ # "page": 1,
3089
+ # "pageSize": 3,
3090
+ # "hasNext": True
3091
+ # }
3092
+ # }
3093
+ #
3094
+ data = self.safe_value(response, 'data', {})
3095
+ rows = self.safe_list(data, 'data', [])
3096
+ return self.parse_incomes(rows, market, since, limit)
3097
+
3098
+ def parse_income(self, income, market: Market = None):
3099
+ #
3100
+ # {
3101
+ # "timestamp": 1640476800000,
3102
+ # "symbol": "BTC-PERP",
3103
+ # "paymentInUSDT": "-0.013991178",
3104
+ # "fundingRate": "0.000173497"
3105
+ # }
3106
+ #
3107
+ marketId = self.safe_string(income, 'symbol')
3108
+ timestamp = self.safe_integer(income, 'timestamp')
3109
+ return {
3110
+ 'info': income,
3111
+ 'symbol': self.safe_symbol(marketId, market, '-', 'swap'),
3112
+ 'code': 'USDT',
3113
+ 'timestamp': timestamp,
3114
+ 'datetime': self.iso8601(timestamp),
3115
+ 'id': None,
3116
+ 'amount': self.safe_number(income, 'paymentInUSDT'),
3117
+ }
3118
+
3119
+ def fetch_margin_modes(self, symbols: Strings = None, params={}) -> MarginModes:
3120
+ """
3121
+ fetches the set margin mode of the user
3122
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
3123
+ :param str[] [symbols]: a list of unified market symbols
3124
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3125
+ :returns dict: a list of `margin mode structures <https://docs.ccxt.com/#/?id=margin-mode-structure>`
3126
+ """
3127
+ self.load_markets()
3128
+ self.load_accounts()
3129
+ account = self.safe_value(self.accounts, 0, {})
3130
+ accountGroup = self.safe_string(account, 'id')
3131
+ request: dict = {
3132
+ 'account-group': accountGroup,
3133
+ }
3134
+ response = self.v2PrivateAccountGroupGetFuturesPosition(self.extend(request, params))
3135
+ #
3136
+ # {
3137
+ # "code": 0,
3138
+ # "data": {
3139
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
3140
+ # "ac": "FUTURES",
3141
+ # "collaterals": [
3142
+ # {
3143
+ # "asset": "USDT",
3144
+ # "balance": "44.570287262",
3145
+ # "referencePrice": "1",
3146
+ # "discountFactor": "1"
3147
+ # }
3148
+ # ],
3149
+ # "contracts": [
3150
+ # {
3151
+ # "symbol": "BTC-PERP",
3152
+ # "side": "LONG",
3153
+ # "position": "0.0001",
3154
+ # "referenceCost": "-3.12277254",
3155
+ # "unrealizedPnl": "-0.001700233",
3156
+ # "realizedPnl": "0",
3157
+ # "avgOpenPrice": "31209",
3158
+ # "marginType": "isolated",
3159
+ # "isolatedMargin": "1.654972977",
3160
+ # "leverage": "2",
3161
+ # "takeProfitPrice": "0",
3162
+ # "takeProfitTrigger": "market",
3163
+ # "stopLossPrice": "0",
3164
+ # "stopLossTrigger": "market",
3165
+ # "buyOpenOrderNotional": "0",
3166
+ # "sellOpenOrderNotional": "0",
3167
+ # "markPrice": "31210.723063672",
3168
+ # "indexPrice": "31223.148857925"
3169
+ # },
3170
+ # ]
3171
+ # }
3172
+ # }
3173
+ #
3174
+ data = self.safe_dict(response, 'data', {})
3175
+ marginModes = self.safe_list(data, 'contracts', [])
3176
+ return self.parse_margin_modes(marginModes, symbols, 'symbol')
3177
+
3178
+ def parse_margin_mode(self, marginMode: dict, market=None) -> MarginMode:
3179
+ marketId = self.safe_string(marginMode, 'symbol')
3180
+ marginType = self.safe_string(marginMode, 'marginType')
3181
+ margin = 'cross' if (marginType == 'crossed') else 'isolated'
3182
+ return {
3183
+ 'info': marginMode,
3184
+ 'symbol': self.safe_symbol(marketId, market),
3185
+ 'marginMode': margin,
3186
+ }
3187
+
3188
+ def fetch_leverages(self, symbols: Strings = None, params={}) -> Leverages:
3189
+ """
3190
+ fetch the set leverage for all contract markets
3191
+ :see: https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
3192
+ :param str[] [symbols]: a list of unified market symbols
3193
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3194
+ :returns dict: a list of `leverage structures <https://docs.ccxt.com/#/?id=leverage-structure>`
3195
+ """
3196
+ self.load_markets()
3197
+ self.load_accounts()
3198
+ account = self.safe_value(self.accounts, 0, {})
3199
+ accountGroup = self.safe_string(account, 'id')
3200
+ request: dict = {
3201
+ 'account-group': accountGroup,
3202
+ }
3203
+ response = self.v2PrivateAccountGroupGetFuturesPosition(self.extend(request, params))
3204
+ #
3205
+ # {
3206
+ # "code": 0,
3207
+ # "data": {
3208
+ # "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
3209
+ # "ac": "FUTURES",
3210
+ # "collaterals": [
3211
+ # {
3212
+ # "asset": "USDT",
3213
+ # "balance": "44.570287262",
3214
+ # "referencePrice": "1",
3215
+ # "discountFactor": "1"
3216
+ # }
3217
+ # ],
3218
+ # "contracts": [
3219
+ # {
3220
+ # "symbol": "BTC-PERP",
3221
+ # "side": "LONG",
3222
+ # "position": "0.0001",
3223
+ # "referenceCost": "-3.12277254",
3224
+ # "unrealizedPnl": "-0.001700233",
3225
+ # "realizedPnl": "0",
3226
+ # "avgOpenPrice": "31209",
3227
+ # "marginType": "isolated",
3228
+ # "isolatedMargin": "1.654972977",
3229
+ # "leverage": "2",
3230
+ # "takeProfitPrice": "0",
3231
+ # "takeProfitTrigger": "market",
3232
+ # "stopLossPrice": "0",
3233
+ # "stopLossTrigger": "market",
3234
+ # "buyOpenOrderNotional": "0",
3235
+ # "sellOpenOrderNotional": "0",
3236
+ # "markPrice": "31210.723063672",
3237
+ # "indexPrice": "31223.148857925"
3238
+ # },
3239
+ # ]
3240
+ # }
3241
+ # }
3242
+ #
3243
+ data = self.safe_dict(response, 'data', {})
3244
+ leverages = self.safe_list(data, 'contracts', [])
3245
+ return self.parse_leverages(leverages, symbols, 'symbol')
3246
+
3247
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
3248
+ marketId = self.safe_string(leverage, 'symbol')
3249
+ leverageValue = self.safe_integer(leverage, 'leverage')
3250
+ marginType = self.safe_string(leverage, 'marginType')
3251
+ marginMode = 'cross' if (marginType == 'crossed') else 'isolated'
3252
+ return {
3253
+ 'info': leverage,
3254
+ 'symbol': self.safe_symbol(marketId, market),
3255
+ 'marginMode': marginMode,
3256
+ 'longLeverage': leverageValue,
3257
+ 'shortLeverage': leverageValue,
3258
+ }
3259
+
3260
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
3261
+ version = api[0]
3262
+ access = api[1]
3263
+ type = self.safe_string(api, 2)
3264
+ url = ''
3265
+ accountCategory = (type == 'accountCategory')
3266
+ if accountCategory or (type == 'accountGroup'):
3267
+ url += self.implode_params('/{account-group}', params)
3268
+ params = self.omit(params, 'account-group')
3269
+ request = self.implode_params(path, params)
3270
+ url += '/api/pro/'
3271
+ if version == 'v2':
3272
+ if type == 'data':
3273
+ request = 'data/' + version + '/' + request
3274
+ else:
3275
+ request = version + '/' + request
3276
+ else:
3277
+ url += version + '/'
3278
+ if accountCategory:
3279
+ url += self.implode_params('{account-category}/', params)
3280
+ params = self.omit(params, 'account-category')
3281
+ url += request
3282
+ if (version == 'v1') and (request == 'cash/balance') or (request == 'margin/balance'):
3283
+ request = 'balance'
3284
+ if (version == 'v1') and (request == 'spot/fee'):
3285
+ request = 'fee'
3286
+ if request.find('subuser') >= 0:
3287
+ parts = request.split('/')
3288
+ request = parts[2]
3289
+ params = self.omit(params, self.extract_params(path))
3290
+ if access == 'public':
3291
+ if params:
3292
+ url += '?' + self.urlencode(params)
3293
+ else:
3294
+ self.check_required_credentials()
3295
+ timestamp = str(self.milliseconds())
3296
+ payload = timestamp + '+' + request
3297
+ hmac = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
3298
+ headers = {
3299
+ 'x-auth-key': self.apiKey,
3300
+ 'x-auth-timestamp': timestamp,
3301
+ 'x-auth-signature': hmac,
3302
+ }
3303
+ if method == 'GET':
3304
+ if params:
3305
+ url += '?' + self.urlencode(params)
3306
+ else:
3307
+ headers['Content-Type'] = 'application/json'
3308
+ body = self.json(params)
3309
+ url = self.urls['api']['rest'] + url
3310
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
3311
+
3312
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
3313
+ if response is None:
3314
+ return None # fallback to default error handler
3315
+ #
3316
+ # {"code": 6010, "message": "Not enough balance."}
3317
+ # {"code": 60060, "message": "The order is already filled or canceled."}
3318
+ # {"code":2100,"message":"ApiKeyFailure"}
3319
+ # {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}}
3320
+ #
3321
+ code = self.safe_string(response, 'code')
3322
+ message = self.safe_string(response, 'message')
3323
+ error = (code is not None) and (code != '0')
3324
+ if error or (message is not None):
3325
+ feedback = self.id + ' ' + body
3326
+ self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
3327
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
3328
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
3329
+ raise ExchangeError(feedback) # unknown message
3330
+ return None