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
@@ -0,0 +1,3423 @@
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.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.hitbtc import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Leverage, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, 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 OrderNotFound
21
+ from ccxt.base.errors import NotSupported
22
+ from ccxt.base.errors import RateLimitExceeded
23
+ from ccxt.base.errors import ExchangeNotAvailable
24
+ from ccxt.base.errors import OnMaintenance
25
+ from ccxt.base.decimal_to_precision import TICK_SIZE
26
+ from ccxt.base.precise import Precise
27
+
28
+
29
+ class hitbtc(Exchange, ImplicitAPI):
30
+
31
+ def describe(self):
32
+ return self.deep_extend(super(hitbtc, self).describe(), {
33
+ 'id': 'hitbtc',
34
+ 'name': 'HitBTC',
35
+ 'countries': ['HK'],
36
+ # 300 requests per second => 1000ms / 300 = 3.333(Trading: placing, replacing, deleting)
37
+ # 30 requests per second =>( 1000ms / rateLimit ) / 30 = cost = 10(Market Data and other Public Requests)
38
+ # 20 requests per second =>( 1000ms / rateLimit ) / 20 = cost = 15(All Other)
39
+ 'rateLimit': 3.333, # TODO: optimize https://api.hitbtc.com/#rate-limiting
40
+ 'version': '3',
41
+ 'has': {
42
+ 'CORS': False,
43
+ 'spot': True,
44
+ 'margin': True,
45
+ 'swap': True,
46
+ 'future': False,
47
+ 'option': None,
48
+ 'addMargin': True,
49
+ 'cancelAllOrders': True,
50
+ 'cancelOrder': True,
51
+ 'closePosition': False,
52
+ 'createDepositAddress': True,
53
+ 'createOrder': True,
54
+ 'createPostOnlyOrder': True,
55
+ 'createReduceOnlyOrder': True,
56
+ 'createStopLimitOrder': True,
57
+ 'createStopMarketOrder': True,
58
+ 'createStopOrder': True,
59
+ 'editOrder': True,
60
+ 'fetchAccounts': False,
61
+ 'fetchBalance': True,
62
+ 'fetchBorrowRateHistories': None,
63
+ 'fetchBorrowRateHistory': None,
64
+ 'fetchClosedOrders': True,
65
+ 'fetchCrossBorrowRate': False,
66
+ 'fetchCrossBorrowRates': False,
67
+ 'fetchCurrencies': True,
68
+ 'fetchDepositAddress': True,
69
+ 'fetchDeposits': True,
70
+ 'fetchDepositsWithdrawals': True,
71
+ 'fetchDepositWithdrawFee': 'emulated',
72
+ 'fetchDepositWithdrawFees': True,
73
+ 'fetchFundingHistory': None,
74
+ 'fetchFundingRate': True,
75
+ 'fetchFundingRateHistory': True,
76
+ 'fetchFundingRates': True,
77
+ 'fetchIndexOHLCV': True,
78
+ 'fetchIsolatedBorrowRate': False,
79
+ 'fetchIsolatedBorrowRates': False,
80
+ 'fetchLeverage': True,
81
+ 'fetchLeverageTiers': None,
82
+ 'fetchLiquidations': False,
83
+ 'fetchMarginMode': 'emulated',
84
+ 'fetchMarginModes': True,
85
+ 'fetchMarketLeverageTiers': False,
86
+ 'fetchMarkets': True,
87
+ 'fetchMarkOHLCV': True,
88
+ 'fetchMyLiquidations': False,
89
+ 'fetchMyTrades': True,
90
+ 'fetchOHLCV': True,
91
+ 'fetchOpenInterest': True,
92
+ 'fetchOpenInterestHistory': False,
93
+ 'fetchOpenOrder': True,
94
+ 'fetchOpenOrders': True,
95
+ 'fetchOrder': True,
96
+ 'fetchOrderBook': True,
97
+ 'fetchOrderBooks': True,
98
+ 'fetchOrders': False,
99
+ 'fetchOrderTrades': True,
100
+ 'fetchPosition': True,
101
+ 'fetchPositions': True,
102
+ 'fetchPremiumIndexOHLCV': True,
103
+ 'fetchTicker': True,
104
+ 'fetchTickers': True,
105
+ 'fetchTrades': True,
106
+ 'fetchTradingFee': True,
107
+ 'fetchTradingFees': True,
108
+ 'fetchTransactions': 'emulated',
109
+ 'fetchWithdrawals': True,
110
+ 'reduceMargin': True,
111
+ 'sandbox': True,
112
+ 'setLeverage': True,
113
+ 'setMargin': False,
114
+ 'setMarginMode': False,
115
+ 'setPositionMode': False,
116
+ 'transfer': True,
117
+ 'withdraw': True,
118
+ },
119
+ 'precisionMode': TICK_SIZE,
120
+ 'urls': {
121
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg',
122
+ 'test': {
123
+ 'public': 'https://api.demo.hitbtc.com/api/3',
124
+ 'private': 'https://api.demo.hitbtc.com/api/3',
125
+ },
126
+ 'api': {
127
+ 'public': 'https://api.hitbtc.com/api/3',
128
+ 'private': 'https://api.hitbtc.com/api/3',
129
+ },
130
+ 'www': 'https://hitbtc.com',
131
+ 'referral': 'https://hitbtc.com/?ref_id=5a5d39a65d466',
132
+ 'doc': [
133
+ 'https://api.hitbtc.com',
134
+ 'https://github.com/hitbtc-com/hitbtc-api/blob/master/APIv2.md',
135
+ ],
136
+ 'fees': [
137
+ 'https://hitbtc.com/fees-and-limits',
138
+ 'https://support.hitbtc.com/hc/en-us/articles/115005148605-Fees-and-limits',
139
+ ],
140
+ },
141
+ 'api': {
142
+ 'public': {
143
+ 'get': {
144
+ 'public/currency': 10,
145
+ 'public/currency/{currency}': 10,
146
+ 'public/symbol': 10,
147
+ 'public/symbol/{symbol}': 10,
148
+ 'public/ticker': 10,
149
+ 'public/ticker/{symbol}': 10,
150
+ 'public/price/rate': 10,
151
+ 'public/price/history': 10,
152
+ 'public/price/ticker': 10,
153
+ 'public/price/ticker/{symbol}': 10,
154
+ 'public/trades': 10,
155
+ 'public/trades/{symbol}': 10,
156
+ 'public/orderbook': 10,
157
+ 'public/orderbook/{symbol}': 10,
158
+ 'public/candles': 10,
159
+ 'public/candles/{symbol}': 10,
160
+ 'public/converted/candles': 10,
161
+ 'public/converted/candles/{symbol}': 10,
162
+ 'public/futures/info': 10,
163
+ 'public/futures/info/{symbol}': 10,
164
+ 'public/futures/history/funding': 10,
165
+ 'public/futures/history/funding/{symbol}': 10,
166
+ 'public/futures/candles/index_price': 10,
167
+ 'public/futures/candles/index_price/{symbol}': 10,
168
+ 'public/futures/candles/mark_price': 10,
169
+ 'public/futures/candles/mark_price/{symbol}': 10,
170
+ 'public/futures/candles/premium_index': 10,
171
+ 'public/futures/candles/premium_index/{symbol}': 10,
172
+ 'public/futures/candles/open_interest': 10,
173
+ 'public/futures/candles/open_interest/{symbol}': 10,
174
+ },
175
+ },
176
+ 'private': {
177
+ 'get': {
178
+ 'spot/balance': 15,
179
+ 'spot/balance/{currency}': 15,
180
+ 'spot/order': 1,
181
+ 'spot/order/{client_order_id}': 1,
182
+ 'spot/fee': 15,
183
+ 'spot/fee/{symbol}': 15,
184
+ 'spot/history/order': 15,
185
+ 'spot/history/trade': 15,
186
+ 'margin/account': 1,
187
+ 'margin/account/isolated/{symbol}': 1,
188
+ 'margin/account/cross/{currency}': 1,
189
+ 'margin/order': 1,
190
+ 'margin/order/{client_order_id}': 1,
191
+ 'margin/config': 15,
192
+ 'margin/history/order': 15,
193
+ 'margin/history/trade': 15,
194
+ 'margin/history/positions': 15,
195
+ 'margin/history/clearing': 15,
196
+ 'futures/balance': 15,
197
+ 'futures/balance/{currency}': 15,
198
+ 'futures/account': 1,
199
+ 'futures/account/isolated/{symbol}': 1,
200
+ 'futures/order': 1,
201
+ 'futures/order/{client_order_id}': 1,
202
+ 'futures/config': 15,
203
+ 'futures/fee': 15,
204
+ 'futures/fee/{symbol}': 15,
205
+ 'futures/history/order': 15,
206
+ 'futures/history/trade': 15,
207
+ 'futures/history/positions': 15,
208
+ 'futures/history/clearing': 15,
209
+ 'wallet/balance': 30,
210
+ 'wallet/balance/{currency}': 30,
211
+ 'wallet/crypto/address': 30,
212
+ 'wallet/crypto/address/recent-deposit': 30,
213
+ 'wallet/crypto/address/recent-withdraw': 30,
214
+ 'wallet/crypto/address/check-mine': 30,
215
+ 'wallet/transactions': 30,
216
+ 'wallet/transactions/{tx_id}': 30,
217
+ 'wallet/crypto/fee/estimate': 30,
218
+ 'wallet/airdrops': 30,
219
+ 'wallet/amount-locks': 30,
220
+ 'sub-account': 15,
221
+ 'sub-account/acl': 15,
222
+ 'sub-account/balance/{subAccID}': 15,
223
+ 'sub-account/crypto/address/{subAccID}/{currency}': 15,
224
+ },
225
+ 'post': {
226
+ 'spot/order': 1,
227
+ 'spot/order/list': 1,
228
+ 'margin/order': 1,
229
+ 'margin/order/list': 1,
230
+ 'futures/order': 1,
231
+ 'futures/order/list': 1,
232
+ 'wallet/crypto/address': 30,
233
+ 'wallet/crypto/withdraw': 30,
234
+ 'wallet/convert': 30,
235
+ 'wallet/transfer': 30,
236
+ 'wallet/internal/withdraw': 30,
237
+ 'wallet/crypto/check-offchain-available': 30,
238
+ 'wallet/crypto/fees/estimate': 30,
239
+ 'wallet/airdrops/{id}/claim': 30,
240
+ 'sub-account/freeze': 15,
241
+ 'sub-account/activate': 15,
242
+ 'sub-account/transfer': 15,
243
+ 'sub-account/acl': 15,
244
+ },
245
+ 'patch': {
246
+ 'spot/order/{client_order_id}': 1,
247
+ 'margin/order/{client_order_id}': 1,
248
+ 'futures/order/{client_order_id}': 1,
249
+ },
250
+ 'delete': {
251
+ 'spot/order': 1,
252
+ 'spot/order/{client_order_id}': 1,
253
+ 'margin/position': 1,
254
+ 'margin/position/isolated/{symbol}': 1,
255
+ 'margin/order': 1,
256
+ 'margin/order/{client_order_id}': 1,
257
+ 'futures/position': 1,
258
+ 'futures/position/{margin_mode}/{symbol}': 1,
259
+ 'futures/order': 1,
260
+ 'futures/order/{client_order_id}': 1,
261
+ 'wallet/crypto/withdraw/{id}': 30,
262
+ },
263
+ 'put': {
264
+ 'margin/account/isolated/{symbol}': 1,
265
+ 'futures/account/isolated/{symbol}': 1,
266
+ 'wallet/crypto/withdraw/{id}': 30,
267
+ },
268
+ },
269
+ },
270
+ 'fees': {
271
+ 'trading': {
272
+ 'tierBased': True,
273
+ 'percentage': True,
274
+ 'taker': self.parse_number('0.0009'),
275
+ 'maker': self.parse_number('0.0009'),
276
+ 'tiers': {
277
+ 'maker': [
278
+ [self.parse_number('0'), self.parse_number('0.0009')],
279
+ [self.parse_number('10'), self.parse_number('0.0007')],
280
+ [self.parse_number('100'), self.parse_number('0.0006')],
281
+ [self.parse_number('500'), self.parse_number('0.0005')],
282
+ [self.parse_number('1000'), self.parse_number('0.0003')],
283
+ [self.parse_number('5000'), self.parse_number('0.0002')],
284
+ [self.parse_number('10000'), self.parse_number('0.0001')],
285
+ [self.parse_number('20000'), self.parse_number('0')],
286
+ [self.parse_number('50000'), self.parse_number('-0.0001')],
287
+ [self.parse_number('100000'), self.parse_number('-0.0001')],
288
+ ],
289
+ 'taker': [
290
+ [self.parse_number('0'), self.parse_number('0.0009')],
291
+ [self.parse_number('10'), self.parse_number('0.0008')],
292
+ [self.parse_number('100'), self.parse_number('0.0007')],
293
+ [self.parse_number('500'), self.parse_number('0.0007')],
294
+ [self.parse_number('1000'), self.parse_number('0.0006')],
295
+ [self.parse_number('5000'), self.parse_number('0.0006')],
296
+ [self.parse_number('10000'), self.parse_number('0.0005')],
297
+ [self.parse_number('20000'), self.parse_number('0.0004')],
298
+ [self.parse_number('50000'), self.parse_number('0.0003')],
299
+ [self.parse_number('100000'), self.parse_number('0.0002')],
300
+ ],
301
+ },
302
+ },
303
+ },
304
+ 'timeframes': {
305
+ '1m': 'M1',
306
+ '3m': 'M3',
307
+ '5m': 'M5',
308
+ '15m': 'M15',
309
+ '30m': 'M30', # default
310
+ '1h': 'H1',
311
+ '4h': 'H4',
312
+ '1d': 'D1',
313
+ '1w': 'D7',
314
+ '1M': '1M',
315
+ },
316
+ 'exceptions': {
317
+ 'exact': {
318
+ '429': RateLimitExceeded,
319
+ '500': ExchangeError,
320
+ '503': ExchangeNotAvailable,
321
+ '504': ExchangeNotAvailable,
322
+ '600': PermissionDenied,
323
+ '800': ExchangeError,
324
+ '1002': AuthenticationError,
325
+ '1003': PermissionDenied,
326
+ '1004': AuthenticationError,
327
+ '1005': AuthenticationError,
328
+ '2001': BadSymbol,
329
+ '2002': BadRequest,
330
+ '2003': BadRequest,
331
+ '2010': BadRequest,
332
+ '2011': BadRequest,
333
+ '2012': BadRequest,
334
+ '2020': BadRequest,
335
+ '2022': BadRequest,
336
+ '2024': InvalidOrder, # Invalid margin mode.
337
+ '10001': BadRequest,
338
+ '10021': AccountSuspended,
339
+ '10022': BadRequest,
340
+ '20001': InsufficientFunds,
341
+ '20002': OrderNotFound,
342
+ '20003': ExchangeError,
343
+ '20004': ExchangeError,
344
+ '20005': ExchangeError,
345
+ '20006': ExchangeError,
346
+ '20007': ExchangeError,
347
+ '20008': InvalidOrder,
348
+ '20009': InvalidOrder,
349
+ '20010': OnMaintenance,
350
+ '20011': ExchangeError,
351
+ '20012': ExchangeError,
352
+ '20014': ExchangeError,
353
+ '20016': ExchangeError,
354
+ '20018': ExchangeError, # Withdrawals are unavailable due to the current configuration. Any of: - internal withdrawals are disabled; - in-chain withdrawals are disabled.
355
+ '20031': ExchangeError,
356
+ '20032': ExchangeError,
357
+ '20033': ExchangeError,
358
+ '20034': ExchangeError,
359
+ '20040': ExchangeError,
360
+ '20041': ExchangeError,
361
+ '20042': ExchangeError,
362
+ '20043': ExchangeError,
363
+ '20044': PermissionDenied,
364
+ '20045': InvalidOrder,
365
+ '20047': InvalidOrder, # Order placing exceeds the central counterparty balance limit.
366
+ '20048': InvalidOrder, # Provided Time-In-Force instruction is invalid or the combination of the instruction and the order type is not allowed.
367
+ '20049': InvalidOrder, # Provided order type is invalid.
368
+ '20080': ExchangeError,
369
+ '21001': ExchangeError,
370
+ '21003': AccountSuspended,
371
+ '21004': AccountSuspended,
372
+ '22004': ExchangeError, # User is not found.
373
+ '22008': ExchangeError, # Gateway timeout exceeded.
374
+ },
375
+ 'broad': {},
376
+ },
377
+ 'options': {
378
+ 'defaultNetwork': 'ERC20',
379
+ 'defaultNetworks': {
380
+ 'ETH': 'ETH',
381
+ 'USDT': 'TRC20',
382
+ },
383
+ 'networks': {
384
+ # mainnet network ids are in lowercase for BTC & ETH
385
+ 'BTC': 'btc',
386
+ 'OMNI': 'BTC',
387
+ 'ETH': 'eth',
388
+ 'ERC20': 'ETH',
389
+ 'ETC': 'ETC',
390
+ 'BEP20': 'BSC',
391
+ 'TRC20': 'TRX',
392
+ # '': 'UGT',
393
+ 'NEAR': 'NEAR',
394
+ # '': 'LWF',
395
+ 'DGB': 'DGB',
396
+ # '': 'YOYOW',
397
+ 'AE': 'AE',
398
+ # 'BCHABC': 'BCHABC',
399
+ # '': 'BCI',
400
+ # 'BYTECOIN': 'bcn',
401
+ 'AR': 'AR',
402
+ # '': 'HPC',
403
+ 'ADA': 'ADA',
404
+ # 'BELDEX': 'BDX',
405
+ # 'ARDOR': 'ARDR',
406
+ # 'NEBLIO': 'NEBL',
407
+ # '': 'DIM',
408
+ 'CHZ': 'CHZ',
409
+ # '': 'BET',
410
+ # '': '8BT',
411
+ 'ABBC': 'ABBC',
412
+ # '': 'ABTC',
413
+ # 'ACHAIN': 'ACT',
414
+ # '': 'ADK',
415
+ # '': 'AEON',
416
+ 'ALGO': 'ALGO',
417
+ # 'AMBROSUS': 'AMB',
418
+ # '': 'APL',
419
+ 'APT': 'APT',
420
+ # '': 'ARK',
421
+ # 'PIRATECHAIN': 'ARRR',
422
+ # '': 'ASP',
423
+ # '': 'ATB',
424
+ 'ATOM': 'ATOM',
425
+ 'AVAXC': 'AVAC',
426
+ 'AVAXX': 'AVAX',
427
+ # '': 'AYA',
428
+ # '': 'B2G',
429
+ # '': 'B2X',
430
+ # '': 'BANANO',
431
+ # '': 'BCCF',
432
+ 'BSV': 'BCHSV',
433
+ 'BEP2': 'BNB',
434
+ # 'BOSON': 'BOS',
435
+ # '': 'BRL', # brazilian real
436
+ # '': 'BST',
437
+ # 'BITCOINADDITION': 'BTCADD',
438
+ # '': 'BTCP',
439
+ # 'SUPERBTC': 'SBTC',
440
+ # 'BITCOINVAULT': 'BTCV',
441
+ # 'BITCOINGOLD': 'BTG',
442
+ # 'BITCOINDIAMOND': 'BCD',
443
+ # 'BITCONNECT': 'BCC',
444
+ # '': 'BTM',
445
+ # 'BITSHARES_OLD': 'BTS',
446
+ # '': 'BTX',
447
+ # '': 'BWI',
448
+ 'CELO': 'CELO',
449
+ # '': 'CENNZ',
450
+ # '': 'CHX',
451
+ 'CKB': 'CKB',
452
+ # 'CALLISTO': 'CLO',
453
+ # '': 'CLR',
454
+ # '': 'CNX',
455
+ # '': 'CRS',
456
+ # '': 'CSOV',
457
+ 'CTXC': 'CTXC',
458
+ # '': 'CURE',
459
+ # 'CONSTELLATION': 'DAG',
460
+ # '': 'DAPS',
461
+ 'DASH': 'DASH',
462
+ # '': 'DBIX',
463
+ 'DCR': 'DCR',
464
+ # '': 'DCT',
465
+ # '': 'DDR',
466
+ # '': 'DNA',
467
+ 'DOGE': 'doge',
468
+ # 'POLKADOT': 'DOT',
469
+ # '': 'NEWDOT', POLKADOT NEW
470
+ # '': 'dsh',
471
+ # '': 'ECA',
472
+ # '': 'ECOIN',
473
+ # '': 'EEX',
474
+ 'EGLD': 'EGLD',
475
+ # '': 'ELE',
476
+ # 'ELECTRONEUM': 'Electroneum',
477
+ # '': 'ELM',
478
+ # '': 'EMC',
479
+ 'EOS': 'EOS',
480
+ # 'AERGO': 'ERG',
481
+ 'ETHW': 'ETHW',
482
+ # 'ETHERLITE': 'ETL',
483
+ # '': 'ETP', # metaverse etp
484
+ # '': 'EUNO',
485
+ 'EVER': 'EVER',
486
+ # '': 'EXP',
487
+ # '': 'fcn',
488
+ 'FET': 'FET',
489
+ 'FIL': 'FIL',
490
+ # '': 'FIRO',
491
+ 'FLOW': 'FLOW',
492
+ # '': 'G999',
493
+ # '': 'GAME',
494
+ # '': 'GASP',
495
+ # '': 'GBX',
496
+ # '': 'GHOST',
497
+ # '': 'GLEEC',
498
+ 'GLMR': 'GLMR',
499
+ # '': 'GMD',
500
+ # '': 'GRAPH',
501
+ 'GRIN': 'GRIN',
502
+ 'HBAR': 'HBAR',
503
+ # '': 'HDG',
504
+ 'HIVE': 'HIVE',
505
+ # 'HARBOR': 'HRB',
506
+ # '': 'HSR',
507
+ # '': 'HTML',
508
+ 'HYDRA': 'HYDRA',
509
+ 'ICP': 'ICP',
510
+ 'ICX': 'ICX',
511
+ # '': 'IML',
512
+ 'IOST': 'IOST',
513
+ 'IOTA': 'IOTA',
514
+ 'IOTX': 'IOTX',
515
+ # '': 'IQ',
516
+ 'KAVA': 'KAVA',
517
+ 'KLAY': 'KIM',
518
+ 'KOMODO': 'KMD',
519
+ # '': 'KRM',
520
+ 'KSM': 'KSM',
521
+ # '': 'LAVA',
522
+ # 'LITECOINCASH': 'LCC',
523
+ 'LSK': 'LSK',
524
+ # '': 'LOC',
525
+ 'LTC': 'ltc',
526
+ # '': 'LTNM',
527
+ # 'TERRACLASSIC': 'LUNA',
528
+ # 'TERRA': 'LUNANEW',
529
+ # '': 'MAN',
530
+ # '': 'MESH',
531
+ 'MINA': 'MINA',
532
+ # '': 'MNX',
533
+ # 'MOBILECOIN': 'MOB',
534
+ 'MOVR': 'MOVR',
535
+ # '': 'MPK',
536
+ # '': 'MRV',
537
+ 'NANO': 'NANO',
538
+ # '': 'NAV',
539
+ 'NEO': 'NEO',
540
+ # 'NIMIQ': 'NIM',
541
+ # '': 'NJBC',
542
+ # '': 'NKN',
543
+ # '': 'NLC2',
544
+ # '': 'NOF',
545
+ # 'ENERGI': 'NRG',
546
+ # '': 'nxt',
547
+ # '': 'ODN',
548
+ 'ONE': 'ONE',
549
+ # 'ONTOLOGYGAS': 'ONG',
550
+ 'ONT': 'ONT',
551
+ 'OPTIMISM': 'OP',
552
+ # '': 'PAD',
553
+ # '': 'PART',
554
+ # '': 'PBKX',
555
+ # '': 'PLC',
556
+ 'PLCU': 'PLCU',
557
+ # '': 'PLI',
558
+ # '': 'POA',
559
+ 'MATIC': 'POLYGON',
560
+ # '': 'PPC',
561
+ # '': 'PQT',
562
+ # '': 'PROC',
563
+ # 'PASTEL': 'PSL',
564
+ # '': 'qcn',
565
+ 'QTUM': 'QTUM',
566
+ # '': 'RCOIN',
567
+ 'REI': 'REI',
568
+ # '': 'RIF',
569
+ # '': 'ROOTS',
570
+ 'OASIS': 'ROSE',
571
+ # '': 'RPX',
572
+ # '': 'RUB',
573
+ 'RVN': 'RVN',
574
+ # '': 'SBD',
575
+ 'SC': 'SC',
576
+ 'SCRT': 'SCRT',
577
+ # '': 'SLX',
578
+ # 'SMARTMESH': 'SMART',
579
+ # '': 'SMT',
580
+ # '': 'SNM',
581
+ 'SOL': 'SOL',
582
+ # '': 'SRX',
583
+ # '': 'STAK',
584
+ 'STEEM': 'STEEM',
585
+ # 'STRATIS': 'STRAT',
586
+ # '': 'TCN',
587
+ # '': 'TENT',
588
+ 'THETA': 'Theta',
589
+ # '': 'TIV',
590
+ # '': 'TNC',
591
+ # 'TON': 'TONCOIN',
592
+ 'TRUE': 'TRUE',
593
+ # '': 'TRY', # turkish lira
594
+ # '': 'UNO',
595
+ # '': 'USNOTA',
596
+ # '': 'VEO',
597
+ 'VET': 'VET',
598
+ # '': 'VITAE',
599
+ # 'VELAS': 'VLX',
600
+ 'VSYS': 'VSYS',
601
+ # '': 'VTC',
602
+ 'WAVES': 'WAVES',
603
+ 'WAX': 'WAX',
604
+ # '': 'WEALTH',
605
+ # 'WALTONCHAIN': 'WTC',
606
+ # '': 'WTT',
607
+ 'XCH': 'XCH',
608
+ # '': 'XDC', # xinfin?
609
+ # '': 'xdn',
610
+ # '': 'XDNCO',
611
+ # '': 'XDNICCO',
612
+ 'XEC': 'XEC',
613
+ 'NEM': 'XEM',
614
+ # 'HAVEN': 'XHV',
615
+ # '': 'XLC',
616
+ 'XLM': 'XLM',
617
+ # '': 'XMO',
618
+ 'XMR': 'xmr',
619
+ # 'MONEROCLASSIC': 'XMC',
620
+ # '': 'XNS',
621
+ # '': 'XPRM',
622
+ # '': 'XRC',
623
+ 'XRD': 'XRD',
624
+ 'XRP': 'XRP',
625
+ 'XTZ': 'XTZ',
626
+ 'XVG': 'XVG',
627
+ 'XYM': 'XYM',
628
+ 'ZEC': 'ZEC',
629
+ 'ZEN': 'ZEN',
630
+ 'ZIL': 'ZIL',
631
+ # '': 'ZYN',
632
+ },
633
+ 'accountsByType': {
634
+ 'spot': 'spot',
635
+ 'funding': 'wallet',
636
+ 'swap': 'derivatives',
637
+ 'future': 'derivatives',
638
+ },
639
+ 'withdraw': {
640
+ 'includeFee': False,
641
+ },
642
+ },
643
+ 'commonCurrencies': {
644
+ 'AUTO': 'Cube',
645
+ 'BCC': 'BCC', # initial symbol for Bitcoin Cash, now inactive
646
+ 'BDP': 'BidiPass',
647
+ 'BET': 'DAO.Casino',
648
+ 'BIT': 'BitRewards',
649
+ 'BOX': 'BOX Token',
650
+ 'CPT': 'Cryptaur', # conflict with CPT = Contents Protocol https://github.com/ccxt/ccxt/issues/4920 and https://github.com/ccxt/ccxt/issues/6081
651
+ 'GET': 'Themis',
652
+ 'GMT': 'GMT Token',
653
+ 'HSR': 'HC',
654
+ 'IQ': 'IQ.Cash',
655
+ 'LNC': 'LinkerCoin',
656
+ 'PLA': 'PlayChip',
657
+ 'PNT': 'Penta',
658
+ 'SBTC': 'Super Bitcoin',
659
+ 'STEPN': 'GMT',
660
+ 'STX': 'STOX',
661
+ 'TV': 'Tokenville',
662
+ 'XMT': 'MTL',
663
+ 'XPNT': 'PNT',
664
+ },
665
+ })
666
+
667
+ def nonce(self):
668
+ return self.milliseconds()
669
+
670
+ async def fetch_markets(self, params={}) -> List[Market]:
671
+ """
672
+ retrieves data on all markets for hitbtc
673
+ :see: https://api.hitbtc.com/#symbols
674
+ :param dict [params]: extra parameters specific to the exchange API endpoint
675
+ :returns dict[]: an array of objects representing market data
676
+ """
677
+ response = await self.publicGetPublicSymbol(params)
678
+ #
679
+ # {
680
+ # "AAVEUSDT_PERP":{
681
+ # "type":"futures",
682
+ # "expiry":null,
683
+ # "underlying":"AAVE",
684
+ # "base_currency":null,
685
+ # "quote_currency":"USDT",
686
+ # "quantity_increment":"0.01",
687
+ # "tick_size":"0.001",
688
+ # "take_rate":"0.0005",
689
+ # "make_rate":"0.0002",
690
+ # "fee_currency":"USDT",
691
+ # "margin_trading":true,
692
+ # "max_initial_leverage":"50.00"
693
+ # },
694
+ # "MANAUSDT":{
695
+ # "type":"spot",
696
+ # "base_currency":"MANA",
697
+ # "quote_currency":"USDT",
698
+ # "quantity_increment":"1",
699
+ # "tick_size":"0.0000001",
700
+ # "take_rate":"0.0025",
701
+ # "make_rate":"0.001",
702
+ # "fee_currency":"USDT",
703
+ # "margin_trading":true,
704
+ # "max_initial_leverage":"5.00"
705
+ # },
706
+ # }
707
+ #
708
+ result = []
709
+ ids = list(response.keys())
710
+ for i in range(0, len(ids)):
711
+ id = ids[i]
712
+ if id.endswith('_BQX'):
713
+ continue # seems like an invalid symbol and if we try to access it individually we get: {"timestamp":"2023-09-02T14:38:20.351Z","error":{"description":"Try get /public/symbol, to get list of all available symbols.","code":2001,"message":"No such symbol: EOSUSD_BQX"},"path":"/api/3/public/symbol/EOSUSD_BQX","requestId":"e1e9fce6-16374591"}
714
+ market = self.safe_value(response, id)
715
+ marketType = self.safe_string(market, 'type')
716
+ expiry = self.safe_integer(market, 'expiry')
717
+ contract = (marketType == 'futures')
718
+ spot = (marketType == 'spot')
719
+ marginTrading = self.safe_bool(market, 'margin_trading', False)
720
+ margin = spot and marginTrading
721
+ future = (expiry is not None)
722
+ swap = (contract and not future)
723
+ option = False
724
+ baseId = self.safe_string_2(market, 'base_currency', 'underlying')
725
+ quoteId = self.safe_string(market, 'quote_currency')
726
+ feeCurrencyId = self.safe_string(market, 'fee_currency')
727
+ base = self.safe_currency_code(baseId)
728
+ quote = self.safe_currency_code(quoteId)
729
+ feeCurrency = self.safe_currency_code(feeCurrencyId)
730
+ settleId = None
731
+ settle = None
732
+ symbol = base + '/' + quote
733
+ type = 'spot'
734
+ contractSize = None
735
+ linear = None
736
+ inverse = None
737
+ if contract:
738
+ contractSize = self.parse_number('1')
739
+ settleId = feeCurrencyId
740
+ settle = self.safe_currency_code(settleId)
741
+ linear = ((quote is not None) and (quote == settle))
742
+ inverse = not linear
743
+ symbol = symbol + ':' + settle
744
+ if future:
745
+ symbol = symbol + '-' + expiry
746
+ type = 'future'
747
+ else:
748
+ type = 'swap'
749
+ lotString = self.safe_string(market, 'quantity_increment')
750
+ stepString = self.safe_string(market, 'tick_size')
751
+ lot = self.parse_number(lotString)
752
+ step = self.parse_number(stepString)
753
+ result.append({
754
+ 'id': id,
755
+ 'symbol': symbol,
756
+ 'base': base,
757
+ 'quote': quote,
758
+ 'settle': settle,
759
+ 'baseId': baseId,
760
+ 'quoteId': quoteId,
761
+ 'settleId': settleId,
762
+ 'type': type,
763
+ 'spot': spot,
764
+ 'margin': margin,
765
+ 'swap': swap,
766
+ 'future': future,
767
+ 'option': option,
768
+ 'active': True,
769
+ 'contract': contract,
770
+ 'linear': linear,
771
+ 'inverse': inverse,
772
+ 'taker': self.safe_number(market, 'take_rate'),
773
+ 'maker': self.safe_number(market, 'make_rate'),
774
+ 'contractSize': contractSize,
775
+ 'expiry': expiry,
776
+ 'expiryDatetime': None,
777
+ 'strike': None,
778
+ 'optionType': None,
779
+ 'feeCurrency': feeCurrency,
780
+ 'precision': {
781
+ 'amount': lot,
782
+ 'price': step,
783
+ },
784
+ 'limits': {
785
+ 'leverage': {
786
+ 'min': self.parse_number('1'),
787
+ 'max': self.safe_number(market, 'max_initial_leverage', 1),
788
+ },
789
+ 'amount': {
790
+ 'min': lot,
791
+ 'max': None,
792
+ },
793
+ 'price': {
794
+ 'min': step,
795
+ 'max': None,
796
+ },
797
+ 'cost': {
798
+ 'min': self.parse_number(Precise.string_mul(lotString, stepString)),
799
+ 'max': None,
800
+ },
801
+ },
802
+ 'created': None,
803
+ 'info': market,
804
+ })
805
+ return result
806
+
807
+ async def fetch_currencies(self, params={}) -> Currencies:
808
+ """
809
+ fetches all available currencies on an exchange
810
+ :see: https://api.hitbtc.com/#currencies
811
+ :param dict [params]: extra parameters specific to the exchange API endpoint
812
+ :returns dict: an associative dictionary of currencies
813
+ """
814
+ response = await self.publicGetPublicCurrency(params)
815
+ #
816
+ # {
817
+ # "WEALTH": {
818
+ # "full_name": "ConnectWealth",
819
+ # "payin_enabled": False,
820
+ # "payout_enabled": False,
821
+ # "transfer_enabled": True,
822
+ # "precision_transfer": "0.001",
823
+ # "networks": [
824
+ # {
825
+ # "network": "ETH",
826
+ # "protocol": "ERC20",
827
+ # "default": True,
828
+ # "payin_enabled": False,
829
+ # "payout_enabled": False,
830
+ # "precision_payout": "0.001",
831
+ # "payout_fee": "0.016800000000",
832
+ # "payout_is_payment_id": False,
833
+ # "payin_payment_id": False,
834
+ # "payin_confirmations": "2"
835
+ # }
836
+ # ]
837
+ # }
838
+ # }
839
+ #
840
+ result: dict = {}
841
+ currencies = list(response.keys())
842
+ for i in range(0, len(currencies)):
843
+ currencyId = currencies[i]
844
+ code = self.safe_currency_code(currencyId)
845
+ entry = response[currencyId]
846
+ name = self.safe_string(entry, 'full_name')
847
+ precision = self.safe_number(entry, 'precision_transfer')
848
+ payinEnabled = self.safe_bool(entry, 'payin_enabled', False)
849
+ payoutEnabled = self.safe_bool(entry, 'payout_enabled', False)
850
+ transferEnabled = self.safe_bool(entry, 'transfer_enabled', False)
851
+ active = payinEnabled and payoutEnabled and transferEnabled
852
+ rawNetworks = self.safe_value(entry, 'networks', [])
853
+ networks: dict = {}
854
+ fee = None
855
+ depositEnabled = None
856
+ withdrawEnabled = None
857
+ for j in range(0, len(rawNetworks)):
858
+ rawNetwork = rawNetworks[j]
859
+ networkId = self.safe_string_2(rawNetwork, 'protocol', 'network')
860
+ network = self.safe_network(networkId)
861
+ fee = self.safe_number(rawNetwork, 'payout_fee')
862
+ networkPrecision = self.safe_number(rawNetwork, 'precision_payout')
863
+ payinEnabledNetwork = self.safe_bool(rawNetwork, 'payin_enabled', False)
864
+ payoutEnabledNetwork = self.safe_bool(rawNetwork, 'payout_enabled', False)
865
+ activeNetwork = payinEnabledNetwork and payoutEnabledNetwork
866
+ if payinEnabledNetwork and not depositEnabled:
867
+ depositEnabled = True
868
+ elif not payinEnabledNetwork:
869
+ depositEnabled = False
870
+ if payoutEnabledNetwork and not withdrawEnabled:
871
+ withdrawEnabled = True
872
+ elif not payoutEnabledNetwork:
873
+ withdrawEnabled = False
874
+ networks[network] = {
875
+ 'info': rawNetwork,
876
+ 'id': networkId,
877
+ 'network': network,
878
+ 'fee': fee,
879
+ 'active': activeNetwork,
880
+ 'deposit': payinEnabledNetwork,
881
+ 'withdraw': payoutEnabledNetwork,
882
+ 'precision': networkPrecision,
883
+ 'limits': {
884
+ 'withdraw': {
885
+ 'min': None,
886
+ 'max': None,
887
+ },
888
+ },
889
+ }
890
+ networksKeys = list(networks.keys())
891
+ networksLength = len(networksKeys)
892
+ result[code] = {
893
+ 'info': entry,
894
+ 'code': code,
895
+ 'id': currencyId,
896
+ 'precision': precision,
897
+ 'name': name,
898
+ 'active': active,
899
+ 'deposit': depositEnabled,
900
+ 'withdraw': withdrawEnabled,
901
+ 'networks': networks,
902
+ 'fee': fee if (networksLength <= 1) else None,
903
+ 'limits': {
904
+ 'amount': {
905
+ 'min': None,
906
+ 'max': None,
907
+ },
908
+ },
909
+ }
910
+ return result
911
+
912
+ def safe_network(self, networkId):
913
+ if networkId is None:
914
+ return None
915
+ else:
916
+ return networkId.upper()
917
+
918
+ async def create_deposit_address(self, code: str, params={}):
919
+ """
920
+ create a currency deposit address
921
+ :see: https://api.hitbtc.com/#generate-deposit-crypto-address
922
+ :param str code: unified currency code of the currency for the deposit address
923
+ :param dict [params]: extra parameters specific to the exchange API endpoint
924
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
925
+ """
926
+ await self.load_markets()
927
+ currency = self.currency(code)
928
+ request: dict = {
929
+ 'currency': currency['id'],
930
+ }
931
+ network = self.safe_string_upper(params, 'network')
932
+ if (network is not None) and (code == 'USDT'):
933
+ networks = self.safe_value(self.options, 'networks')
934
+ parsedNetwork = self.safe_string(networks, network)
935
+ if parsedNetwork is not None:
936
+ request['currency'] = parsedNetwork
937
+ params = self.omit(params, 'network')
938
+ response = await self.privatePostWalletCryptoAddress(self.extend(request, params))
939
+ #
940
+ # {"currency":"ETH","address":"0xd0d9aea60c41988c3e68417e2616065617b7afd3"}
941
+ #
942
+ currencyId = self.safe_string(response, 'currency')
943
+ return {
944
+ 'currency': self.safe_currency_code(currencyId),
945
+ 'address': self.safe_string(response, 'address'),
946
+ 'tag': self.safe_string(response, 'payment_id'),
947
+ 'network': None,
948
+ 'info': response,
949
+ }
950
+
951
+ async def fetch_deposit_address(self, code: str, params={}):
952
+ """
953
+ fetch the deposit address for a currency associated with self account
954
+ :see: https://api.hitbtc.com/#get-deposit-crypto-address
955
+ :param str code: unified currency code
956
+ :param dict [params]: extra parameters specific to the exchange API endpoint
957
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
958
+ """
959
+ await self.load_markets()
960
+ currency = self.currency(code)
961
+ request: dict = {
962
+ 'currency': currency['id'],
963
+ }
964
+ network = self.safe_string_upper(params, 'network')
965
+ if (network is not None) and (code == 'USDT'):
966
+ networks = self.safe_value(self.options, 'networks')
967
+ parsedNetwork = self.safe_string(networks, network)
968
+ if parsedNetwork is not None:
969
+ request['currency'] = parsedNetwork
970
+ params = self.omit(params, 'network')
971
+ response = await self.privateGetWalletCryptoAddress(self.extend(request, params))
972
+ #
973
+ # [{"currency":"ETH","address":"0xd0d9aea60c41988c3e68417e2616065617b7afd3"}]
974
+ #
975
+ firstAddress = self.safe_value(response, 0)
976
+ address = self.safe_string(firstAddress, 'address')
977
+ currencyId = self.safe_string(firstAddress, 'currency')
978
+ tag = self.safe_string(firstAddress, 'payment_id')
979
+ parsedCode = self.safe_currency_code(currencyId)
980
+ return {
981
+ 'info': response,
982
+ 'address': address,
983
+ 'tag': tag,
984
+ 'code': parsedCode, # kept here for backward-compatibility, but will be removed soon
985
+ 'currency': parsedCode,
986
+ 'network': None,
987
+ }
988
+
989
+ def parse_balance(self, response) -> Balances:
990
+ result: dict = {'info': response}
991
+ for i in range(0, len(response)):
992
+ entry = response[i]
993
+ currencyId = self.safe_string(entry, 'currency')
994
+ code = self.safe_currency_code(currencyId)
995
+ account = self.account()
996
+ account['free'] = self.safe_string(entry, 'available')
997
+ account['used'] = self.safe_string(entry, 'reserved')
998
+ result[code] = account
999
+ return self.safe_balance(result)
1000
+
1001
+ async def fetch_balance(self, params={}) -> Balances:
1002
+ """
1003
+ query for balance and get the amount of funds available for trading or funds locked in orders
1004
+ :see: https://api.hitbtc.com/#wallet-balance
1005
+ :see: https://api.hitbtc.com/#get-spot-trading-balance
1006
+ :see: https://api.hitbtc.com/#get-trading-balance
1007
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1008
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1009
+ """
1010
+ type = self.safe_string_lower(params, 'type', 'spot')
1011
+ params = self.omit(params, ['type'])
1012
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
1013
+ account = self.safe_string(accountsByType, type, type)
1014
+ response = None
1015
+ if account == 'wallet':
1016
+ response = await self.privateGetWalletBalance(params)
1017
+ elif account == 'spot':
1018
+ response = await self.privateGetSpotBalance(params)
1019
+ elif account == 'derivatives':
1020
+ response = await self.privateGetFuturesBalance(params)
1021
+ else:
1022
+ keys = list(accountsByType.keys())
1023
+ raise BadRequest(self.id + ' fetchBalance() type parameter must be one of ' + ', '.join(keys))
1024
+ #
1025
+ # [
1026
+ # {
1027
+ # "currency": "PAXG",
1028
+ # "available": "0",
1029
+ # "reserved": "0",
1030
+ # "reserved_margin": "0",
1031
+ # },
1032
+ # ...
1033
+ # ]
1034
+ #
1035
+ return self.parse_balance(response)
1036
+
1037
+ async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1038
+ """
1039
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1040
+ :see: https://api.hitbtc.com/#tickers
1041
+ :param str symbol: unified symbol of the market to fetch the ticker for
1042
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1043
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1044
+ """
1045
+ await self.load_markets()
1046
+ market = self.market(symbol)
1047
+ request: dict = {
1048
+ 'symbol': market['id'],
1049
+ }
1050
+ response = await self.publicGetPublicTickerSymbol(self.extend(request, params))
1051
+ #
1052
+ # {
1053
+ # "ask": "0.020572",
1054
+ # "bid": "0.020566",
1055
+ # "last": "0.020574",
1056
+ # "low": "0.020388",
1057
+ # "high": "0.021084",
1058
+ # "open": "0.020913",
1059
+ # "volume": "138444.3666",
1060
+ # "volume_quote": "2853.6874972480",
1061
+ # "timestamp": "2021-06-02T17:52:36.731Z"
1062
+ # }
1063
+ #
1064
+ return self.parse_ticker(response, market)
1065
+
1066
+ async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1067
+ """
1068
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1069
+ :see: https://api.hitbtc.com/#tickers
1070
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1071
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1072
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1073
+ """
1074
+ await self.load_markets()
1075
+ symbols = self.market_symbols(symbols)
1076
+ request: dict = {}
1077
+ if symbols is not None:
1078
+ marketIds = self.market_ids(symbols)
1079
+ delimited = ','.join(marketIds)
1080
+ request['symbols'] = delimited
1081
+ response = await self.publicGetPublicTicker(self.extend(request, params))
1082
+ #
1083
+ # {
1084
+ # "BTCUSDT": {
1085
+ # "ask": "63049.06",
1086
+ # "bid": "63046.41",
1087
+ # "last": "63048.36",
1088
+ # "low": "62010.00",
1089
+ # "high": "66657.99",
1090
+ # "open": "64839.75",
1091
+ # "volume": "15272.13278",
1092
+ # "volume_quote": "976312127.6277998",
1093
+ # "timestamp": "2021-10-22T04:25:47.573Z"
1094
+ # }
1095
+ # }
1096
+ #
1097
+ result: dict = {}
1098
+ keys = list(response.keys())
1099
+ for i in range(0, len(keys)):
1100
+ marketId = keys[i]
1101
+ market = self.safe_market(marketId)
1102
+ symbol = market['symbol']
1103
+ entry = response[marketId]
1104
+ result[symbol] = self.parse_ticker(entry, market)
1105
+ return self.filter_by_array_tickers(result, 'symbol', symbols)
1106
+
1107
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1108
+ #
1109
+ # {
1110
+ # "ask": "62756.01",
1111
+ # "bid": "62754.09",
1112
+ # "last": "62755.87",
1113
+ # "low": "62010.00",
1114
+ # "high": "66657.99",
1115
+ # "open": "65089.27",
1116
+ # "volume": "16719.50366",
1117
+ # "volume_quote": "1063422878.8156828",
1118
+ # "timestamp": "2021-10-22T07:29:14.585Z"
1119
+ # }
1120
+ #
1121
+ timestamp = self.parse8601(ticker['timestamp'])
1122
+ symbol = self.safe_symbol(None, market)
1123
+ baseVolume = self.safe_string(ticker, 'volume')
1124
+ quoteVolume = self.safe_string(ticker, 'volume_quote')
1125
+ open = self.safe_string(ticker, 'open')
1126
+ last = self.safe_string(ticker, 'last')
1127
+ return self.safe_ticker({
1128
+ 'symbol': symbol,
1129
+ 'timestamp': timestamp,
1130
+ 'datetime': self.iso8601(timestamp),
1131
+ 'high': self.safe_string(ticker, 'high'),
1132
+ 'low': self.safe_string(ticker, 'low'),
1133
+ 'bid': self.safe_string(ticker, 'bid'),
1134
+ 'bidVolume': None,
1135
+ 'ask': self.safe_string(ticker, 'ask'),
1136
+ 'askVolume': None,
1137
+ 'vwap': None,
1138
+ 'open': open,
1139
+ 'close': last,
1140
+ 'last': last,
1141
+ 'previousClose': None,
1142
+ 'change': None,
1143
+ 'percentage': None,
1144
+ 'average': None,
1145
+ 'baseVolume': baseVolume,
1146
+ 'quoteVolume': quoteVolume,
1147
+ 'info': ticker,
1148
+ }, market)
1149
+
1150
+ async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1151
+ """
1152
+ get the list of most recent trades for a particular symbol
1153
+ :see: https://api.hitbtc.com/#trades
1154
+ :param str symbol: unified symbol of the market to fetch trades for
1155
+ :param int [since]: timestamp in ms of the earliest trade to fetch
1156
+ :param int [limit]: the maximum amount of trades to fetch
1157
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1158
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1159
+ """
1160
+ await self.load_markets()
1161
+ market = None
1162
+ request: dict = {}
1163
+ if limit is not None:
1164
+ request['limit'] = min(limit, 1000)
1165
+ if since is not None:
1166
+ request['from'] = since
1167
+ response = None
1168
+ if symbol is not None:
1169
+ market = self.market(symbol)
1170
+ request['symbol'] = market['id']
1171
+ response = await self.publicGetPublicTradesSymbol(self.extend(request, params))
1172
+ else:
1173
+ response = await self.publicGetPublicTrades(self.extend(request, params))
1174
+ if symbol is not None:
1175
+ return self.parse_trades(response, market)
1176
+ trades = []
1177
+ marketIds = list(response.keys())
1178
+ for i in range(0, len(marketIds)):
1179
+ marketId = marketIds[i]
1180
+ marketInner = self.market(marketId)
1181
+ rawTrades = response[marketId]
1182
+ parsed = self.parse_trades(rawTrades, marketInner)
1183
+ trades = self.array_concat(trades, parsed)
1184
+ return trades
1185
+
1186
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1187
+ """
1188
+ fetch all trades made by the user
1189
+ :see: https://api.hitbtc.com/#spot-trades-history
1190
+ :see: https://api.hitbtc.com/#futures-trades-history
1191
+ :see: https://api.hitbtc.com/#margin-trades-history
1192
+ :param str symbol: unified market symbol
1193
+ :param int [since]: the earliest time in ms to fetch trades for
1194
+ :param int [limit]: the maximum number of trades structures to retrieve
1195
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1196
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1197
+ :param bool [params.margin]: True for fetching margin trades
1198
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1199
+ """
1200
+ await self.load_markets()
1201
+ market = None
1202
+ request: dict = {}
1203
+ if symbol is not None:
1204
+ market = self.market(symbol)
1205
+ request['symbol'] = market['id']
1206
+ if limit is not None:
1207
+ request['limit'] = limit
1208
+ if since is not None:
1209
+ request['from'] = since
1210
+ marketType = None
1211
+ marginMode = None
1212
+ response = None
1213
+ marketType, params = self.handle_market_type_and_params('fetchMyTrades', market, params)
1214
+ marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
1215
+ params = self.omit(params, ['marginMode', 'margin'])
1216
+ if marginMode is not None:
1217
+ response = await self.privateGetMarginHistoryTrade(self.extend(request, params))
1218
+ else:
1219
+ if marketType == 'spot':
1220
+ response = await self.privateGetSpotHistoryTrade(self.extend(request, params))
1221
+ elif marketType == 'swap':
1222
+ response = await self.privateGetFuturesHistoryTrade(self.extend(request, params))
1223
+ elif marketType == 'margin':
1224
+ response = await self.privateGetMarginHistoryTrade(self.extend(request, params))
1225
+ else:
1226
+ raise NotSupported(self.id + ' fetchMyTrades() not support self market type')
1227
+ return self.parse_trades(response, market, since, limit)
1228
+
1229
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1230
+ #
1231
+ # createOrder(market)
1232
+ #
1233
+ # {
1234
+ # "id": "1569252895",
1235
+ # "position_id": "0",
1236
+ # "quantity": "10",
1237
+ # "price": "0.03919424",
1238
+ # "fee": "0.000979856000",
1239
+ # "timestamp": "2022-01-25T19:38:36.153Z",
1240
+ # "taker": True
1241
+ # }
1242
+ #
1243
+ # fetchTrades
1244
+ #
1245
+ # {
1246
+ # "id": 974786185,
1247
+ # "price": "0.032462",
1248
+ # "qty": "0.3673",
1249
+ # "side": "buy",
1250
+ # "timestamp": "2020-10-16T12:57:39.846Z"
1251
+ # }
1252
+ #
1253
+ # fetchMyTrades spot
1254
+ #
1255
+ # {
1256
+ # "id": 277210397,
1257
+ # "clientOrderId": "6e102f3e7f3f4e04aeeb1cdc95592f1a",
1258
+ # "orderId": 28102855393,
1259
+ # "symbol": "ETHBTC",
1260
+ # "side": "sell",
1261
+ # "quantity": "0.002",
1262
+ # "price": "0.073365",
1263
+ # "fee": "0.000000147",
1264
+ # "timestamp": "2018-04-28T18:39:55.345Z",
1265
+ # "taker": True
1266
+ # }
1267
+ #
1268
+ # fetchMyTrades swap and margin
1269
+ #
1270
+ # {
1271
+ # "id": 4718564,
1272
+ # "order_id": 58730811958,
1273
+ # "client_order_id": "475c47d97f867f09726186eb22b4c3d4",
1274
+ # "symbol": "BTCUSDT_PERP",
1275
+ # "side": "sell",
1276
+ # "quantity": "0.0001",
1277
+ # "price": "41118.51",
1278
+ # "fee": "0.002055925500",
1279
+ # "timestamp": "2022-03-17T05:23:17.795Z",
1280
+ # "taker": True,
1281
+ # "position_id": 2350122,
1282
+ # "pnl": "0.002255000000",
1283
+ # "liquidation": False
1284
+ # }
1285
+ #
1286
+ timestamp = self.parse8601(trade['timestamp'])
1287
+ marketId = self.safe_string(trade, 'symbol')
1288
+ market = self.safe_market(marketId, market)
1289
+ symbol = market['symbol']
1290
+ fee = None
1291
+ feeCostString = self.safe_string(trade, 'fee')
1292
+ taker = self.safe_value(trade, 'taker')
1293
+ takerOrMaker = None
1294
+ if taker is not None:
1295
+ takerOrMaker = 'taker' if taker else 'maker'
1296
+ else:
1297
+ takerOrMaker = 'taker' # the only case when `taker` field is missing, is public fetchTrades and it must be taker
1298
+ if feeCostString is not None:
1299
+ info = self.safe_value(market, 'info', {})
1300
+ feeCurrency = self.safe_string(info, 'fee_currency')
1301
+ feeCurrencyCode = self.safe_currency_code(feeCurrency)
1302
+ fee = {
1303
+ 'cost': feeCostString,
1304
+ 'currency': feeCurrencyCode,
1305
+ }
1306
+ # we use clientOrderId order id with self exchange intentionally
1307
+ # because most of their endpoints will require clientOrderId
1308
+ # explained here: https://github.com/ccxt/ccxt/issues/5674
1309
+ orderId = self.safe_string_2(trade, 'clientOrderId', 'client_order_id')
1310
+ priceString = self.safe_string(trade, 'price')
1311
+ amountString = self.safe_string_2(trade, 'quantity', 'qty')
1312
+ side = self.safe_string(trade, 'side')
1313
+ id = self.safe_string(trade, 'id')
1314
+ return self.safe_trade({
1315
+ 'info': trade,
1316
+ 'id': id,
1317
+ 'order': orderId,
1318
+ 'timestamp': timestamp,
1319
+ 'datetime': self.iso8601(timestamp),
1320
+ 'symbol': symbol,
1321
+ 'type': None,
1322
+ 'side': side,
1323
+ 'takerOrMaker': takerOrMaker,
1324
+ 'price': priceString,
1325
+ 'amount': amountString,
1326
+ 'cost': None,
1327
+ 'fee': fee,
1328
+ }, market)
1329
+
1330
+ async def fetch_transactions_helper(self, types, code, since, limit, params):
1331
+ await self.load_markets()
1332
+ request: dict = {
1333
+ 'types': types,
1334
+ }
1335
+ currency = None
1336
+ if code is not None:
1337
+ currency = self.currency(code)
1338
+ request['currencies'] = currency['id']
1339
+ if since is not None:
1340
+ request['from'] = self.iso8601(since)
1341
+ if limit is not None:
1342
+ request['limit'] = limit
1343
+ response = await self.privateGetWalletTransactions(self.extend(request, params))
1344
+ #
1345
+ # [
1346
+ # {
1347
+ # "id": "101609495",
1348
+ # "created_at": "2018-03-06T22:05:06.507Z",
1349
+ # "updated_at": "2018-03-06T22:11:45.03Z",
1350
+ # "status": "SUCCESS",
1351
+ # "type": "DEPOSIT",
1352
+ # "subtype": "BLOCKCHAIN",
1353
+ # "native": {
1354
+ # "tx_id": "e20b0965-4024-44d0-b63f-7fb8996a6706",
1355
+ # "index": "881652766",
1356
+ # "currency": "ETH",
1357
+ # "amount": "0.01418088",
1358
+ # "hash": "d95dbbff3f9234114f1211ab0ba2a94f03f394866fd5749d74a1edab80e6c5d3",
1359
+ # "address": "0xd9259302c32c0a0295d86a39185c9e14f6ba0a0d",
1360
+ # "confirmations": "20",
1361
+ # "senders": [
1362
+ # "0x243bec9256c9a3469da22103891465b47583d9f1"
1363
+ # ]
1364
+ # }
1365
+ # }
1366
+ # ]
1367
+ #
1368
+ return self.parse_transactions(response, currency, since, limit, params)
1369
+
1370
+ def parse_transaction_status(self, status: Str):
1371
+ statuses: dict = {
1372
+ 'PENDING': 'pending',
1373
+ 'FAILED': 'failed',
1374
+ 'SUCCESS': 'ok',
1375
+ }
1376
+ return self.safe_string(statuses, status, status)
1377
+
1378
+ def parse_transaction_type(self, type):
1379
+ types: dict = {
1380
+ 'DEPOSIT': 'deposit',
1381
+ 'WITHDRAW': 'withdrawal',
1382
+ }
1383
+ return self.safe_string(types, type, type)
1384
+
1385
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
1386
+ #
1387
+ # transaction
1388
+ #
1389
+ # {
1390
+ # "id": "101609495",
1391
+ # "created_at": "2018-03-06T22:05:06.507Z",
1392
+ # "updated_at": "2018-03-06T22:11:45.03Z",
1393
+ # "status": "SUCCESS",
1394
+ # "type": "DEPOSIT", # DEPOSIT, WITHDRAW, ..
1395
+ # "subtype": "BLOCKCHAIN",
1396
+ # "native": {
1397
+ # "tx_id": "e20b0965-4024-44d0-b63f-7fb8996a6706",
1398
+ # "index": "881652766",
1399
+ # "currency": "ETH",
1400
+ # "amount": "0.01418088",
1401
+ # "hash": "d95dbbff3f9234114f1211ab0ba2a94f03f394866fd5749d74a1edab80e6c5d3",
1402
+ # "address": "0xd9259302c32c0a0295d86a39185c9e14f6ba0a0d",
1403
+ # "confirmations": "20",
1404
+ # "senders": [
1405
+ # "0x243bec9256c9a3469da22103891465b47583d9f1"
1406
+ # ],
1407
+ # "fee": "1.22" # only for WITHDRAW
1408
+ # }
1409
+ # },
1410
+ # "operation_id": "084cfcd5-06b9-4826-882e-fdb75ec3625d", # only for WITHDRAW
1411
+ # "commit_risk": {}
1412
+ # withdraw
1413
+ #
1414
+ # {
1415
+ # "id":"084cfcd5-06b9-4826-882e-fdb75ec3625d"
1416
+ # }
1417
+ #
1418
+ id = self.safe_string_2(transaction, 'operation_id', 'id')
1419
+ timestamp = self.parse8601(self.safe_string(transaction, 'created_at'))
1420
+ updated = self.parse8601(self.safe_string(transaction, 'updated_at'))
1421
+ type = self.parse_transaction_type(self.safe_string(transaction, 'type'))
1422
+ status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
1423
+ native = self.safe_value(transaction, 'native', {})
1424
+ currencyId = self.safe_string(native, 'currency')
1425
+ code = self.safe_currency_code(currencyId)
1426
+ txhash = self.safe_string(native, 'hash')
1427
+ address = self.safe_string(native, 'address')
1428
+ addressTo = address
1429
+ tag = self.safe_string(native, 'payment_id')
1430
+ tagTo = tag
1431
+ sender = self.safe_value(native, 'senders')
1432
+ addressFrom = self.safe_string(sender, 0)
1433
+ amount = self.safe_number(native, 'amount')
1434
+ subType = self.safe_string(transaction, 'subtype')
1435
+ internal = subType == 'OFFCHAIN'
1436
+ # https://api.hitbtc.com/#check-if-offchain-is-available
1437
+ fee = {
1438
+ 'currency': None,
1439
+ 'cost': None,
1440
+ 'rate': None,
1441
+ }
1442
+ feeCost = self.safe_number(native, 'fee')
1443
+ if feeCost is not None:
1444
+ fee['currency'] = code
1445
+ fee['cost'] = feeCost
1446
+ return {
1447
+ 'info': transaction,
1448
+ 'id': id,
1449
+ 'txid': txhash,
1450
+ 'type': type,
1451
+ 'currency': code,
1452
+ 'network': None,
1453
+ 'amount': amount,
1454
+ 'status': status,
1455
+ 'timestamp': timestamp,
1456
+ 'datetime': self.iso8601(timestamp),
1457
+ 'address': address,
1458
+ 'addressFrom': addressFrom,
1459
+ 'addressTo': addressTo,
1460
+ 'tag': tag,
1461
+ 'tagFrom': None,
1462
+ 'tagTo': tagTo,
1463
+ 'updated': updated,
1464
+ 'comment': None,
1465
+ 'internal': internal,
1466
+ 'fee': fee,
1467
+ }
1468
+
1469
+ async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1470
+ """
1471
+ fetch history of deposits and withdrawals
1472
+ :see: https://api.hitbtc.com/#get-transactions-history
1473
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
1474
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
1475
+ :param int [limit]: max number of deposit/withdrawals to return, default is None
1476
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1477
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1478
+ """
1479
+ return await self.fetch_transactions_helper('DEPOSIT,WITHDRAW', code, since, limit, params)
1480
+
1481
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1482
+ """
1483
+ fetch all deposits made to an account
1484
+ :see: https://api.hitbtc.com/#get-transactions-history
1485
+ :param str code: unified currency code
1486
+ :param int [since]: the earliest time in ms to fetch deposits for
1487
+ :param int [limit]: the maximum number of deposits structures to retrieve
1488
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1489
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1490
+ """
1491
+ return await self.fetch_transactions_helper('DEPOSIT', code, since, limit, params)
1492
+
1493
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1494
+ """
1495
+ fetch all withdrawals made from an account
1496
+ :see: https://api.hitbtc.com/#get-transactions-history
1497
+ :param str code: unified currency code
1498
+ :param int [since]: the earliest time in ms to fetch withdrawals for
1499
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
1500
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1501
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1502
+ """
1503
+ return await self.fetch_transactions_helper('WITHDRAW', code, since, limit, params)
1504
+
1505
+ async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}):
1506
+ """
1507
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data for multiple markets
1508
+ :see: https://api.hitbtc.com/#order-books
1509
+ :param str[]|None symbols: list of unified market symbols, all symbols fetched if None, default is None
1510
+ :param int [limit]: max number of entries per orderbook to return, default is None
1511
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1512
+ :returns dict: a dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbol
1513
+ """
1514
+ await self.load_markets()
1515
+ request: dict = {}
1516
+ if symbols is not None:
1517
+ marketIdsInner = self.market_ids(symbols)
1518
+ request['symbols'] = ','.join(marketIdsInner)
1519
+ if limit is not None:
1520
+ request['depth'] = limit
1521
+ response = await self.publicGetPublicOrderbook(self.extend(request, params))
1522
+ result: dict = {}
1523
+ marketIds = list(response.keys())
1524
+ for i in range(0, len(marketIds)):
1525
+ marketId = marketIds[i]
1526
+ orderbook = response[marketId]
1527
+ symbol = self.safe_symbol(marketId)
1528
+ timestamp = self.parse8601(self.safe_string(orderbook, 'timestamp'))
1529
+ result[symbol] = self.parse_order_book(response[marketId], symbol, timestamp, 'bid', 'ask')
1530
+ return result
1531
+
1532
+ async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1533
+ """
1534
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1535
+ :see: https://api.hitbtc.com/#order-books
1536
+ :param str symbol: unified symbol of the market to fetch the order book for
1537
+ :param int [limit]: the maximum amount of order book entries to return
1538
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1539
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1540
+ """
1541
+ await self.load_markets()
1542
+ market = self.market(symbol)
1543
+ request: dict = {
1544
+ 'symbol': market['id'],
1545
+ }
1546
+ if limit is not None:
1547
+ request['depth'] = limit
1548
+ response = await self.publicGetPublicOrderbookSymbol(self.extend(request, params))
1549
+ timestamp = self.parse8601(self.safe_string(response, 'timestamp'))
1550
+ return self.parse_order_book(response, symbol, timestamp, 'bid', 'ask')
1551
+
1552
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
1553
+ #
1554
+ # {
1555
+ # "symbol":"ARVUSDT", # returned from fetchTradingFees only
1556
+ # "take_rate":"0.0009",
1557
+ # "make_rate":"0.0009"
1558
+ # }
1559
+ #
1560
+ taker = self.safe_number(fee, 'take_rate')
1561
+ maker = self.safe_number(fee, 'make_rate')
1562
+ marketId = self.safe_string(fee, 'symbol')
1563
+ symbol = self.safe_symbol(marketId, market)
1564
+ return {
1565
+ 'info': fee,
1566
+ 'symbol': symbol,
1567
+ 'taker': taker,
1568
+ 'maker': maker,
1569
+ 'percentage': None,
1570
+ 'tierBased': None,
1571
+ }
1572
+
1573
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
1574
+ """
1575
+ fetch the trading fees for a market
1576
+ :see: https://api.hitbtc.com/#get-trading-commission
1577
+ :see: https://api.hitbtc.com/#get-trading-commission-2
1578
+ :param str symbol: unified market symbol
1579
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1580
+ :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
1581
+ """
1582
+ await self.load_markets()
1583
+ market = self.market(symbol)
1584
+ request: dict = {
1585
+ 'symbol': market['id'],
1586
+ }
1587
+ response = None
1588
+ if market['type'] == 'spot':
1589
+ response = await self.privateGetSpotFeeSymbol(self.extend(request, params))
1590
+ elif market['type'] == 'swap':
1591
+ response = await self.privateGetFuturesFeeSymbol(self.extend(request, params))
1592
+ else:
1593
+ raise NotSupported(self.id + ' fetchTradingFee() not support self market type')
1594
+ #
1595
+ # {
1596
+ # "take_rate":"0.0009",
1597
+ # "make_rate":"0.0009"
1598
+ # }
1599
+ #
1600
+ return self.parse_trading_fee(response, market)
1601
+
1602
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
1603
+ """
1604
+ fetch the trading fees for multiple markets
1605
+ :see: https://api.hitbtc.com/#get-all-trading-commissions
1606
+ :see: https://api.hitbtc.com/#get-all-trading-commissions-2
1607
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1608
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1609
+ """
1610
+ await self.load_markets()
1611
+ marketType, query = self.handle_market_type_and_params('fetchTradingFees', None, params)
1612
+ response = None
1613
+ if marketType == 'spot':
1614
+ response = await self.privateGetSpotFee(query)
1615
+ elif marketType == 'swap':
1616
+ response = await self.privateGetFuturesFee(query)
1617
+ else:
1618
+ raise NotSupported(self.id + ' fetchTradingFees() not support self market type')
1619
+ #
1620
+ # [
1621
+ # {
1622
+ # "symbol":"ARVUSDT",
1623
+ # "take_rate":"0.0009",
1624
+ # "make_rate":"0.0009"
1625
+ # }
1626
+ # ]
1627
+ #
1628
+ result: dict = {}
1629
+ for i in range(0, len(response)):
1630
+ fee = self.parse_trading_fee(response[i])
1631
+ symbol = fee['symbol']
1632
+ result[symbol] = fee
1633
+ return result
1634
+
1635
+ async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1636
+ """
1637
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1638
+ :see: https://api.hitbtc.com/#candles
1639
+ :see: https://api.hitbtc.com/#futures-index-price-candles
1640
+ :see: https://api.hitbtc.com/#futures-mark-price-candles
1641
+ :see: https://api.hitbtc.com/#futures-premium-index-candles
1642
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1643
+ :param str timeframe: the length of time each candle represents
1644
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1645
+ :param int [limit]: the maximum amount of candles to fetch
1646
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1647
+ :param int [params.until]: timestamp in ms of the latest funding rate
1648
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1649
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1650
+ """
1651
+ await self.load_markets()
1652
+ paginate = False
1653
+ paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
1654
+ if paginate:
1655
+ return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000)
1656
+ market = self.market(symbol)
1657
+ request: dict = {
1658
+ 'symbol': market['id'],
1659
+ 'period': self.safe_string(self.timeframes, timeframe, timeframe),
1660
+ }
1661
+ if since is not None:
1662
+ request['from'] = self.iso8601(since)
1663
+ request, params = self.handle_until_option('until', request, params)
1664
+ if limit is not None:
1665
+ request['limit'] = min(limit, 1000)
1666
+ price = self.safe_string(params, 'price')
1667
+ params = self.omit(params, 'price')
1668
+ response = None
1669
+ if price == 'mark':
1670
+ response = await self.publicGetPublicFuturesCandlesMarkPriceSymbol(self.extend(request, params))
1671
+ elif price == 'index':
1672
+ response = await self.publicGetPublicFuturesCandlesIndexPriceSymbol(self.extend(request, params))
1673
+ elif price == 'premiumIndex':
1674
+ response = await self.publicGetPublicFuturesCandlesPremiumIndexSymbol(self.extend(request, params))
1675
+ else:
1676
+ response = await self.publicGetPublicCandlesSymbol(self.extend(request, params))
1677
+ #
1678
+ # Spot and Swap
1679
+ #
1680
+ # [
1681
+ # {
1682
+ # "timestamp": "2021-10-25T07:38:00.000Z",
1683
+ # "open": "4173.391",
1684
+ # "close": "4170.923",
1685
+ # "min": "4170.923",
1686
+ # "max": "4173.986",
1687
+ # "volume": "0.1879",
1688
+ # "volume_quote": "784.2517846"
1689
+ # }
1690
+ # ]
1691
+ #
1692
+ # Mark, Index and Premium Index
1693
+ #
1694
+ # [
1695
+ # {
1696
+ # "timestamp": "2022-04-01T01:28:00.000Z",
1697
+ # "open": "45146.39",
1698
+ # "close": "45219.43",
1699
+ # "min": "45146.39",
1700
+ # "max": "45219.43"
1701
+ # },
1702
+ # ]
1703
+ #
1704
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)
1705
+
1706
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1707
+ #
1708
+ # Spot and Swap
1709
+ #
1710
+ # {
1711
+ # "timestamp":"2015-08-20T19:01:00.000Z",
1712
+ # "open":"0.006",
1713
+ # "close":"0.006",
1714
+ # "min":"0.006",
1715
+ # "max":"0.006",
1716
+ # "volume":"0.003",
1717
+ # "volume_quote":"0.000018"
1718
+ # }
1719
+ #
1720
+ # Mark, Index and Premium Index
1721
+ #
1722
+ # {
1723
+ # "timestamp": "2022-04-01T01:28:00.000Z",
1724
+ # "open": "45146.39",
1725
+ # "close": "45219.43",
1726
+ # "min": "45146.39",
1727
+ # "max": "45219.43"
1728
+ # },
1729
+ #
1730
+ return [
1731
+ self.parse8601(self.safe_string(ohlcv, 'timestamp')),
1732
+ self.safe_number(ohlcv, 'open'),
1733
+ self.safe_number(ohlcv, 'max'),
1734
+ self.safe_number(ohlcv, 'min'),
1735
+ self.safe_number(ohlcv, 'close'),
1736
+ self.safe_number(ohlcv, 'volume'),
1737
+ ]
1738
+
1739
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1740
+ """
1741
+ fetches information on multiple closed orders made by the user
1742
+ :see: https://api.hitbtc.com/#spot-orders-history
1743
+ :see: https://api.hitbtc.com/#futures-orders-history
1744
+ :see: https://api.hitbtc.com/#margin-orders-history
1745
+ :param str symbol: unified market symbol of the market orders were made in
1746
+ :param int [since]: the earliest time in ms to fetch orders for
1747
+ :param int [limit]: the maximum number of order structures to retrieve
1748
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1749
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1750
+ :param bool [params.margin]: True for fetching margin orders
1751
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1752
+ """
1753
+ await self.load_markets()
1754
+ market = None
1755
+ request: dict = {}
1756
+ if symbol is not None:
1757
+ market = self.market(symbol)
1758
+ request['symbol'] = market['id']
1759
+ if since is not None:
1760
+ request['from'] = self.iso8601(since)
1761
+ if limit is not None:
1762
+ request['limit'] = limit
1763
+ marketType = None
1764
+ marginMode = None
1765
+ marketType, params = self.handle_market_type_and_params('fetchClosedOrders', market, params)
1766
+ marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
1767
+ params = self.omit(params, ['marginMode', 'margin'])
1768
+ response = None
1769
+ if marginMode is not None:
1770
+ response = await self.privateGetMarginHistoryOrder(self.extend(request, params))
1771
+ else:
1772
+ if marketType == 'spot':
1773
+ response = await self.privateGetSpotHistoryOrder(self.extend(request, params))
1774
+ elif marketType == 'swap':
1775
+ response = await self.privateGetFuturesHistoryOrder(self.extend(request, params))
1776
+ elif marketType == 'margin':
1777
+ response = await self.privateGetMarginHistoryOrder(self.extend(request, params))
1778
+ else:
1779
+ raise NotSupported(self.id + ' fetchClosedOrders() not support self market type')
1780
+ parsed = self.parse_orders(response, market, since, limit)
1781
+ return self.filter_by_array(parsed, 'status', ['closed', 'canceled'], False)
1782
+
1783
+ async def fetch_order(self, id: str, symbol: Str = None, params={}):
1784
+ """
1785
+ fetches information on an order made by the user
1786
+ :see: https://api.hitbtc.com/#spot-orders-history
1787
+ :see: https://api.hitbtc.com/#futures-orders-history
1788
+ :see: https://api.hitbtc.com/#margin-orders-history
1789
+ :param str symbol: unified symbol of the market the order was made in
1790
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1791
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1792
+ :param bool [params.margin]: True for fetching a margin order
1793
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1794
+ """
1795
+ await self.load_markets()
1796
+ market = None
1797
+ if symbol is not None:
1798
+ market = self.market(symbol)
1799
+ request: dict = {
1800
+ 'client_order_id': id,
1801
+ }
1802
+ marketType = None
1803
+ marginMode = None
1804
+ marketType, params = self.handle_market_type_and_params('fetchOrder', market, params)
1805
+ marginMode, params = self.handle_margin_mode_and_params('fetchOrder', params)
1806
+ params = self.omit(params, ['marginMode', 'margin'])
1807
+ response = None
1808
+ if marginMode is not None:
1809
+ response = await self.privateGetMarginHistoryOrder(self.extend(request, params))
1810
+ else:
1811
+ if marketType == 'spot':
1812
+ response = await self.privateGetSpotHistoryOrder(self.extend(request, params))
1813
+ elif marketType == 'swap':
1814
+ response = await self.privateGetFuturesHistoryOrder(self.extend(request, params))
1815
+ elif marketType == 'margin':
1816
+ response = await self.privateGetMarginHistoryOrder(self.extend(request, params))
1817
+ else:
1818
+ raise NotSupported(self.id + ' fetchOrder() not support self market type')
1819
+ #
1820
+ # [
1821
+ # {
1822
+ # "id": "685965182082",
1823
+ # "client_order_id": "B3CBm9uGg9oYQlw96bBSEt38-6gbgBO0",
1824
+ # "symbol": "BTCUSDT",
1825
+ # "side": "buy",
1826
+ # "status": "new",
1827
+ # "type": "limit",
1828
+ # "time_in_force": "GTC",
1829
+ # "quantity": "0.00010",
1830
+ # "quantity_cumulative": "0",
1831
+ # "price": "50000.00",
1832
+ # "price_average": "0",
1833
+ # "created_at": "2021-10-26T11:40:09.287Z",
1834
+ # "updated_at": "2021-10-26T11:40:09.287Z"
1835
+ # }
1836
+ # ]
1837
+ #
1838
+ order = self.safe_dict(response, 0)
1839
+ return self.parse_order(order, market)
1840
+
1841
+ async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1842
+ """
1843
+ fetch all the trades made from a single order
1844
+ :see: https://api.hitbtc.com/#spot-trades-history
1845
+ :see: https://api.hitbtc.com/#futures-trades-history
1846
+ :see: https://api.hitbtc.com/#margin-trades-history
1847
+ :param str id: order id
1848
+ :param str symbol: unified market symbol
1849
+ :param int [since]: the earliest time in ms to fetch trades for
1850
+ :param int [limit]: the maximum number of trades to retrieve
1851
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1852
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1853
+ :param bool [params.margin]: True for fetching margin trades
1854
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1855
+ """
1856
+ await self.load_markets()
1857
+ market = None
1858
+ if symbol is not None:
1859
+ market = self.market(symbol)
1860
+ request: dict = {
1861
+ 'order_id': id, # exchange assigned order id to the client order id
1862
+ }
1863
+ marketType = None
1864
+ marginMode = None
1865
+ marketType, params = self.handle_market_type_and_params('fetchOrderTrades', market, params)
1866
+ marginMode, params = self.handle_margin_mode_and_params('fetchOrderTrades', params)
1867
+ params = self.omit(params, ['marginMode', 'margin'])
1868
+ response = None
1869
+ if marginMode is not None:
1870
+ response = await self.privateGetMarginHistoryTrade(self.extend(request, params))
1871
+ else:
1872
+ if marketType == 'spot':
1873
+ response = await self.privateGetSpotHistoryTrade(self.extend(request, params))
1874
+ elif marketType == 'swap':
1875
+ response = await self.privateGetFuturesHistoryTrade(self.extend(request, params))
1876
+ elif marketType == 'margin':
1877
+ response = await self.privateGetMarginHistoryTrade(self.extend(request, params))
1878
+ else:
1879
+ raise NotSupported(self.id + ' fetchOrderTrades() not support self market type')
1880
+ #
1881
+ # Spot
1882
+ #
1883
+ # [
1884
+ # {
1885
+ # "id": 1393448977,
1886
+ # "order_id": 653496804534,
1887
+ # "client_order_id": "065f6f0ff9d54547848454182263d7b4",
1888
+ # "symbol": "DICEETH",
1889
+ # "side": "buy",
1890
+ # "quantity": "1.4",
1891
+ # "price": "0.00261455",
1892
+ # "fee": "0.000003294333",
1893
+ # "timestamp": "2021-09-19T05:35:56.601Z",
1894
+ # "taker": True
1895
+ # }
1896
+ # ]
1897
+ #
1898
+ # Swap and Margin
1899
+ #
1900
+ # [
1901
+ # {
1902
+ # "id": 4718551,
1903
+ # "order_id": 58730748700,
1904
+ # "client_order_id": "dcbcd8549e3445ee922665946002ef67",
1905
+ # "symbol": "BTCUSDT_PERP",
1906
+ # "side": "buy",
1907
+ # "quantity": "0.0001",
1908
+ # "price": "41095.96",
1909
+ # "fee": "0.002054798000",
1910
+ # "timestamp": "2022-03-17T05:23:02.217Z",
1911
+ # "taker": True,
1912
+ # "position_id": 2350122,
1913
+ # "pnl": "0",
1914
+ # "liquidation": False
1915
+ # }
1916
+ # ]
1917
+ #
1918
+ return self.parse_trades(response, market, since, limit)
1919
+
1920
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1921
+ """
1922
+ fetch all unfilled currently open orders
1923
+ :see: https://api.hitbtc.com/#get-all-active-spot-orders
1924
+ :see: https://api.hitbtc.com/#get-active-futures-orders
1925
+ :see: https://api.hitbtc.com/#get-active-margin-orders
1926
+ :param str symbol: unified market symbol
1927
+ :param int [since]: the earliest time in ms to fetch open orders for
1928
+ :param int [limit]: the maximum number of open orders structures to retrieve
1929
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1930
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1931
+ :param bool [params.margin]: True for fetching open margin orders
1932
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1933
+ """
1934
+ await self.load_markets()
1935
+ market = None
1936
+ request: dict = {}
1937
+ if symbol is not None:
1938
+ market = self.market(symbol)
1939
+ request['symbol'] = market['id']
1940
+ marketType = None
1941
+ marginMode = None
1942
+ marketType, params = self.handle_market_type_and_params('fetchOpenOrders', market, params)
1943
+ marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
1944
+ params = self.omit(params, ['marginMode', 'margin'])
1945
+ response = None
1946
+ if marginMode is not None:
1947
+ response = await self.privateGetMarginOrder(self.extend(request, params))
1948
+ else:
1949
+ if marketType == 'spot':
1950
+ response = await self.privateGetSpotOrder(self.extend(request, params))
1951
+ elif marketType == 'swap':
1952
+ response = await self.privateGetFuturesOrder(self.extend(request, params))
1953
+ elif marketType == 'margin':
1954
+ response = await self.privateGetMarginOrder(self.extend(request, params))
1955
+ else:
1956
+ raise NotSupported(self.id + ' fetchOpenOrders() not support self market type')
1957
+ #
1958
+ # [
1959
+ # {
1960
+ # "id": "488953123149",
1961
+ # "client_order_id": "103ad305301e4c3590045b13de15b36e",
1962
+ # "symbol": "BTCUSDT",
1963
+ # "side": "buy",
1964
+ # "status": "new",
1965
+ # "type": "limit",
1966
+ # "time_in_force": "GTC",
1967
+ # "quantity": "0.00001",
1968
+ # "quantity_cumulative": "0",
1969
+ # "price": "0.01",
1970
+ # "post_only": False,
1971
+ # "created_at": "2021-04-13T13:06:16.567Z",
1972
+ # "updated_at": "2021-04-13T13:06:16.567Z"
1973
+ # }
1974
+ # ]
1975
+ #
1976
+ return self.parse_orders(response, market, since, limit)
1977
+
1978
+ async def fetch_open_order(self, id: str, symbol: Str = None, params={}):
1979
+ """
1980
+ fetch an open order by it's id
1981
+ :see: https://api.hitbtc.com/#get-active-spot-order
1982
+ :see: https://api.hitbtc.com/#get-active-futures-order
1983
+ :see: https://api.hitbtc.com/#get-active-margin-order
1984
+ :param str id: order id
1985
+ :param str symbol: unified market symbol, default is None
1986
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1987
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
1988
+ :param bool [params.margin]: True for fetching an open margin order
1989
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1990
+ """
1991
+ await self.load_markets()
1992
+ market = None
1993
+ if symbol is not None:
1994
+ market = self.market(symbol)
1995
+ request: dict = {
1996
+ 'client_order_id': id,
1997
+ }
1998
+ marketType = None
1999
+ marginMode = None
2000
+ marketType, params = self.handle_market_type_and_params('fetchOpenOrder', market, params)
2001
+ marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrder', params)
2002
+ params = self.omit(params, ['marginMode', 'margin'])
2003
+ response = None
2004
+ if marginMode is not None:
2005
+ response = await self.privateGetMarginOrderClientOrderId(self.extend(request, params))
2006
+ else:
2007
+ if marketType == 'spot':
2008
+ response = await self.privateGetSpotOrderClientOrderId(self.extend(request, params))
2009
+ elif marketType == 'swap':
2010
+ response = await self.privateGetFuturesOrderClientOrderId(self.extend(request, params))
2011
+ elif marketType == 'margin':
2012
+ response = await self.privateGetMarginOrderClientOrderId(self.extend(request, params))
2013
+ else:
2014
+ raise NotSupported(self.id + ' fetchOpenOrder() not support self market type')
2015
+ return self.parse_order(response, market)
2016
+
2017
+ async def cancel_all_orders(self, symbol: Str = None, params={}):
2018
+ """
2019
+ cancel all open orders
2020
+ :see: https://api.hitbtc.com/#cancel-all-spot-orders
2021
+ :see: https://api.hitbtc.com/#cancel-futures-orders
2022
+ :see: https://api.hitbtc.com/#cancel-all-margin-orders
2023
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
2024
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2025
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
2026
+ :param bool [params.margin]: True for canceling margin orders
2027
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2028
+ """
2029
+ await self.load_markets()
2030
+ market = None
2031
+ request: dict = {}
2032
+ if symbol is not None:
2033
+ market = self.market(symbol)
2034
+ request['symbol'] = market['id']
2035
+ marketType = None
2036
+ marginMode = None
2037
+ marketType, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
2038
+ marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
2039
+ params = self.omit(params, ['marginMode', 'margin'])
2040
+ response = None
2041
+ if marginMode is not None:
2042
+ response = await self.privateDeleteMarginOrder(self.extend(request, params))
2043
+ else:
2044
+ if marketType == 'spot':
2045
+ response = await self.privateDeleteSpotOrder(self.extend(request, params))
2046
+ elif marketType == 'swap':
2047
+ response = await self.privateDeleteFuturesOrder(self.extend(request, params))
2048
+ elif marketType == 'margin':
2049
+ response = await self.privateDeleteMarginOrder(self.extend(request, params))
2050
+ else:
2051
+ raise NotSupported(self.id + ' cancelAllOrders() not support self market type')
2052
+ return self.parse_orders(response, market)
2053
+
2054
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
2055
+ """
2056
+ cancels an open order
2057
+ :see: https://api.hitbtc.com/#cancel-spot-order
2058
+ :see: https://api.hitbtc.com/#cancel-futures-order
2059
+ :see: https://api.hitbtc.com/#cancel-margin-order
2060
+ :param str id: order id
2061
+ :param str symbol: unified symbol of the market the order was made in
2062
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2063
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
2064
+ :param bool [params.margin]: True for canceling a margin order
2065
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2066
+ """
2067
+ await self.load_markets()
2068
+ market = None
2069
+ request: dict = {
2070
+ 'client_order_id': id,
2071
+ }
2072
+ if symbol is not None:
2073
+ market = self.market(symbol)
2074
+ marketType = None
2075
+ marginMode = None
2076
+ marketType, params = self.handle_market_type_and_params('cancelOrder', market, params)
2077
+ marginMode, params = self.handle_margin_mode_and_params('cancelOrder', params)
2078
+ params = self.omit(params, ['marginMode', 'margin'])
2079
+ response = None
2080
+ if marginMode is not None:
2081
+ response = await self.privateDeleteMarginOrderClientOrderId(self.extend(request, params))
2082
+ else:
2083
+ if marketType == 'spot':
2084
+ response = await self.privateDeleteSpotOrderClientOrderId(self.extend(request, params))
2085
+ elif marketType == 'swap':
2086
+ response = await self.privateDeleteFuturesOrderClientOrderId(self.extend(request, params))
2087
+ elif marketType == 'margin':
2088
+ response = await self.privateDeleteMarginOrderClientOrderId(self.extend(request, params))
2089
+ else:
2090
+ raise NotSupported(self.id + ' cancelOrder() not support self market type')
2091
+ return self.parse_order(response, market)
2092
+
2093
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
2094
+ await self.load_markets()
2095
+ market = None
2096
+ request: dict = {
2097
+ 'client_order_id': id,
2098
+ 'quantity': self.amount_to_precision(symbol, amount),
2099
+ }
2100
+ if (type == 'limit') or (type == 'stopLimit'):
2101
+ if price is None:
2102
+ raise ExchangeError(self.id + ' editOrder() limit order requires price')
2103
+ request['price'] = self.price_to_precision(symbol, price)
2104
+ if symbol is not None:
2105
+ market = self.market(symbol)
2106
+ marketType = None
2107
+ marginMode = None
2108
+ marketType, params = self.handle_market_type_and_params('editOrder', market, params)
2109
+ marginMode, params = self.handle_margin_mode_and_params('editOrder', params)
2110
+ params = self.omit(params, ['marginMode', 'margin'])
2111
+ response = None
2112
+ if marginMode is not None:
2113
+ response = await self.privatePatchMarginOrderClientOrderId(self.extend(request, params))
2114
+ else:
2115
+ if marketType == 'spot':
2116
+ response = await self.privatePatchSpotOrderClientOrderId(self.extend(request, params))
2117
+ elif marketType == 'swap':
2118
+ response = await self.privatePatchFuturesOrderClientOrderId(self.extend(request, params))
2119
+ elif marketType == 'margin':
2120
+ response = await self.privatePatchMarginOrderClientOrderId(self.extend(request, params))
2121
+ else:
2122
+ raise NotSupported(self.id + ' editOrder() not support self market type')
2123
+ return self.parse_order(response, market)
2124
+
2125
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2126
+ """
2127
+ create a trade order
2128
+ :see: https://api.hitbtc.com/#create-new-spot-order
2129
+ :see: https://api.hitbtc.com/#create-margin-order
2130
+ :see: https://api.hitbtc.com/#create-futures-order
2131
+ :param str symbol: unified symbol of the market to create an order in
2132
+ :param str type: 'market' or 'limit'
2133
+ :param str side: 'buy' or 'sell'
2134
+ :param float amount: how much of currency you want to trade in units of base currency
2135
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2136
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2137
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported for spot-margin, swap supports both, default is 'cross'
2138
+ :param bool [params.margin]: True for creating a margin order
2139
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
2140
+ :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
2141
+ :param str [params.timeInForce]: "GTC", "IOC", "FOK", "Day", "GTD"
2142
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2143
+ """
2144
+ await self.load_markets()
2145
+ market = self.market(symbol)
2146
+ request = None
2147
+ marketType = None
2148
+ marketType, params = self.handle_market_type_and_params('createOrder', market, params)
2149
+ marginMode = None
2150
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
2151
+ request, params = self.create_order_request(market, marketType, type, side, amount, price, marginMode, params)
2152
+ response = None
2153
+ if marketType == 'swap':
2154
+ response = await self.privatePostFuturesOrder(self.extend(request, params))
2155
+ elif (marketType == 'margin') or (marginMode is not None):
2156
+ response = await self.privatePostMarginOrder(self.extend(request, params))
2157
+ else:
2158
+ response = await self.privatePostSpotOrder(self.extend(request, params))
2159
+ return self.parse_order(response, market)
2160
+
2161
+ def create_order_request(self, market: object, marketType: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, marginMode: Str = None, params={}):
2162
+ isLimit = (type == 'limit')
2163
+ reduceOnly = self.safe_value(params, 'reduceOnly')
2164
+ timeInForce = self.safe_string(params, 'timeInForce')
2165
+ triggerPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'stop_price'])
2166
+ isPostOnly = self.is_post_only(type == 'market', None, params)
2167
+ request: dict = {
2168
+ 'type': type,
2169
+ 'side': side,
2170
+ 'quantity': self.amount_to_precision(market['symbol'], amount),
2171
+ 'symbol': market['id'],
2172
+ # 'client_order_id': 'r42gdPjNMZN-H_xs8RKl2wljg_dfgdg4', # Optional
2173
+ # 'time_in_force': 'GTC', # Optional GTC, IOC, FOK, Day, GTD
2174
+ # 'price': self.price_to_precision(symbol, price), # Required if type is limit, stopLimit, or takeProfitLimit
2175
+ # 'stop_price': self.safe_number(params, 'stop_price'), # Required if type is stopLimit, stopMarket, takeProfitLimit, takeProfitMarket
2176
+ # 'expire_time': '2021-06-15T17:01:05.092Z', # Required if timeInForce is GTD
2177
+ # 'strict_validate': False,
2178
+ # 'post_only': False, # Optional
2179
+ # 'reduce_only': False, # Optional
2180
+ # 'display_quantity': '0', # Optional
2181
+ # 'take_rate': 0.001, # Optional
2182
+ # 'make_rate': 0.001, # Optional
2183
+ }
2184
+ if reduceOnly is not None:
2185
+ if (market['type'] != 'swap') and (market['type'] != 'margin'):
2186
+ raise InvalidOrder(self.id + ' createOrder() does not support reduce_only for ' + market['type'] + ' orders, reduce_only orders are supported for swap and margin markets only')
2187
+ if reduceOnly is True:
2188
+ request['reduce_only'] = reduceOnly
2189
+ if isPostOnly:
2190
+ request['post_only'] = True
2191
+ if timeInForce is not None:
2192
+ request['time_in_force'] = timeInForce
2193
+ if isLimit or (type == 'stopLimit') or (type == 'takeProfitLimit'):
2194
+ if price is None:
2195
+ raise ExchangeError(self.id + ' createOrder() requires a price argument for limit orders')
2196
+ request['price'] = self.price_to_precision(market['symbol'], price)
2197
+ if (timeInForce == 'GTD'):
2198
+ expireTime = self.safe_string(params, 'expire_time')
2199
+ if expireTime is None:
2200
+ raise ExchangeError(self.id + ' createOrder() requires an expire_time parameter for a GTD order')
2201
+ if triggerPrice is not None:
2202
+ request['stop_price'] = self.price_to_precision(market['symbol'], triggerPrice)
2203
+ if isLimit:
2204
+ request['type'] = 'stopLimit'
2205
+ elif type == 'market':
2206
+ request['type'] = 'stopMarket'
2207
+ elif (type == 'stopLimit') or (type == 'stopMarket') or (type == 'takeProfitLimit') or (type == 'takeProfitMarket'):
2208
+ raise ExchangeError(self.id + ' createOrder() requires a stopPrice parameter for stop-loss and take-profit orders')
2209
+ params = self.omit(params, ['triggerPrice', 'timeInForce', 'stopPrice', 'stop_price', 'reduceOnly', 'postOnly'])
2210
+ if marketType == 'swap':
2211
+ # set default margin mode to cross
2212
+ if marginMode is None:
2213
+ marginMode = 'cross'
2214
+ request['margin_mode'] = marginMode
2215
+ return [request, params]
2216
+
2217
+ def parse_order_status(self, status: Str):
2218
+ statuses: dict = {
2219
+ 'new': 'open',
2220
+ 'suspended': 'open',
2221
+ 'partiallyFilled': 'open',
2222
+ 'filled': 'closed',
2223
+ 'canceled': 'canceled',
2224
+ 'expired': 'failed',
2225
+ }
2226
+ return self.safe_string(statuses, status, status)
2227
+
2228
+ def parse_order(self, order: dict, market: Market = None) -> Order:
2229
+ #
2230
+ # limit
2231
+ # {
2232
+ # "id": 488953123149,
2233
+ # "client_order_id": "103ad305301e4c3590045b13de15b36e",
2234
+ # "symbol": "BTCUSDT",
2235
+ # "side": "buy",
2236
+ # "status": "new",
2237
+ # "type": "limit",
2238
+ # "time_in_force": "GTC",
2239
+ # "quantity": "0.00001",
2240
+ # "quantity_cumulative": "0",
2241
+ # "price": "0.01",
2242
+ # "price_average": "0.01",
2243
+ # "post_only": False,
2244
+ # "created_at": "2021-04-13T13:06:16.567Z",
2245
+ # "updated_at": "2021-04-13T13:06:16.567Z"
2246
+ # }
2247
+ #
2248
+ # market
2249
+ # {
2250
+ # "id": "685877626834",
2251
+ # "client_order_id": "Yshl7G-EjaREyXQYaGbsmdtVbW-nzQwu",
2252
+ # "symbol": "BTCUSDT",
2253
+ # "side": "buy",
2254
+ # "status": "filled",
2255
+ # "type": "market",
2256
+ # "time_in_force": "GTC",
2257
+ # "quantity": "0.00010",
2258
+ # "quantity_cumulative": "0.00010",
2259
+ # "post_only": False,
2260
+ # "created_at": "2021-10-26T08:55:55.1Z",
2261
+ # "updated_at": "2021-10-26T08:55:55.1Z",
2262
+ # "trades": [
2263
+ # {
2264
+ # "id": "1437229630",
2265
+ # "position_id": "0",
2266
+ # "quantity": "0.00010",
2267
+ # "price": "62884.78",
2268
+ # "fee": "0.005659630200",
2269
+ # "timestamp": "2021-10-26T08:55:55.1Z",
2270
+ # "taker": True
2271
+ # }
2272
+ # ]
2273
+ # }
2274
+ #
2275
+ # swap and margin
2276
+ #
2277
+ # {
2278
+ # "id": 58418961892,
2279
+ # "client_order_id": "r42gdPjNMZN-H_xs8RKl2wljg_dfgdg4",
2280
+ # "symbol": "BTCUSDT_PERP",
2281
+ # "side": "buy",
2282
+ # "status": "new",
2283
+ # "type": "limit",
2284
+ # "time_in_force": "GTC",
2285
+ # "quantity": "0.0005",
2286
+ # "quantity_cumulative": "0",
2287
+ # "price": "30000.00",
2288
+ # "post_only": False,
2289
+ # "reduce_only": False,
2290
+ # "created_at": "2022-03-16T08:16:53.039Z",
2291
+ # "updated_at": "2022-03-16T08:16:53.039Z"
2292
+ # }
2293
+ #
2294
+ id = self.safe_string(order, 'client_order_id')
2295
+ # we use clientOrderId order id with self exchange intentionally
2296
+ # because most of their endpoints will require clientOrderId
2297
+ # explained here: https://github.com/ccxt/ccxt/issues/5674
2298
+ side = self.safe_string(order, 'side')
2299
+ type = self.safe_string(order, 'type')
2300
+ amount = self.safe_string(order, 'quantity')
2301
+ price = self.safe_string(order, 'price')
2302
+ average = self.safe_string(order, 'price_average')
2303
+ created = self.safe_string(order, 'created_at')
2304
+ timestamp = self.parse8601(created)
2305
+ updated = self.safe_string(order, 'updated_at')
2306
+ lastTradeTimestamp = None
2307
+ if updated != created:
2308
+ lastTradeTimestamp = self.parse8601(updated)
2309
+ filled = self.safe_string(order, 'quantity_cumulative')
2310
+ status = self.parse_order_status(self.safe_string(order, 'status'))
2311
+ marketId = self.safe_string(order, 'symbol')
2312
+ market = self.safe_market(marketId, market)
2313
+ symbol = market['symbol']
2314
+ postOnly = self.safe_value(order, 'post_only')
2315
+ timeInForce = self.safe_string(order, 'time_in_force')
2316
+ rawTrades = self.safe_value(order, 'trades')
2317
+ stopPrice = self.safe_string(order, 'stop_price')
2318
+ return self.safe_order({
2319
+ 'info': order,
2320
+ 'id': id,
2321
+ 'clientOrderId': id,
2322
+ 'timestamp': timestamp,
2323
+ 'datetime': self.iso8601(timestamp),
2324
+ 'lastTradeTimestamp': lastTradeTimestamp,
2325
+ 'lastUpdateTimestamp': lastTradeTimestamp,
2326
+ 'symbol': symbol,
2327
+ 'price': price,
2328
+ 'amount': amount,
2329
+ 'type': type,
2330
+ 'side': side,
2331
+ 'timeInForce': timeInForce,
2332
+ 'postOnly': postOnly,
2333
+ 'reduceOnly': self.safe_value(order, 'reduce_only'),
2334
+ 'filled': filled,
2335
+ 'remaining': None,
2336
+ 'cost': None,
2337
+ 'status': status,
2338
+ 'average': average,
2339
+ 'trades': rawTrades,
2340
+ 'fee': None,
2341
+ 'stopPrice': stopPrice,
2342
+ 'triggerPrice': stopPrice,
2343
+ 'takeProfitPrice': None,
2344
+ 'stopLossPrice': None,
2345
+ }, market)
2346
+
2347
+ async def fetch_margin_modes(self, symbols: List[Str] = None, params={}) -> MarginModes:
2348
+ """
2349
+ fetches margin mode of the user
2350
+ :see: https://api.hitbtc.com/#get-margin-position-parameters
2351
+ :see: https://api.hitbtc.com/#get-futures-position-parameters
2352
+ :param str symbol: unified symbol of the market the order was made in
2353
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2354
+ :returns dict: a list of `margin mode structures <https://docs.ccxt.com/#/?id=margin-mode-structure>`
2355
+ """
2356
+ await self.load_markets()
2357
+ market = None
2358
+ if symbols is not None:
2359
+ symbols = self.market_symbols(symbols)
2360
+ market = self.market(symbols[0])
2361
+ marketType = None
2362
+ marketType, params = self.handle_market_type_and_params('fetchMarginMode', market, params)
2363
+ response = None
2364
+ if marketType == 'margin':
2365
+ response = await self.privateGetMarginConfig(params)
2366
+ #
2367
+ # {
2368
+ # "config": [{
2369
+ # "symbol": "BTCUSD",
2370
+ # "margin_call_leverage_mul": "1.50",
2371
+ # "liquidation_leverage_mul": "2.00",
2372
+ # "max_initial_leverage": "10.00",
2373
+ # "margin_mode": "Isolated",
2374
+ # "force_close_fee": "0.05",
2375
+ # "enabled": True,
2376
+ # "active": True,
2377
+ # "limit_base": "50000.00",
2378
+ # "limit_power": "2.2",
2379
+ # "unlimited_threshold": "10.0"
2380
+ # }]
2381
+ # }
2382
+ #
2383
+ elif marketType == 'swap':
2384
+ response = await self.privateGetFuturesConfig(params)
2385
+ #
2386
+ # {
2387
+ # "config": [{
2388
+ # "symbol": "BTCUSD_PERP",
2389
+ # "margin_call_leverage_mul": "1.20",
2390
+ # "liquidation_leverage_mul": "2.00",
2391
+ # "max_initial_leverage": "100.00",
2392
+ # "margin_mode": "Isolated",
2393
+ # "force_close_fee": "0.001",
2394
+ # "enabled": True,
2395
+ # "active": False,
2396
+ # "limit_base": "5000000.000000000000",
2397
+ # "limit_power": "1.25",
2398
+ # "unlimited_threshold": "2.00"
2399
+ # }]
2400
+ # }
2401
+ #
2402
+ else:
2403
+ raise BadSymbol(self.id + ' fetchMarginModes() supports swap contracts and margin only')
2404
+ config = self.safe_list(response, 'config', [])
2405
+ return self.parse_margin_modes(config, symbols, 'symbol')
2406
+
2407
+ def parse_margin_mode(self, marginMode: dict, market=None) -> MarginMode:
2408
+ marketId = self.safe_string(marginMode, 'symbol')
2409
+ return {
2410
+ 'info': marginMode,
2411
+ 'symbol': self.safe_symbol(marketId, market),
2412
+ 'marginMode': self.safe_string_lower(marginMode, 'margin_mode'),
2413
+ }
2414
+
2415
+ async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2416
+ """
2417
+ transfer currency internally between wallets on the same account
2418
+ :see: https://api.hitbtc.com/#transfer-between-wallet-and-exchange
2419
+ :param str code: unified currency code
2420
+ :param float amount: amount to transfer
2421
+ :param str fromAccount: account to transfer from
2422
+ :param str toAccount: account to transfer to
2423
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2424
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2425
+ """
2426
+ # account can be "spot", "wallet", or "derivatives"
2427
+ await self.load_markets()
2428
+ currency = self.currency(code)
2429
+ requestAmount = self.currency_to_precision(code, amount)
2430
+ accountsByType = self.safe_value(self.options, 'accountsByType', {})
2431
+ fromAccount = fromAccount.lower()
2432
+ toAccount = toAccount.lower()
2433
+ fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
2434
+ toId = self.safe_string(accountsByType, toAccount, toAccount)
2435
+ if fromId == toId:
2436
+ raise BadRequest(self.id + ' transfer() fromAccount and toAccount arguments cannot be the same account')
2437
+ request: dict = {
2438
+ 'currency': currency['id'],
2439
+ 'amount': requestAmount,
2440
+ 'source': fromId,
2441
+ 'destination': toId,
2442
+ }
2443
+ response = await self.privatePostWalletTransfer(self.extend(request, params))
2444
+ #
2445
+ # [
2446
+ # "2db6ebab-fb26-4537-9ef8-1a689472d236"
2447
+ # ]
2448
+ #
2449
+ return self.parse_transfer(response, currency)
2450
+
2451
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2452
+ #
2453
+ # transfer
2454
+ #
2455
+ # [
2456
+ # "2db6ebab-fb26-4537-9ef8-1a689472d236"
2457
+ # ]
2458
+ #
2459
+ return {
2460
+ 'id': self.safe_string(transfer, 0),
2461
+ 'timestamp': None,
2462
+ 'datetime': None,
2463
+ 'currency': self.safe_currency_code(None, currency),
2464
+ 'amount': None,
2465
+ 'fromAccount': None,
2466
+ 'toAccount': None,
2467
+ 'status': None,
2468
+ 'info': transfer,
2469
+ }
2470
+
2471
+ async def convert_currency_network(self, code: str, amount, fromNetwork, toNetwork, params):
2472
+ await self.load_markets()
2473
+ if code != 'USDT':
2474
+ raise ExchangeError(self.id + ' convertCurrencyNetwork() only supports USDT currently')
2475
+ networks = self.safe_value(self.options, 'networks', {})
2476
+ fromNetwork = fromNetwork.upper()
2477
+ toNetwork = toNetwork.upper()
2478
+ fromNetwork = self.safe_string(networks, fromNetwork) # handle ETH>ERC20 alias
2479
+ toNetwork = self.safe_string(networks, toNetwork) # handle ETH>ERC20 alias
2480
+ if fromNetwork == toNetwork:
2481
+ raise BadRequest(self.id + ' convertCurrencyNetwork() fromNetwork cannot be the same')
2482
+ if (fromNetwork is None) or (toNetwork is None):
2483
+ keys = list(networks.keys())
2484
+ raise ArgumentsRequired(self.id + ' convertCurrencyNetwork() requires a fromNetwork parameter and a toNetwork parameter, supported networks are ' + ', '.join(keys))
2485
+ request: dict = {
2486
+ 'from_currency': fromNetwork,
2487
+ 'to_currency': toNetwork,
2488
+ 'amount': self.currency_to_precision(code, amount),
2489
+ }
2490
+ response = await self.privatePostWalletConvert(self.extend(request, params))
2491
+ # {"result":["587a1868-e62d-4d8e-b27c-dbdb2ee96149","e168df74-c041-41f2-b76c-e43e4fed5bc7"]}
2492
+ return {
2493
+ 'info': response,
2494
+ }
2495
+
2496
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2497
+ """
2498
+ make a withdrawal
2499
+ :see: https://api.hitbtc.com/#withdraw-crypto
2500
+ :param str code: unified currency code
2501
+ :param float amount: the amount to withdraw
2502
+ :param str address: the address to withdraw to
2503
+ :param str tag:
2504
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2505
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2506
+ """
2507
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
2508
+ await self.load_markets()
2509
+ self.check_address(address)
2510
+ currency = self.currency(code)
2511
+ request: dict = {
2512
+ 'currency': currency['id'],
2513
+ 'amount': amount,
2514
+ 'address': address,
2515
+ }
2516
+ if tag is not None:
2517
+ request['payment_id'] = tag
2518
+ networks = self.safe_value(self.options, 'networks', {})
2519
+ network = self.safe_string_upper(params, 'network')
2520
+ if (network is not None) and (code == 'USDT'):
2521
+ parsedNetwork = self.safe_string(networks, network)
2522
+ if parsedNetwork is not None:
2523
+ request['network_code'] = parsedNetwork
2524
+ params = self.omit(params, 'network')
2525
+ withdrawOptions = self.safe_value(self.options, 'withdraw', {})
2526
+ includeFee = self.safe_bool(withdrawOptions, 'includeFee', False)
2527
+ if includeFee:
2528
+ request['include_fee'] = True
2529
+ response = await self.privatePostWalletCryptoWithdraw(self.extend(request, params))
2530
+ #
2531
+ # {
2532
+ # "id":"084cfcd5-06b9-4826-882e-fdb75ec3625d"
2533
+ # }
2534
+ #
2535
+ return self.parse_transaction(response, currency)
2536
+
2537
+ async def fetch_funding_rates(self, symbols: Strings = None, params={}):
2538
+ """
2539
+ fetches funding rates for multiple markets
2540
+ :see: https://api.hitbtc.com/#futures-info
2541
+ :param str[] symbols: unified symbols of the markets to fetch the funding rates for, all market funding rates are returned if not assigned
2542
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2543
+ :returns dict: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2544
+ """
2545
+ await self.load_markets()
2546
+ market = None
2547
+ request: dict = {}
2548
+ if symbols is not None:
2549
+ symbols = self.market_symbols(symbols)
2550
+ market = self.market(symbols[0])
2551
+ queryMarketIds = self.market_ids(symbols)
2552
+ request['symbols'] = ','.join(queryMarketIds)
2553
+ type = None
2554
+ type, params = self.handle_market_type_and_params('fetchFundingRates', market, params)
2555
+ if type != 'swap':
2556
+ raise NotSupported(self.id + ' fetchFundingRates() does not support ' + type + ' markets')
2557
+ response = await self.publicGetPublicFuturesInfo(self.extend(request, params))
2558
+ #
2559
+ # {
2560
+ # "BTCUSDT_PERP": {
2561
+ # "contract_type": "perpetual",
2562
+ # "mark_price": "30897.68",
2563
+ # "index_price": "30895.29",
2564
+ # "funding_rate": "0.0001",
2565
+ # "open_interest": "93.7128",
2566
+ # "next_funding_time": "2021-07-21T16:00:00.000Z",
2567
+ # "indicative_funding_rate": "0.0001",
2568
+ # "premium_index": "0.000047541807127312",
2569
+ # "avg_premium_index": "0.000087063368020112",
2570
+ # "interest_rate": "0.0001",
2571
+ # "timestamp": "2021-07-21T09:48:37.235Z"
2572
+ # }
2573
+ # }
2574
+ #
2575
+ marketIds = list(response.keys())
2576
+ fundingRates: dict = {}
2577
+ for i in range(0, len(marketIds)):
2578
+ marketId = self.safe_string(marketIds, i)
2579
+ rawFundingRate = self.safe_value(response, marketId)
2580
+ marketInner = self.market(marketId)
2581
+ symbol = marketInner['symbol']
2582
+ fundingRate = self.parse_funding_rate(rawFundingRate, marketInner)
2583
+ fundingRates[symbol] = fundingRate
2584
+ return self.filter_by_array(fundingRates, 'symbol', symbols)
2585
+
2586
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2587
+ """
2588
+ :see: https://api.hitbtc.com/#funding-history
2589
+ fetches historical funding rate prices
2590
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2591
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
2592
+ :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
2593
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2594
+ :param int [params.until]: timestamp in ms of the latest funding rate
2595
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2596
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2597
+ """
2598
+ await self.load_markets()
2599
+ paginate = False
2600
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2601
+ if paginate:
2602
+ return await self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 1000)
2603
+ market = None
2604
+ request: dict = {
2605
+ # all arguments are optional
2606
+ # 'symbols': Comma separated list of symbol codes,
2607
+ # 'sort': 'DESC' or 'ASC'
2608
+ # 'from': 'Datetime or Number',
2609
+ # 'until': 'Datetime or Number',
2610
+ # 'limit': 100,
2611
+ # 'offset': 0,
2612
+ }
2613
+ request, params = self.handle_until_option('until', request, params)
2614
+ if symbol is not None:
2615
+ market = self.market(symbol)
2616
+ symbol = market['symbol']
2617
+ request['symbols'] = market['id']
2618
+ if since is not None:
2619
+ request['from'] = since
2620
+ if limit is not None:
2621
+ request['limit'] = limit
2622
+ response = await self.publicGetPublicFuturesHistoryFunding(self.extend(request, params))
2623
+ #
2624
+ # {
2625
+ # "BTCUSDT_PERP": [
2626
+ # {
2627
+ # "timestamp": "2021-07-29T16:00:00.271Z",
2628
+ # "funding_rate": "0.0001",
2629
+ # "avg_premium_index": "0.000061858585213222",
2630
+ # "next_funding_time": "2021-07-30T00:00:00.000Z",
2631
+ # "interest_rate": "0.0001"
2632
+ # },
2633
+ # ...
2634
+ # ],
2635
+ # ...
2636
+ # }
2637
+ #
2638
+ contracts = list(response.keys())
2639
+ rates = []
2640
+ for i in range(0, len(contracts)):
2641
+ marketId = contracts[i]
2642
+ marketInner = self.safe_market(marketId)
2643
+ fundingRateData = response[marketId]
2644
+ for j in range(0, len(fundingRateData)):
2645
+ entry = fundingRateData[j]
2646
+ symbolInner = self.safe_symbol(marketInner['symbol'])
2647
+ fundingRate = self.safe_number(entry, 'funding_rate')
2648
+ datetime = self.safe_string(entry, 'timestamp')
2649
+ rates.append({
2650
+ 'info': entry,
2651
+ 'symbol': symbolInner,
2652
+ 'fundingRate': fundingRate,
2653
+ 'timestamp': self.parse8601(datetime),
2654
+ 'datetime': datetime,
2655
+ })
2656
+ sorted = self.sort_by(rates, 'timestamp')
2657
+ return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
2658
+
2659
+ async def fetch_positions(self, symbols: Strings = None, params={}):
2660
+ """
2661
+ fetch all open positions
2662
+ :see: https://api.hitbtc.com/#get-futures-margin-accounts
2663
+ :see: https://api.hitbtc.com/#get-all-margin-accounts
2664
+ :param str[]|None symbols: not used by hitbtc fetchPositions()
2665
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2666
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported, defaults to spot-margin endpoint if self is set
2667
+ :param bool [params.margin]: True for fetching spot-margin positions
2668
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2669
+ """
2670
+ await self.load_markets()
2671
+ request: dict = {}
2672
+ marketType = None
2673
+ marginMode = None
2674
+ marketType, params = self.handle_market_type_and_params('fetchPositions', None, params)
2675
+ if marketType == 'spot':
2676
+ marketType = 'swap'
2677
+ marginMode, params = self.handle_margin_mode_and_params('fetchPositions', params)
2678
+ params = self.omit(params, ['marginMode', 'margin'])
2679
+ response = None
2680
+ if marginMode is not None:
2681
+ response = await self.privateGetMarginAccount(self.extend(request, params))
2682
+ else:
2683
+ if marketType == 'swap':
2684
+ response = await self.privateGetFuturesAccount(self.extend(request, params))
2685
+ elif marketType == 'margin':
2686
+ response = await self.privateGetMarginAccount(self.extend(request, params))
2687
+ else:
2688
+ raise NotSupported(self.id + ' fetchPositions() not support self market type')
2689
+ #
2690
+ # [
2691
+ # {
2692
+ # "symbol": "ETHUSDT_PERP",
2693
+ # "type": "isolated",
2694
+ # "leverage": "10.00",
2695
+ # "created_at": "2022-03-19T07:54:35.24Z",
2696
+ # "updated_at": "2022-03-19T07:54:58.922Z",
2697
+ # currencies": [
2698
+ # {
2699
+ # "code": "USDT",
2700
+ # "margin_balance": "7.478100643043",
2701
+ # "reserved_orders": "0",
2702
+ # "reserved_positions": "0.303530761300"
2703
+ # }
2704
+ # ],
2705
+ # "positions": [
2706
+ # {
2707
+ # "id": 2470568,
2708
+ # "symbol": "ETHUSDT_PERP",
2709
+ # "quantity": "0.001",
2710
+ # "price_entry": "2927.509",
2711
+ # "price_margin_call": "0",
2712
+ # "price_liquidation": "0",
2713
+ # "pnl": "0",
2714
+ # "created_at": "2022-03-19T07:54:35.24Z",
2715
+ # "updated_at": "2022-03-19T07:54:58.922Z"
2716
+ # }
2717
+ # ]
2718
+ # },
2719
+ # ]
2720
+ #
2721
+ result = []
2722
+ for i in range(0, len(response)):
2723
+ result.append(self.parse_position(response[i]))
2724
+ return result
2725
+
2726
+ async def fetch_position(self, symbol: str, params={}):
2727
+ """
2728
+ fetch data on a single open contract trade position
2729
+ :see: https://api.hitbtc.com/#get-futures-margin-account
2730
+ :see: https://api.hitbtc.com/#get-isolated-margin-account
2731
+ :param str symbol: unified market symbol of the market the position is held in, default is None
2732
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2733
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported, defaults to spot-margin endpoint if self is set
2734
+ :param bool [params.margin]: True for fetching a spot-margin position
2735
+ :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2736
+ """
2737
+ await self.load_markets()
2738
+ market = self.market(symbol)
2739
+ request: dict = {
2740
+ 'symbol': market['id'],
2741
+ }
2742
+ marketType = None
2743
+ marginMode = None
2744
+ marketType, params = self.handle_market_type_and_params('fetchPosition', None, params)
2745
+ marginMode, params = self.handle_margin_mode_and_params('fetchPosition', params)
2746
+ params = self.omit(params, ['marginMode', 'margin'])
2747
+ response = None
2748
+ if marginMode is not None:
2749
+ response = await self.privateGetMarginAccountIsolatedSymbol(self.extend(request, params))
2750
+ else:
2751
+ if marketType == 'swap':
2752
+ response = await self.privateGetFuturesAccountIsolatedSymbol(self.extend(request, params))
2753
+ elif marketType == 'margin':
2754
+ response = await self.privateGetMarginAccountIsolatedSymbol(self.extend(request, params))
2755
+ else:
2756
+ raise NotSupported(self.id + ' fetchPosition() not support self market type')
2757
+ #
2758
+ # [
2759
+ # {
2760
+ # "symbol": "ETHUSDT_PERP",
2761
+ # "type": "isolated",
2762
+ # "leverage": "10.00",
2763
+ # "created_at": "2022-03-19T07:54:35.24Z",
2764
+ # "updated_at": "2022-03-19T07:54:58.922Z",
2765
+ # currencies": [
2766
+ # {
2767
+ # "code": "USDT",
2768
+ # "margin_balance": "7.478100643043",
2769
+ # "reserved_orders": "0",
2770
+ # "reserved_positions": "0.303530761300"
2771
+ # }
2772
+ # ],
2773
+ # "positions": [
2774
+ # {
2775
+ # "id": 2470568,
2776
+ # "symbol": "ETHUSDT_PERP",
2777
+ # "quantity": "0.001",
2778
+ # "price_entry": "2927.509",
2779
+ # "price_margin_call": "0",
2780
+ # "price_liquidation": "0",
2781
+ # "pnl": "0",
2782
+ # "created_at": "2022-03-19T07:54:35.24Z",
2783
+ # "updated_at": "2022-03-19T07:54:58.922Z"
2784
+ # }
2785
+ # ]
2786
+ # },
2787
+ # ]
2788
+ #
2789
+ return self.parse_position(response, market)
2790
+
2791
+ def parse_position(self, position: dict, market: Market = None):
2792
+ #
2793
+ # [
2794
+ # {
2795
+ # "symbol": "ETHUSDT_PERP",
2796
+ # "type": "isolated",
2797
+ # "leverage": "10.00",
2798
+ # "created_at": "2022-03-19T07:54:35.24Z",
2799
+ # "updated_at": "2022-03-19T07:54:58.922Z",
2800
+ # currencies": [
2801
+ # {
2802
+ # "code": "USDT",
2803
+ # "margin_balance": "7.478100643043",
2804
+ # "reserved_orders": "0",
2805
+ # "reserved_positions": "0.303530761300"
2806
+ # }
2807
+ # ],
2808
+ # "positions": [
2809
+ # {
2810
+ # "id": 2470568,
2811
+ # "symbol": "ETHUSDT_PERP",
2812
+ # "quantity": "0.001",
2813
+ # "price_entry": "2927.509",
2814
+ # "price_margin_call": "0",
2815
+ # "price_liquidation": "0",
2816
+ # "pnl": "0",
2817
+ # "created_at": "2022-03-19T07:54:35.24Z",
2818
+ # "updated_at": "2022-03-19T07:54:58.922Z"
2819
+ # }
2820
+ # ]
2821
+ # },
2822
+ # ]
2823
+ #
2824
+ marginMode = self.safe_string(position, 'type')
2825
+ leverage = self.safe_number(position, 'leverage')
2826
+ datetime = self.safe_string(position, 'updated_at')
2827
+ positions = self.safe_value(position, 'positions', [])
2828
+ liquidationPrice = None
2829
+ entryPrice = None
2830
+ contracts = None
2831
+ for i in range(0, len(positions)):
2832
+ entry = positions[i]
2833
+ liquidationPrice = self.safe_number(entry, 'price_liquidation')
2834
+ entryPrice = self.safe_number(entry, 'price_entry')
2835
+ contracts = self.safe_number(entry, 'quantity')
2836
+ currencies = self.safe_value(position, 'currencies', [])
2837
+ collateral = None
2838
+ for i in range(0, len(currencies)):
2839
+ entry = currencies[i]
2840
+ collateral = self.safe_number(entry, 'margin_balance')
2841
+ marketId = self.safe_string(position, 'symbol')
2842
+ market = self.safe_market(marketId, market)
2843
+ symbol = market['symbol']
2844
+ return self.safe_position({
2845
+ 'info': position,
2846
+ 'id': None,
2847
+ 'symbol': symbol,
2848
+ 'notional': None,
2849
+ 'marginMode': marginMode,
2850
+ 'marginType': marginMode,
2851
+ 'liquidationPrice': liquidationPrice,
2852
+ 'entryPrice': entryPrice,
2853
+ 'unrealizedPnl': None,
2854
+ 'percentage': None,
2855
+ 'contracts': contracts,
2856
+ 'contractSize': None,
2857
+ 'markPrice': None,
2858
+ 'lastPrice': None,
2859
+ 'side': None,
2860
+ 'hedged': None,
2861
+ 'timestamp': self.parse8601(datetime),
2862
+ 'datetime': datetime,
2863
+ 'lastUpdateTimestamp': None,
2864
+ 'maintenanceMargin': None,
2865
+ 'maintenanceMarginPercentage': None,
2866
+ 'collateral': collateral,
2867
+ 'initialMargin': None,
2868
+ 'initialMarginPercentage': None,
2869
+ 'leverage': leverage,
2870
+ 'marginRatio': None,
2871
+ 'stopLossPrice': None,
2872
+ 'takeProfitPrice': None,
2873
+ })
2874
+
2875
+ def parse_open_interest(self, interest, market: Market = None):
2876
+ #
2877
+ # {
2878
+ # "contract_type": "perpetual",
2879
+ # "mark_price": "42307.43",
2880
+ # "index_price": "42303.27",
2881
+ # "funding_rate": "0.0001",
2882
+ # "open_interest": "30.9826",
2883
+ # "next_funding_time": "2022-03-22T16:00:00.000Z",
2884
+ # "indicative_funding_rate": "0.0001",
2885
+ # "premium_index": "0",
2886
+ # "avg_premium_index": "0.000029587712038098",
2887
+ # "interest_rate": "0.0001",
2888
+ # "timestamp": "2022-03-22T08:08:26.687Z"
2889
+ # }
2890
+ #
2891
+ datetime = self.safe_string(interest, 'timestamp')
2892
+ value = self.safe_number(interest, 'open_interest')
2893
+ return self.safe_open_interest({
2894
+ 'symbol': market['symbol'],
2895
+ 'openInterestAmount': None,
2896
+ 'openInterestValue': value,
2897
+ 'timestamp': self.parse8601(datetime),
2898
+ 'datetime': datetime,
2899
+ 'info': interest,
2900
+ }, market)
2901
+
2902
+ async def fetch_open_interest(self, symbol: str, params={}):
2903
+ """
2904
+ Retrieves the open interest of a derivative trading pair
2905
+ :see: https://api.hitbtc.com/#futures-info
2906
+ :param str symbol: Unified CCXT market symbol
2907
+ :param dict [params]: exchange specific parameters
2908
+ :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=interest-history-structure:
2909
+ """
2910
+ await self.load_markets()
2911
+ market = self.market(symbol)
2912
+ if not market['swap']:
2913
+ raise BadSymbol(self.id + ' fetchOpenInterest() supports swap contracts only')
2914
+ request: dict = {
2915
+ 'symbol': market['id'],
2916
+ }
2917
+ response = await self.publicGetPublicFuturesInfoSymbol(self.extend(request, params))
2918
+ #
2919
+ # {
2920
+ # "contract_type": "perpetual",
2921
+ # "mark_price": "42307.43",
2922
+ # "index_price": "42303.27",
2923
+ # "funding_rate": "0.0001",
2924
+ # "open_interest": "30.9826",
2925
+ # "next_funding_time": "2022-03-22T16:00:00.000Z",
2926
+ # "indicative_funding_rate": "0.0001",
2927
+ # "premium_index": "0",
2928
+ # "avg_premium_index": "0.000029587712038098",
2929
+ # "interest_rate": "0.0001",
2930
+ # "timestamp": "2022-03-22T08:08:26.687Z"
2931
+ # }
2932
+ #
2933
+ return self.parse_open_interest(response, market)
2934
+
2935
+ async def fetch_funding_rate(self, symbol: str, params={}):
2936
+ """
2937
+ fetch the current funding rate
2938
+ :see: https://api.hitbtc.com/#futures-info
2939
+ :param str symbol: unified market symbol
2940
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2941
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2942
+ """
2943
+ await self.load_markets()
2944
+ market = self.market(symbol)
2945
+ if not market['swap']:
2946
+ raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
2947
+ request: dict = {
2948
+ 'symbol': market['id'],
2949
+ }
2950
+ response = await self.publicGetPublicFuturesInfoSymbol(self.extend(request, params))
2951
+ #
2952
+ # {
2953
+ # "contract_type": "perpetual",
2954
+ # "mark_price": "42307.43",
2955
+ # "index_price": "42303.27",
2956
+ # "funding_rate": "0.0001",
2957
+ # "open_interest": "30.9826",
2958
+ # "next_funding_time": "2022-03-22T16:00:00.000Z",
2959
+ # "indicative_funding_rate": "0.0001",
2960
+ # "premium_index": "0",
2961
+ # "avg_premium_index": "0.000029587712038098",
2962
+ # "interest_rate": "0.0001",
2963
+ # "timestamp": "2022-03-22T08:08:26.687Z"
2964
+ # }
2965
+ #
2966
+ return self.parse_funding_rate(response, market)
2967
+
2968
+ def parse_funding_rate(self, contract, market: Market = None):
2969
+ #
2970
+ # {
2971
+ # "contract_type": "perpetual",
2972
+ # "mark_price": "42307.43",
2973
+ # "index_price": "42303.27",
2974
+ # "funding_rate": "0.0001",
2975
+ # "open_interest": "30.9826",
2976
+ # "next_funding_time": "2022-03-22T16:00:00.000Z",
2977
+ # "indicative_funding_rate": "0.0001",
2978
+ # "premium_index": "0",
2979
+ # "avg_premium_index": "0.000029587712038098",
2980
+ # "interest_rate": "0.0001",
2981
+ # "timestamp": "2022-03-22T08:08:26.687Z"
2982
+ # }
2983
+ #
2984
+ fundingDateTime = self.safe_string(contract, 'next_funding_time')
2985
+ datetime = self.safe_string(contract, 'timestamp')
2986
+ return {
2987
+ 'info': contract,
2988
+ 'symbol': self.safe_symbol(None, market),
2989
+ 'markPrice': self.safe_number(contract, 'mark_price'),
2990
+ 'indexPrice': self.safe_number(contract, 'index_price'),
2991
+ 'interestRate': self.safe_number(contract, 'interest_rate'),
2992
+ 'estimatedSettlePrice': None,
2993
+ 'timestamp': self.parse8601(datetime),
2994
+ 'datetime': datetime,
2995
+ 'fundingRate': self.safe_number(contract, 'funding_rate'),
2996
+ 'fundingTimestamp': self.parse8601(fundingDateTime),
2997
+ 'fundingDatetime': fundingDateTime,
2998
+ 'nextFundingRate': self.safe_number(contract, 'indicative_funding_rate'),
2999
+ 'nextFundingTimestamp': None,
3000
+ 'nextFundingDatetime': None,
3001
+ 'previousFundingRate': None,
3002
+ 'previousFundingTimestamp': None,
3003
+ 'previousFundingDatetime': None,
3004
+ }
3005
+
3006
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
3007
+ await self.load_markets()
3008
+ market = self.market(symbol)
3009
+ leverage = self.safe_string(params, 'leverage')
3010
+ if market['swap']:
3011
+ if leverage is None:
3012
+ raise ArgumentsRequired(self.id + ' modifyMarginHelper() requires a leverage parameter for swap markets')
3013
+ stringAmount = self.number_to_string(amount)
3014
+ if stringAmount != '0':
3015
+ amount = self.amount_to_precision(symbol, stringAmount)
3016
+ else:
3017
+ amount = '0'
3018
+ request: dict = {
3019
+ 'symbol': market['id'], # swap and margin
3020
+ 'margin_balance': amount, # swap and margin
3021
+ # "leverage": "10", # swap only required
3022
+ # "strict_validate": False, # swap and margin
3023
+ }
3024
+ if leverage is not None:
3025
+ request['leverage'] = leverage
3026
+ marketType = None
3027
+ marginMode = None
3028
+ marketType, params = self.handle_market_type_and_params('modifyMarginHelper', market, params)
3029
+ marginMode, params = self.handle_margin_mode_and_params('modifyMarginHelper', params)
3030
+ response = None
3031
+ if marketType == 'swap':
3032
+ response = await self.privatePutFuturesAccountIsolatedSymbol(self.extend(request, params))
3033
+ elif (marketType == 'margin') or (marketType == 'spot') or (marginMode == 'isolated'):
3034
+ response = await self.privatePutMarginAccountIsolatedSymbol(self.extend(request, params))
3035
+ else:
3036
+ raise NotSupported(self.id + ' modifyMarginHelper() not support self market type')
3037
+ #
3038
+ # {
3039
+ # "symbol": "BTCUSDT_PERP",
3040
+ # "type": "isolated",
3041
+ # "leverage": "8.00",
3042
+ # "created_at": "2022-03-30T23:34:27.161Z",
3043
+ # "updated_at": "2022-03-30T23:34:27.161Z",
3044
+ # "currencies": [
3045
+ # {
3046
+ # "code": "USDT",
3047
+ # "margin_balance": "7.000000000000",
3048
+ # "reserved_orders": "0",
3049
+ # "reserved_positions": "0"
3050
+ # }
3051
+ # ],
3052
+ # "positions": null
3053
+ # }
3054
+ #
3055
+ return self.extend(self.parse_margin_modification(response, market), {
3056
+ 'amount': self.parse_number(amount),
3057
+ 'type': type,
3058
+ })
3059
+
3060
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
3061
+ #
3062
+ # addMargin/reduceMargin
3063
+ #
3064
+ # {
3065
+ # "symbol": "BTCUSDT_PERP",
3066
+ # "type": "isolated",
3067
+ # "leverage": "8.00",
3068
+ # "created_at": "2022-03-30T23:34:27.161Z",
3069
+ # "updated_at": "2022-03-30T23:34:27.161Z",
3070
+ # "currencies": [
3071
+ # {
3072
+ # "code": "USDT",
3073
+ # "margin_balance": "7.000000000000",
3074
+ # "reserved_orders": "0",
3075
+ # "reserved_positions": "0"
3076
+ # }
3077
+ # ],
3078
+ # "positions": null
3079
+ # }
3080
+ #
3081
+ currencies = self.safe_value(data, 'currencies', [])
3082
+ currencyInfo = self.safe_value(currencies, 0)
3083
+ datetime = self.safe_string(data, 'updated_at')
3084
+ return {
3085
+ 'info': data,
3086
+ 'symbol': market['symbol'],
3087
+ 'type': None,
3088
+ 'marginMode': 'isolated',
3089
+ 'amount': None,
3090
+ 'total': None,
3091
+ 'code': self.safe_string(currencyInfo, 'code'),
3092
+ 'status': None,
3093
+ 'timestamp': self.parse8601(datetime),
3094
+ 'datetime': datetime,
3095
+ }
3096
+
3097
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3098
+ """
3099
+ remove margin from a position
3100
+ :see: https://api.hitbtc.com/#create-update-margin-account-2
3101
+ :see: https://api.hitbtc.com/#create-update-margin-account
3102
+ :param str symbol: unified market symbol
3103
+ :param float amount: the amount of margin to remove
3104
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3105
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported, defaults to the spot-margin endpoint if self is set
3106
+ :param bool [params.margin]: True for reducing spot-margin
3107
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
3108
+ """
3109
+ if self.number_to_string(amount) != '0':
3110
+ raise BadRequest(self.id + ' reduceMargin() on hitbtc requires the amount to be 0 and that will remove the entire margin amount')
3111
+ return await self.modify_margin_helper(symbol, amount, 'reduce', params)
3112
+
3113
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3114
+ """
3115
+ add margin
3116
+ :see: https://api.hitbtc.com/#create-update-margin-account-2
3117
+ :see: https://api.hitbtc.com/#create-update-margin-account
3118
+ :param str symbol: unified market symbol
3119
+ :param float amount: amount of margin to add
3120
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3121
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported, defaults to the spot-margin endpoint if self is set
3122
+ :param bool [params.margin]: True for adding spot-margin
3123
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
3124
+ """
3125
+ return await self.modify_margin_helper(symbol, amount, 'add', params)
3126
+
3127
+ async def fetch_leverage(self, symbol: str, params={}) -> Leverage:
3128
+ """
3129
+ fetch the set leverage for a market
3130
+ :see: https://api.hitbtc.com/#get-futures-margin-account
3131
+ :see: https://api.hitbtc.com/#get-isolated-margin-account
3132
+ :param str symbol: unified market symbol
3133
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3134
+ :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported, defaults to the spot-margin endpoint if self is set
3135
+ :param bool [params.margin]: True for fetching spot-margin leverage
3136
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
3137
+ """
3138
+ await self.load_markets()
3139
+ market = self.market(symbol)
3140
+ request: dict = {
3141
+ 'symbol': market['id'],
3142
+ }
3143
+ marginMode = None
3144
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params)
3145
+ params = self.omit(params, ['marginMode', 'margin'])
3146
+ response = None
3147
+ if marginMode is not None:
3148
+ response = await self.privateGetMarginAccountIsolatedSymbol(self.extend(request, params))
3149
+ else:
3150
+ if market['type'] == 'spot':
3151
+ response = await self.privateGetMarginAccountIsolatedSymbol(self.extend(request, params))
3152
+ elif market['type'] == 'swap':
3153
+ response = await self.privateGetFuturesAccountIsolatedSymbol(self.extend(request, params))
3154
+ elif market['type'] == 'margin':
3155
+ response = await self.privateGetMarginAccountIsolatedSymbol(self.extend(request, params))
3156
+ else:
3157
+ raise NotSupported(self.id + ' fetchLeverage() not support self market type')
3158
+ #
3159
+ # {
3160
+ # "symbol": "BTCUSDT",
3161
+ # "type": "isolated",
3162
+ # "leverage": "12.00",
3163
+ # "created_at": "2022-03-29T22:31:29.067Z",
3164
+ # "updated_at": "2022-03-30T00:00:00.125Z",
3165
+ # "currencies": [
3166
+ # {
3167
+ # "code": "USDT",
3168
+ # "margin_balance": "20.824360374174",
3169
+ # "reserved_orders": "0",
3170
+ # "reserved_positions": "0.973330435000"
3171
+ # }
3172
+ # ],
3173
+ # "positions": [
3174
+ # {
3175
+ # "id": 631301,
3176
+ # "symbol": "BTCUSDT",
3177
+ # "quantity": "0.00022",
3178
+ # "price_entry": "47425.57",
3179
+ # "price_margin_call": "",
3180
+ # "price_liquidation": "0",
3181
+ # "pnl": "0",
3182
+ # "created_at": "2022-03-29T22:31:29.067Z",
3183
+ # "updated_at": "2022-03-30T00:00:00.125Z"
3184
+ # }
3185
+ # ]
3186
+ # }
3187
+ #
3188
+ return self.parse_leverage(response, market)
3189
+
3190
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
3191
+ marketId = self.safe_string(leverage, 'symbol')
3192
+ leverageValue = self.safe_integer(leverage, 'leverage')
3193
+ return {
3194
+ 'info': leverage,
3195
+ 'symbol': self.safe_symbol(marketId, market),
3196
+ 'marginMode': self.safe_string_lower(leverage, 'type'),
3197
+ 'longLeverage': leverageValue,
3198
+ 'shortLeverage': leverageValue,
3199
+ }
3200
+
3201
+ async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
3202
+ """
3203
+ set the level of leverage for a market
3204
+ :see: https://api.hitbtc.com/#create-update-margin-account-2
3205
+ :param float leverage: the rate of leverage
3206
+ :param str symbol: unified market symbol
3207
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3208
+ :returns dict: response from the exchange
3209
+ """
3210
+ if symbol is None:
3211
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
3212
+ await self.load_markets()
3213
+ if params['margin_balance'] is None:
3214
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a margin_balance parameter that will transfer margin to the specified trading pair')
3215
+ market = self.market(symbol)
3216
+ amount = self.safe_number(params, 'margin_balance')
3217
+ maxLeverage = self.safe_integer(market['limits']['leverage'], 'max', 50)
3218
+ if market['type'] != 'swap':
3219
+ raise BadSymbol(self.id + ' setLeverage() supports swap contracts only')
3220
+ if (leverage < 1) or (leverage > maxLeverage):
3221
+ raise BadRequest(self.id + ' setLeverage() leverage should be between 1 and ' + str(maxLeverage) + ' for ' + symbol)
3222
+ request: dict = {
3223
+ 'symbol': market['id'],
3224
+ 'leverage': str(leverage),
3225
+ 'margin_balance': self.amount_to_precision(symbol, amount),
3226
+ # 'strict_validate': False,
3227
+ }
3228
+ return await self.privatePutFuturesAccountIsolatedSymbol(self.extend(request, params))
3229
+
3230
+ async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
3231
+ """
3232
+ fetch deposit and withdraw fees
3233
+ :see: https://api.hitbtc.com/#currencies
3234
+ :param str[]|None codes: list of unified currency codes
3235
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3236
+ :returns dict[]: a list of `fees structures <https://docs.ccxt.com/#/?id=fee-structure>`
3237
+ """
3238
+ await self.load_markets()
3239
+ response = await self.publicGetPublicCurrency(params)
3240
+ #
3241
+ # {
3242
+ # "WEALTH": {
3243
+ # "full_name": "ConnectWealth",
3244
+ # "payin_enabled": False,
3245
+ # "payout_enabled": False,
3246
+ # "transfer_enabled": True,
3247
+ # "precision_transfer": "0.001",
3248
+ # "networks": [
3249
+ # {
3250
+ # "network": "ETH",
3251
+ # "protocol": "ERC20",
3252
+ # "default": True,
3253
+ # "payin_enabled": False,
3254
+ # "payout_enabled": False,
3255
+ # "precision_payout": "0.001",
3256
+ # "payout_fee": "0.016800000000",
3257
+ # "payout_is_payment_id": False,
3258
+ # "payin_payment_id": False,
3259
+ # "payin_confirmations": "2"
3260
+ # }
3261
+ # ]
3262
+ # }
3263
+ # }
3264
+ #
3265
+ return self.parse_deposit_withdraw_fees(response, codes)
3266
+
3267
+ def parse_deposit_withdraw_fee(self, fee, currency: Currency = None):
3268
+ #
3269
+ # {
3270
+ # "full_name": "ConnectWealth",
3271
+ # "payin_enabled": False,
3272
+ # "payout_enabled": False,
3273
+ # "transfer_enabled": True,
3274
+ # "precision_transfer": "0.001",
3275
+ # "networks": [
3276
+ # {
3277
+ # "network": "ETH",
3278
+ # "protocol": "ERC20",
3279
+ # "default": True,
3280
+ # "payin_enabled": False,
3281
+ # "payout_enabled": False,
3282
+ # "precision_payout": "0.001",
3283
+ # "payout_fee": "0.016800000000",
3284
+ # "payout_is_payment_id": False,
3285
+ # "payin_payment_id": False,
3286
+ # "payin_confirmations": "2"
3287
+ # }
3288
+ # ]
3289
+ # }
3290
+ #
3291
+ networks = self.safe_value(fee, 'networks', [])
3292
+ result = self.deposit_withdraw_fee(fee)
3293
+ for j in range(0, len(networks)):
3294
+ networkEntry = networks[j]
3295
+ networkId = self.safe_string(networkEntry, 'network')
3296
+ networkCode = self.network_id_to_code(networkId)
3297
+ withdrawFee = self.safe_number(networkEntry, 'payout_fee')
3298
+ isDefault = self.safe_value(networkEntry, 'default')
3299
+ withdrawResult: dict = {
3300
+ 'fee': withdrawFee,
3301
+ 'percentage': False if (withdrawFee is not None) else None,
3302
+ }
3303
+ if isDefault is True:
3304
+ result['withdraw'] = withdrawResult
3305
+ result['networks'][networkCode] = {
3306
+ 'withdraw': withdrawResult,
3307
+ 'deposit': {
3308
+ 'fee': None,
3309
+ 'percentage': None,
3310
+ },
3311
+ }
3312
+ return result
3313
+
3314
+ async def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
3315
+ """
3316
+ closes open positions for a market
3317
+ :see: https://api.hitbtc.com/#close-all-futures-margin-positions
3318
+ :param dict [params]: extra parameters specific to the okx api endpoint
3319
+ :param str [params.symbol]: *required* unified market symbol
3320
+ :param str [params.marginMode]: 'cross' or 'isolated', default is 'cross'
3321
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3322
+ """
3323
+ await self.load_markets()
3324
+ marginMode = None
3325
+ marginMode, params = self.handle_margin_mode_and_params('closePosition', params, 'cross')
3326
+ market = self.market(symbol)
3327
+ request: dict = {
3328
+ 'symbol': market['id'],
3329
+ 'margin_mode': marginMode,
3330
+ }
3331
+ response = await self.privateDeleteFuturesPositionMarginModeSymbol(self.extend(request, params))
3332
+ #
3333
+ # {
3334
+ # "id":"202471640",
3335
+ # "symbol":"TRXUSDT_PERP",
3336
+ # "margin_mode":"Cross",
3337
+ # "leverage":"1.00",
3338
+ # "quantity":"0",
3339
+ # "price_entry":"0",
3340
+ # "price_margin_call":"0",
3341
+ # "price_liquidation":"0",
3342
+ # "pnl":"0.001234100000",
3343
+ # "created_at":"2023-10-29T14:46:13.235Z",
3344
+ # "updated_at":"2023-12-19T09:34:40.014Z"
3345
+ # }
3346
+ #
3347
+ return self.parse_order(response, market)
3348
+
3349
+ def handle_margin_mode_and_params(self, methodName, params={}, defaultValue=None):
3350
+ """
3351
+ * @ignore
3352
+ marginMode specified by params["marginMode"], self.options["marginMode"], self.options["defaultMarginMode"], params["margin"] = True or self.options["defaultType"] = 'margin'
3353
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3354
+ :returns Array: the marginMode in lowercase
3355
+ """
3356
+ defaultType = self.safe_string(self.options, 'defaultType')
3357
+ isMargin = self.safe_bool(params, 'margin', False)
3358
+ marginMode = None
3359
+ marginMode, params = super(hitbtc, self).handle_margin_mode_and_params(methodName, params, defaultValue)
3360
+ if marginMode is None:
3361
+ if (defaultType == 'margin') or (isMargin is True):
3362
+ marginMode = 'isolated'
3363
+ return [marginMode, params]
3364
+
3365
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
3366
+ #
3367
+ # {
3368
+ # "error": {
3369
+ # "code": 20001,
3370
+ # "message": "Insufficient funds",
3371
+ # "description": "Check that the funds are sufficient, given commissions"
3372
+ # }
3373
+ # }
3374
+ #
3375
+ # {
3376
+ # "error": {
3377
+ # "code": "600",
3378
+ # "message": "Action not allowed"
3379
+ # }
3380
+ # }
3381
+ #
3382
+ error = self.safe_value(response, 'error')
3383
+ errorCode = self.safe_string(error, 'code')
3384
+ if errorCode is not None:
3385
+ feedback = self.id + ' ' + body
3386
+ message = self.safe_string_2(error, 'message', 'description')
3387
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
3388
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
3389
+ raise ExchangeError(feedback)
3390
+ return None
3391
+
3392
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
3393
+ query = self.omit(params, self.extract_params(path))
3394
+ implodedPath = self.implode_params(path, params)
3395
+ url = self.urls['api'][api] + '/' + implodedPath
3396
+ getRequest = None
3397
+ keys = list(query.keys())
3398
+ queryLength = len(keys)
3399
+ headers = {
3400
+ 'Content-Type': 'application/json',
3401
+ }
3402
+ if method == 'GET':
3403
+ if queryLength:
3404
+ getRequest = '?' + self.urlencode(query)
3405
+ url = url + getRequest
3406
+ else:
3407
+ body = self.json(params)
3408
+ if api == 'private':
3409
+ self.check_required_credentials()
3410
+ timestamp = str(self.nonce())
3411
+ payload = [method, '/api/3/' + implodedPath]
3412
+ if method == 'GET':
3413
+ if getRequest is not None:
3414
+ payload.append(getRequest)
3415
+ else:
3416
+ payload.append(body)
3417
+ payload.append(timestamp)
3418
+ payloadString = ''.join(payload)
3419
+ signature = self.hmac(self.encode(payloadString), self.encode(self.secret), hashlib.sha256, 'hex')
3420
+ secondPayload = self.apiKey + ':' + signature + ':' + timestamp
3421
+ encoded = self.string_to_base64(secondPayload)
3422
+ headers['Authorization'] = 'HS256 ' + encoded
3423
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}