ccxt-ir 4.3.46.0.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/krakenfutures.py ADDED
@@ -0,0 +1,2601 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.base.exchange import Exchange
7
+ from ccxt.abstract.krakenfutures import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, LeverageTier, LeverageTiers, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, 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 ArgumentsRequired
14
+ from ccxt.base.errors import BadRequest
15
+ from ccxt.base.errors import InsufficientFunds
16
+ from ccxt.base.errors import InvalidOrder
17
+ from ccxt.base.errors import OrderNotFound
18
+ from ccxt.base.errors import OrderImmediatelyFillable
19
+ from ccxt.base.errors import OrderNotFillable
20
+ from ccxt.base.errors import DuplicateOrderId
21
+ from ccxt.base.errors import ContractUnavailable
22
+ from ccxt.base.errors import DDoSProtection
23
+ from ccxt.base.errors import RateLimitExceeded
24
+ from ccxt.base.errors import ExchangeNotAvailable
25
+ from ccxt.base.errors import InvalidNonce
26
+ from ccxt.base.decimal_to_precision import TICK_SIZE
27
+ from ccxt.base.precise import Precise
28
+
29
+
30
+ class krakenfutures(Exchange, ImplicitAPI):
31
+
32
+ def describe(self):
33
+ return self.deep_extend(super(krakenfutures, self).describe(), {
34
+ 'id': 'krakenfutures',
35
+ 'name': 'Kraken Futures',
36
+ 'countries': ['US'],
37
+ 'version': 'v3',
38
+ 'userAgent': None,
39
+ 'rateLimit': 600,
40
+ 'pro': True,
41
+ 'has': {
42
+ 'CORS': None,
43
+ 'spot': False,
44
+ 'margin': False,
45
+ 'swap': True,
46
+ 'future': True,
47
+ 'option': False,
48
+ 'cancelAllOrders': True,
49
+ 'cancelAllOrdersAfter': True,
50
+ 'cancelOrder': True,
51
+ 'cancelOrders': True,
52
+ 'createMarketOrder': False,
53
+ 'createOrder': True,
54
+ 'editOrder': True,
55
+ 'fetchBalance': True,
56
+ 'fetchBorrowRateHistories': False,
57
+ 'fetchBorrowRateHistory': False,
58
+ 'fetchCanceledOrders': True,
59
+ 'fetchClosedOrders': True, # https://support.kraken.com/hc/en-us/articles/360058243651-Historical-orders
60
+ 'fetchCrossBorrowRate': False,
61
+ 'fetchCrossBorrowRates': False,
62
+ 'fetchDepositAddress': False,
63
+ 'fetchDepositAddresses': False,
64
+ 'fetchDepositAddressesByNetwork': False,
65
+ 'fetchFundingHistory': None,
66
+ 'fetchFundingRate': 'emulated',
67
+ 'fetchFundingRateHistory': True,
68
+ 'fetchFundingRates': True,
69
+ 'fetchIndexOHLCV': False,
70
+ 'fetchIsolatedBorrowRate': False,
71
+ 'fetchIsolatedBorrowRates': False,
72
+ 'fetchIsolatedPositions': False,
73
+ 'fetchLeverage': True,
74
+ 'fetchLeverages': True,
75
+ 'fetchLeverageTiers': True,
76
+ 'fetchMarketLeverageTiers': 'emulated',
77
+ 'fetchMarkets': True,
78
+ 'fetchMarkOHLCV': True,
79
+ 'fetchMyTrades': True,
80
+ 'fetchOHLCV': True,
81
+ 'fetchOpenOrders': True,
82
+ 'fetchOrder': False,
83
+ 'fetchOrderBook': True,
84
+ 'fetchOrders': False,
85
+ 'fetchPositions': True,
86
+ 'fetchPremiumIndexOHLCV': False,
87
+ 'fetchTickers': True,
88
+ 'fetchTrades': True,
89
+ 'sandbox': True,
90
+ 'setLeverage': True,
91
+ 'setMarginMode': False,
92
+ 'transfer': True,
93
+ },
94
+ 'urls': {
95
+ 'test': {
96
+ 'public': 'https://demo-futures.kraken.com/derivatives/api/',
97
+ 'private': 'https://demo-futures.kraken.com/derivatives/api/',
98
+ 'charts': 'https://demo-futures.kraken.com/api/charts/',
99
+ 'www': 'https://demo-futures.kraken.com',
100
+ },
101
+ 'logo': 'https://user-images.githubusercontent.com/24300605/81436764-b22fd580-9172-11ea-9703-742783e6376d.jpg',
102
+ 'api': {
103
+ 'charts': 'https://futures.kraken.com/api/charts/',
104
+ 'history': 'https://futures.kraken.com/api/history/',
105
+ 'feeschedules': 'https://futures.kraken.com/api/feeschedules/',
106
+ 'public': 'https://futures.kraken.com/derivatives/api/',
107
+ 'private': 'https://futures.kraken.com/derivatives/api/',
108
+ },
109
+ 'www': 'https://futures.kraken.com/',
110
+ 'doc': [
111
+ 'https://docs.futures.kraken.com/#introduction',
112
+ ],
113
+ 'fees': 'https://support.kraken.com/hc/en-us/articles/360022835771-Transaction-fees-and-rebates-for-Kraken-Futures',
114
+ 'referral': None,
115
+ },
116
+ 'api': {
117
+ 'public': {
118
+ 'get': [
119
+ 'feeschedules',
120
+ 'instruments',
121
+ 'orderbook',
122
+ 'tickers',
123
+ 'history',
124
+ 'historicalfundingrates',
125
+ ],
126
+ },
127
+ 'private': {
128
+ 'get': [
129
+ 'feeschedules/volumes',
130
+ 'openpositions',
131
+ 'notifications',
132
+ 'accounts',
133
+ 'openorders',
134
+ 'recentorders',
135
+ 'fills',
136
+ 'transfers',
137
+ 'leveragepreferences',
138
+ 'pnlpreferences',
139
+ ],
140
+ 'post': [
141
+ 'sendorder',
142
+ 'editorder',
143
+ 'cancelorder',
144
+ 'transfer',
145
+ 'batchorder',
146
+ 'cancelallorders',
147
+ 'cancelallordersafter',
148
+ 'withdrawal', # for futures wallet -> kraken spot wallet
149
+ ],
150
+ 'put': [
151
+ 'leveragepreferences',
152
+ 'pnlpreferences',
153
+ ],
154
+ },
155
+ 'charts': {
156
+ 'get': [
157
+ '{price_type}/{symbol}/{interval}',
158
+ ],
159
+ },
160
+ 'history': {
161
+ 'get': [
162
+ 'orders',
163
+ 'executions',
164
+ 'triggers',
165
+ 'accountlogcsv',
166
+ 'account-log',
167
+ 'market/{symbol}/orders',
168
+ 'market/{symbol}/executions',
169
+ ],
170
+ },
171
+ },
172
+ 'fees': {
173
+ 'trading': {
174
+ 'tierBased': True,
175
+ 'percentage': True,
176
+ 'taker': self.parse_number('0.0005'),
177
+ 'maker': self.parse_number('0.0002'),
178
+ 'tiers': {
179
+ 'taker': [
180
+ [self.parse_number('0'), self.parse_number('0.0005')],
181
+ [self.parse_number('100000'), self.parse_number('0.0004')],
182
+ [self.parse_number('1000000'), self.parse_number('0.0003')],
183
+ [self.parse_number('5000000'), self.parse_number('0.00025')],
184
+ [self.parse_number('10000000'), self.parse_number('0.0002')],
185
+ [self.parse_number('20000000'), self.parse_number('0.00015')],
186
+ [self.parse_number('50000000'), self.parse_number('0.000125')],
187
+ [self.parse_number('100000000'), self.parse_number('0.0001')],
188
+ ],
189
+ 'maker': [
190
+ [self.parse_number('0'), self.parse_number('0.0002')],
191
+ [self.parse_number('100000'), self.parse_number('0.0015')],
192
+ [self.parse_number('1000000'), self.parse_number('0.000125')],
193
+ [self.parse_number('5000000'), self.parse_number('0.0001')],
194
+ [self.parse_number('10000000'), self.parse_number('0.000075')],
195
+ [self.parse_number('20000000'), self.parse_number('0.00005')],
196
+ [self.parse_number('50000000'), self.parse_number('0.000025')],
197
+ [self.parse_number('100000000'), self.parse_number('0')],
198
+ ],
199
+ },
200
+ },
201
+ },
202
+ 'exceptions': {
203
+ 'exact': {
204
+ 'apiLimitExceeded': RateLimitExceeded,
205
+ 'marketUnavailable': ContractUnavailable,
206
+ 'requiredArgumentMissing': BadRequest,
207
+ 'unavailable': ExchangeNotAvailable,
208
+ 'authenticationError': AuthenticationError,
209
+ 'accountInactive': ExchangeError, # When account has no trade history / no order history. Should self error be ignored in some cases?
210
+ 'invalidAccount': BadRequest, # the fromAccount or the toAccount are invalid
211
+ 'invalidAmount': BadRequest,
212
+ 'insufficientFunds': InsufficientFunds,
213
+ 'Bad Request': BadRequest, # The URL contains invalid characters.(Please encode the json URL parameter)
214
+ 'Unavailable': InsufficientFunds, # Insufficient funds in Futures account [withdraw]
215
+ 'invalidUnit': BadRequest,
216
+ 'Json Parse Error': ExchangeError,
217
+ 'nonceBelowThreshold': InvalidNonce,
218
+ 'nonceDuplicate': InvalidNonce,
219
+ 'notFound': BadRequest,
220
+ 'Server Error': ExchangeError,
221
+ 'unknownError': ExchangeError,
222
+ },
223
+ 'broad': {
224
+ 'invalidArgument': BadRequest,
225
+ 'nonceBelowThreshold': InvalidNonce,
226
+ 'nonceDuplicate': InvalidNonce,
227
+ },
228
+ },
229
+ 'precisionMode': TICK_SIZE,
230
+ 'options': {
231
+ 'access': {
232
+ 'history': {
233
+ 'GET': {
234
+ 'orders': 'private',
235
+ 'executions': 'private',
236
+ 'triggers': 'private',
237
+ 'accountlogcsv': 'private',
238
+ },
239
+ },
240
+ },
241
+ 'settlementCurrencies': {
242
+ 'flex': ['USDT', 'BTC', 'USD', 'GBP', 'EUR', 'USDC'],
243
+ },
244
+ 'symbol': {
245
+ 'quoteIds': ['USD', 'XBT'],
246
+ 'reversed': False,
247
+ },
248
+ 'versions': {
249
+ 'public': {
250
+ 'GET': {
251
+ 'historicalfundingrates': 'v4',
252
+ },
253
+ },
254
+ 'charts': {
255
+ 'GET': {
256
+ '{price_type}/{symbol}/{interval}': 'v1',
257
+ },
258
+ },
259
+ 'history': {
260
+ 'GET': {
261
+ 'orders': 'v2',
262
+ 'executions': 'v2',
263
+ 'triggers': 'v2',
264
+ 'accountlogcsv': 'v2',
265
+ },
266
+ },
267
+ },
268
+ 'fetchTrades': {
269
+ 'method': 'historyGetMarketSymbolExecutions', # historyGetMarketSymbolExecutions, publicGetHistory
270
+ },
271
+ },
272
+ 'timeframes': {
273
+ '1m': '1m',
274
+ '5m': '5m',
275
+ '15m': '15m',
276
+ '30m': '30m',
277
+ '1h': '1h',
278
+ '4h': '4h',
279
+ '12h': '12h',
280
+ '1d': '1d',
281
+ '1w': '1w',
282
+ },
283
+ })
284
+
285
+ def fetch_markets(self, params={}) -> List[Market]:
286
+ """
287
+ Fetches the available trading markets from the exchange, Multi-collateral markets are returned markets, but can be settled in multiple currencies
288
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-instrument-details-get-instruments
289
+ :param dict [params]: exchange specific params
290
+ :returns: An array of market structures
291
+ """
292
+ response = self.publicGetInstruments(params)
293
+ #
294
+ # {
295
+ # "result": "success",
296
+ # "instruments": [
297
+ # {
298
+ # "symbol": "fi_ethusd_180928",
299
+ # "type": "futures_inverse", # futures_vanilla # spot index
300
+ # "underlying": "rr_ethusd",
301
+ # "lastTradingTime": "2018-09-28T15:00:00.000Z",
302
+ # "tickSize": 0.1,
303
+ # "contractSize": 1,
304
+ # "tradeable": True,
305
+ # "marginLevels": [
306
+ # {
307
+ # "contracts":0,
308
+ # "initialMargin":0.02,
309
+ # "maintenanceMargin":0.01
310
+ # },
311
+ # {
312
+ # "contracts":250000,
313
+ # "initialMargin":0.04,
314
+ # "maintenanceMargin":0.02
315
+ # },
316
+ # ...
317
+ # ],
318
+ # "isin": "GB00JVMLMP88",
319
+ # "retailMarginLevels": [
320
+ # {
321
+ # "contracts": 0,
322
+ # "initialMargin": 0.5,
323
+ # "maintenanceMargin": 0.25
324
+ # }
325
+ # ],
326
+ # "tags": [],
327
+ # },
328
+ # {
329
+ # "symbol": "in_xbtusd",
330
+ # "type": "spot index",
331
+ # "tradeable":false
332
+ # }
333
+ # ]
334
+ # "serverTime": "2018-07-19T11:32:39.433Z"
335
+ # }
336
+ #
337
+ instruments = self.safe_value(response, 'instruments', [])
338
+ result = []
339
+ for i in range(0, len(instruments)):
340
+ market = instruments[i]
341
+ id = self.safe_string(market, 'symbol')
342
+ marketType = self.safe_string(market, 'type')
343
+ type = None
344
+ index = (marketType.find(' index') >= 0)
345
+ linear = None
346
+ inverse = None
347
+ expiry = None
348
+ if not index:
349
+ linear = (marketType.find('_vanilla') >= 0)
350
+ inverse = not linear
351
+ settleTime = self.safe_string(market, 'lastTradingTime')
352
+ type = 'swap' if (settleTime is None) else 'future'
353
+ expiry = self.parse8601(settleTime)
354
+ else:
355
+ type = 'index'
356
+ swap = (type == 'swap')
357
+ future = (type == 'future')
358
+ symbol = id
359
+ split = id.split('_')
360
+ splitMarket = self.safe_string(split, 1)
361
+ baseId = splitMarket[0:len(splitMarket) - 3]
362
+ quoteId = 'usd' # always USD
363
+ base = self.safe_currency_code(baseId)
364
+ quote = self.safe_currency_code(quoteId)
365
+ # swap == perpetual
366
+ settle = None
367
+ settleId = None
368
+ cvtp = self.safe_string(market, 'contractValueTradePrecision')
369
+ amountPrecision = self.parse_number(self.integer_precision_to_amount(cvtp))
370
+ pricePrecision = self.safe_number(market, 'tickSize')
371
+ contract = (swap or future or index)
372
+ swapOrFutures = (swap or future)
373
+ if swapOrFutures:
374
+ exchangeType = self.safe_string(market, 'type')
375
+ if exchangeType == 'futures_inverse':
376
+ settle = base
377
+ settleId = baseId
378
+ inverse = True
379
+ else:
380
+ settle = quote
381
+ settleId = quoteId
382
+ inverse = False
383
+ linear = not inverse
384
+ symbol = base + '/' + quote + ':' + settle
385
+ if future:
386
+ symbol = symbol + '-' + self.yymmdd(expiry)
387
+ result.append({
388
+ 'id': id,
389
+ 'symbol': symbol,
390
+ 'base': base,
391
+ 'quote': quote,
392
+ 'settle': settle,
393
+ 'baseId': baseId,
394
+ 'quoteId': quoteId,
395
+ 'settleId': settleId,
396
+ 'type': type,
397
+ 'spot': False,
398
+ 'margin': False,
399
+ 'swap': swap,
400
+ 'future': future,
401
+ 'option': False,
402
+ 'index': index,
403
+ 'active': None,
404
+ 'contract': contract,
405
+ 'linear': linear,
406
+ 'inverse': inverse,
407
+ 'contractSize': self.safe_number(market, 'contractSize'),
408
+ 'maintenanceMarginRate': None,
409
+ 'expiry': expiry,
410
+ 'expiryDatetime': self.iso8601(expiry),
411
+ 'strike': None,
412
+ 'optionType': None,
413
+ 'precision': {
414
+ 'amount': amountPrecision,
415
+ 'price': pricePrecision,
416
+ },
417
+ 'limits': {
418
+ 'leverage': {
419
+ 'min': None,
420
+ 'max': None,
421
+ },
422
+ 'amount': {
423
+ 'min': None,
424
+ 'max': None,
425
+ },
426
+ 'price': {
427
+ 'min': None,
428
+ 'max': None,
429
+ },
430
+ 'cost': {
431
+ 'min': None,
432
+ 'max': None,
433
+ },
434
+ },
435
+ 'created': self.parse8601(self.safe_string(market, 'openingDate')),
436
+ 'info': market,
437
+ })
438
+ settlementCurrencies = self.options['settlementCurrencies']['flex']
439
+ currencies = []
440
+ for i in range(0, len(settlementCurrencies)):
441
+ code = settlementCurrencies[i]
442
+ currencies.append({
443
+ 'id': code.lower(),
444
+ 'numericId': None,
445
+ 'code': code,
446
+ 'precision': None,
447
+ })
448
+ self.currencies = self.deep_extend(currencies, self.currencies)
449
+ return result
450
+
451
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
452
+ """
453
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-orderbook
454
+ Fetches a list of open orders in a market
455
+ :param str symbol: Unified market symbol
456
+ :param int [limit]: Not used by krakenfutures
457
+ :param dict [params]: exchange specific params
458
+ :returns: An `order book structure <https://docs.ccxt.com/#/?id=order-book-structure>`
459
+ """
460
+ self.load_markets()
461
+ market = self.market(symbol)
462
+ request: dict = {
463
+ 'symbol': market['id'],
464
+ }
465
+ response = self.publicGetOrderbook(self.extend(request, params))
466
+ #
467
+ # {
468
+ # "result": "success",
469
+ # "serverTime": "2016-02-25T09:45:53.818Z",
470
+ # "orderBook": {
471
+ # "bids": [
472
+ # [
473
+ # 4213,
474
+ # 2000,
475
+ # ],
476
+ # [
477
+ # 4210,
478
+ # 4000,
479
+ # ],
480
+ # ...
481
+ # ],
482
+ # "asks": [
483
+ # [
484
+ # 4218,
485
+ # 4000,
486
+ # ],
487
+ # [
488
+ # 4220,
489
+ # 5000,
490
+ # ],
491
+ # ...
492
+ # ],
493
+ # },
494
+ # }
495
+ #
496
+ timestamp = self.parse8601(response['serverTime'])
497
+ return self.parse_order_book(response['orderBook'], symbol, timestamp)
498
+
499
+ def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
500
+ """
501
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
502
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-tickers
503
+ :param str[] symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
504
+ :param dict [params]: extra parameters specific to the exchange API endpoint
505
+ :returns dict: an array of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
506
+ """
507
+ self.load_markets()
508
+ response = self.publicGetTickers(params)
509
+ #
510
+ # {
511
+ # "result": "success",
512
+ # "tickers": [
513
+ # {
514
+ # "tag": 'semiannual', # 'month', 'quarter', "perpetual", "semiannual",
515
+ # "pair": "ETH:USD",
516
+ # "symbol": "fi_ethusd_220624",
517
+ # "markPrice": "2925.72",
518
+ # "bid": "2923.8",
519
+ # "bidSize": "16804",
520
+ # "ask": "2928.65",
521
+ # "askSize": "1339",
522
+ # "vol24h": "860493",
523
+ # "openInterest": "3023363.00000000",
524
+ # "open24h": "3021.25",
525
+ # "indexPrice": "2893.71",
526
+ # "last": "2942.25",
527
+ # "lastTime": "2022-02-18T14:08:15.578Z",
528
+ # "lastSize": "151",
529
+ # "suspended": False
530
+ # },
531
+ # {
532
+ # "symbol": "in_xbtusd", # "rr_xbtusd",
533
+ # "last": "40411",
534
+ # "lastTime": "2022-02-18T14:16:28.000Z"
535
+ # },
536
+ # ...
537
+ # ],
538
+ # "serverTime": "2022-02-18T14:16:29.440Z"
539
+ # }
540
+ #
541
+ tickers = self.safe_list(response, 'tickers')
542
+ return self.parse_tickers(tickers, symbols)
543
+
544
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
545
+ #
546
+ # {
547
+ # "tag": 'semiannual', # 'month', 'quarter', "perpetual", "semiannual",
548
+ # "pair": "ETH:USD",
549
+ # "symbol": "fi_ethusd_220624",
550
+ # "markPrice": "2925.72",
551
+ # "bid": "2923.8",
552
+ # "bidSize": "16804",
553
+ # "ask": "2928.65",
554
+ # "askSize": "1339",
555
+ # "vol24h": "860493",
556
+ # "openInterest": "3023363.00000000",
557
+ # "open24h": "3021.25",
558
+ # "indexPrice": "2893.71",
559
+ # "last": "2942.25",
560
+ # "lastTime": "2022-02-18T14:08:15.578Z",
561
+ # "lastSize": "151",
562
+ # "suspended": False
563
+ # }
564
+ #
565
+ # {
566
+ # "symbol": "in_xbtusd", # "rr_xbtusd",
567
+ # "last": "40411",
568
+ # "lastTime": "2022-02-18T14:16:28.000Z"
569
+ # }
570
+ #
571
+ marketId = self.safe_string(ticker, 'symbol')
572
+ market = self.safe_market(marketId, market)
573
+ symbol = market['symbol']
574
+ timestamp = self.parse8601(self.safe_string(ticker, 'lastTime'))
575
+ open = self.safe_string(ticker, 'open24h')
576
+ last = self.safe_string(ticker, 'last')
577
+ change = Precise.string_sub(last, open)
578
+ percentage = Precise.string_mul(Precise.string_div(change, open), '100')
579
+ average = Precise.string_div(Precise.string_add(open, last), '2')
580
+ volume = self.safe_string(ticker, 'vol24h')
581
+ baseVolume = None
582
+ quoteVolume = None
583
+ isIndex = self.safe_bool(market, 'index', False)
584
+ if not isIndex:
585
+ if market['linear']:
586
+ baseVolume = volume
587
+ elif market['inverse']:
588
+ quoteVolume = volume
589
+ return self.safe_ticker({
590
+ 'symbol': symbol,
591
+ 'timestamp': timestamp,
592
+ 'datetime': self.iso8601(timestamp),
593
+ 'high': None,
594
+ 'low': None,
595
+ 'bid': self.safe_string(ticker, 'bid'),
596
+ 'bidVolume': self.safe_string(ticker, 'bidSize'),
597
+ 'ask': self.safe_string(ticker, 'ask'),
598
+ 'askVolume': self.safe_string(ticker, 'askSize'),
599
+ 'vwap': None,
600
+ 'open': open,
601
+ 'close': last,
602
+ 'last': last,
603
+ 'previousClose': None,
604
+ 'change': change,
605
+ 'percentage': percentage,
606
+ 'average': average,
607
+ 'baseVolume': baseVolume,
608
+ 'quoteVolume': quoteVolume,
609
+ 'info': ticker,
610
+ })
611
+
612
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
613
+ """
614
+ :see: https://docs.futures.kraken.com/#http-api-charts-candles
615
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
616
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
617
+ :param str timeframe: the length of time each candle represents
618
+ :param int [since]: timestamp in ms of the earliest candle to fetch
619
+ :param int [limit]: the maximum amount of candles to fetch
620
+ :param dict [params]: extra parameters specific to the exchange API endpoint
621
+ :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)
622
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
623
+ """
624
+ self.load_markets()
625
+ market = self.market(symbol)
626
+ paginate = False
627
+ paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
628
+ if paginate:
629
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 5000)
630
+ request: dict = {
631
+ 'symbol': market['id'],
632
+ 'price_type': self.safe_string(params, 'price', 'trade'),
633
+ 'interval': self.timeframes[timeframe],
634
+ }
635
+ params = self.omit(params, 'price')
636
+ if since is not None:
637
+ duration = self.parse_timeframe(timeframe)
638
+ request['from'] = self.parse_to_int(since / 1000)
639
+ if limit is None:
640
+ limit = 5000
641
+ limit = min(limit, 5000)
642
+ toTimestamp = self.sum(request['from'], limit * duration - 1)
643
+ currentTimestamp = self.seconds()
644
+ request['to'] = min(toTimestamp, currentTimestamp)
645
+ elif limit is not None:
646
+ limit = min(limit, 5000)
647
+ duration = self.parse_timeframe(timeframe)
648
+ request['to'] = self.seconds()
649
+ request['from'] = self.parse_to_int(request['to'] - (duration * limit))
650
+ response = self.chartsGetPriceTypeSymbolInterval(self.extend(request, params))
651
+ #
652
+ # {
653
+ # "candles": [
654
+ # {
655
+ # "time": 1645198500000,
656
+ # "open": "309.15000000000",
657
+ # "high": "309.15000000000",
658
+ # "low": "308.70000000000",
659
+ # "close": "308.85000000000",
660
+ # "volume": 0
661
+ # }
662
+ # ],
663
+ # "more_candles": True
664
+ # }
665
+ #
666
+ candles = self.safe_list(response, 'candles')
667
+ return self.parse_ohlcvs(candles, market, timeframe, since, limit)
668
+
669
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
670
+ #
671
+ # {
672
+ # "time": 1645198500000,
673
+ # "open": "309.15000000000",
674
+ # "high": "309.15000000000",
675
+ # "low": "308.70000000000",
676
+ # "close": "308.85000000000",
677
+ # "volume": 0
678
+ # }
679
+ #
680
+ return [
681
+ self.safe_integer(ohlcv, 'time'), # unix timestamp in milliseconds
682
+ self.safe_number(ohlcv, 'open'), # open price
683
+ self.safe_number(ohlcv, 'high'), # highest price
684
+ self.safe_number(ohlcv, 'low'), # lowest price
685
+ self.safe_number(ohlcv, 'close'), # close price
686
+ self.safe_number(ohlcv, 'volume'), # trading volume, None for mark or index price
687
+ ]
688
+
689
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
690
+ """
691
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-trade-history
692
+ :see: https://docs.futures.kraken.com/#http-api-history-market-history-get-public-execution-events
693
+ Fetch a history of filled trades that self account has made
694
+ :param str symbol: Unified CCXT market symbol
695
+ :param int [since]: Timestamp in ms of earliest trade. Not used by krakenfutures except in combination with params.until
696
+ :param int [limit]: Total number of trades, cannot exceed 100
697
+ :param dict [params]: Exchange specific params
698
+ :param int [params.until]: Timestamp in ms of latest trade
699
+ :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)
700
+ :param str [params.method]: The method to use to fetch trades. Can be 'historyGetMarketSymbolExecutions' or 'publicGetHistory' default is 'historyGetMarketSymbolExecutions'
701
+ :returns: An array of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
702
+ """
703
+ self.load_markets()
704
+ paginate = False
705
+ paginate, params = self.handle_option_and_params(params, 'fetchTrades', 'paginate')
706
+ if paginate:
707
+ return self.fetch_paginated_call_dynamic('fetchTrades', symbol, since, limit, params)
708
+ market = self.market(symbol)
709
+ request: dict = {
710
+ 'symbol': market['id'],
711
+ }
712
+ method = None
713
+ method, params = self.handle_option_and_params(params, 'fetchTrades', 'method', 'historyGetMarketSymbolExecutions')
714
+ rawTrades = None
715
+ isFullHistoryEndpoint = (method == 'historyGetMarketSymbolExecutions')
716
+ if isFullHistoryEndpoint:
717
+ request, params = self.handle_until_option('before', request, params)
718
+ if since is not None:
719
+ request['since'] = since
720
+ request['sort'] = 'asc'
721
+ if limit is not None:
722
+ request['count'] = limit
723
+ response = self.historyGetMarketSymbolExecutions(self.extend(request, params))
724
+ #
725
+ # {
726
+ # "elements": [
727
+ # {
728
+ # "uid": "a5105030-f054-44cc-98ab-30d5cae96bef",
729
+ # "timestamp": "1710150778607",
730
+ # "event": {
731
+ # "Execution": {
732
+ # "execution": {
733
+ # "uid": "2d485b71-cd28-4a1e-9364-371a127550d2",
734
+ # "makerOrder": {
735
+ # "uid": "0a25f66b-1109-49ec-93a3-d17bf9e9137e",
736
+ # "tradeable": "PF_XBTUSD",
737
+ # "direction": "Buy",
738
+ # "quantity": "0.26500",
739
+ # "timestamp": "1710150778570",
740
+ # "limitPrice": "71907",
741
+ # "orderType": "Post",
742
+ # "reduceOnly": False,
743
+ # "lastUpdateTimestamp": "1710150778570"
744
+ # },
745
+ # "takerOrder": {
746
+ # "uid": "04de3ee0-9125-4960-bf8f-f63b577b6790",
747
+ # "tradeable": "PF_XBTUSD",
748
+ # "direction": "Sell",
749
+ # "quantity": "0.0002",
750
+ # "timestamp": "1710150778607",
751
+ # "limitPrice": "71187.00",
752
+ # "orderType": "Market",
753
+ # "reduceOnly": False,
754
+ # "lastUpdateTimestamp": "1710150778607"
755
+ # },
756
+ # "timestamp": "1710150778607",
757
+ # "quantity": "0.0002",
758
+ # "price": "71907",
759
+ # "markPrice": "71903.32715463147",
760
+ # "limitFilled": False,
761
+ # "usdValue": "14.38"
762
+ # },
763
+ # "takerReducedQuantity": ""
764
+ # }
765
+ # }
766
+ # },
767
+ # ... followed by older items
768
+ # ],
769
+ # "len": "1000",
770
+ # "continuationToken": "QTexMDE0OTe33NTcyXy8xNDIzAjc1NjY5MwI="
771
+ # }
772
+ #
773
+ elements = self.safe_list(response, 'elements', [])
774
+ # we need to reverse the list to fix chronology
775
+ rawTrades = []
776
+ length = len(elements)
777
+ for i in range(0, length):
778
+ index = length - 1 - i
779
+ element = elements[index]
780
+ event = self.safe_dict(element, 'event', {})
781
+ executionContainer = self.safe_dict(event, 'Execution', {})
782
+ rawTrade = self.safe_dict(executionContainer, 'execution', {})
783
+ rawTrades.append(rawTrade)
784
+ else:
785
+ request, params = self.handle_until_option('lastTime', request, params)
786
+ response = self.publicGetHistory(self.extend(request, params))
787
+ #
788
+ # {
789
+ # "result": "success",
790
+ # "history": [
791
+ # {
792
+ # "time": "2022-03-18T04:55:37.692Z",
793
+ # "trade_id": 100,
794
+ # "price": 0.7921,
795
+ # "size": 1068,
796
+ # "side": "sell",
797
+ # "type": "fill",
798
+ # "uid": "6c5da0b0-f1a8-483f-921f-466eb0388265"
799
+ # },
800
+ # ...
801
+ # ],
802
+ # "serverTime": "2022-03-18T06:39:18.056Z"
803
+ # }
804
+ #
805
+ rawTrades = self.safe_list(response, 'history', [])
806
+ return self.parse_trades(rawTrades, market, since, limit)
807
+
808
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
809
+ #
810
+ # fetchTrades(recent trades)
811
+ #
812
+ # {
813
+ # "time": "2019-02-14T09:25:33.920Z",
814
+ # "trade_id": 100,
815
+ # "price": 3574,
816
+ # "size": 100,
817
+ # "side": "buy",
818
+ # "type": "fill" # fill, liquidation, assignment, termination
819
+ # "uid": "11c3d82c-9e70-4fe9-8115-f643f1b162d4"
820
+ # }
821
+ #
822
+ # fetchTrades(executions history)
823
+ #
824
+ # {
825
+ # "timestamp": "1710152516830",
826
+ # "price": "71927.0",
827
+ # "quantity": "0.0695",
828
+ # "markPrice": "71936.38701675525",
829
+ # "limitFilled": True,
830
+ # "usdValue": "4998.93",
831
+ # "uid": "116ae634-253f-470b-bd20-fa9d429fb8b1",
832
+ # "makerOrder": {"uid": "17bfe4de-c01e-4938-926c-617d2a2d0597", "tradeable": "PF_XBTUSD", "direction": "Buy", "quantity": "0.0695", "timestamp": "1710152515836", "limitPrice": "71927.0", "orderType": "Post", "reduceOnly": False, "lastUpdateTimestamp": "1710152515836"},
833
+ # "takerOrder": {"uid": "d3e437b4-aa70-4108-b5cf-b1eecb9845b5", "tradeable": "PF_XBTUSD", "direction": "Sell", "quantity": "0.940100", "timestamp": "1710152516830", "limitPrice": "71915", "orderType": "IoC", "reduceOnly": False, "lastUpdateTimestamp": "1710152516830"}
834
+ # }
835
+ #
836
+ # fetchMyTrades(private)
837
+ #
838
+ # {
839
+ # "fillTime": "2016-02-25T09:47:01.000Z",
840
+ # "order_id": "c18f0c17-9971-40e6-8e5b-10df05d422f0",
841
+ # "fill_id": "522d4e08-96e7-4b44-9694-bfaea8fe215e",
842
+ # "cliOrdId": "d427f920-ec55-4c18-ba95-5fe241513b30", # OPTIONAL
843
+ # "symbol": "fi_xbtusd_180615",
844
+ # "side": "buy",
845
+ # "size": 2000,
846
+ # "price": 4255,
847
+ # "fillType": "maker" # taker, takerAfterEdit, maker, liquidation, assignee
848
+ # }
849
+ #
850
+ # execution report(createOrder, editOrder)
851
+ #
852
+ # {
853
+ # "executionId": "e1ec9f63-2338-4c44-b40a-43486c6732d7",
854
+ # "price": 7244.5,
855
+ # "amount": 10,
856
+ # "orderPriorEdit": null,
857
+ # "orderPriorExecution": {
858
+ # "orderId": "61ca5732-3478-42fe-8362-abbfd9465294",
859
+ # "cliOrdId": null,
860
+ # "type": "lmt",
861
+ # "symbol": "pi_xbtusd",
862
+ # "side": "buy",
863
+ # "quantity": 10,
864
+ # "filled": 0,
865
+ # "limitPrice": 7500,
866
+ # "reduceOnly": False,
867
+ # "timestamp": "2019-12-11T17:17:33.888Z",
868
+ # "lastUpdateTimestamp": "2019-12-11T17:17:33.888Z"
869
+ # },
870
+ # "takerReducedQuantity": null,
871
+ # "type": "EXECUTION"
872
+ # }
873
+ #
874
+ timestamp = self.parse8601(self.safe_string_2(trade, 'time', 'fillTime'))
875
+ price = self.safe_string(trade, 'price')
876
+ amount = self.safe_string_n(trade, ['size', 'amount', 'quantity'], '0.0')
877
+ id = self.safe_string_2(trade, 'uid', 'fill_id')
878
+ if id is None:
879
+ id = self.safe_string(trade, 'executionId')
880
+ order = self.safe_string(trade, 'order_id')
881
+ marketId = self.safe_string(trade, 'symbol')
882
+ side = self.safe_string(trade, 'side')
883
+ type = None
884
+ priorEdit = self.safe_value(trade, 'orderPriorEdit')
885
+ priorExecution = self.safe_value(trade, 'orderPriorExecution')
886
+ if priorExecution is not None:
887
+ order = self.safe_string(priorExecution, 'orderId')
888
+ marketId = self.safe_string(priorExecution, 'symbol')
889
+ side = self.safe_string(priorExecution, 'side')
890
+ type = self.safe_string(priorExecution, 'type')
891
+ elif priorEdit is not None:
892
+ order = self.safe_string(priorEdit, 'orderId')
893
+ marketId = self.safe_string(priorEdit, 'symbol')
894
+ side = self.safe_string(priorEdit, 'type')
895
+ type = self.safe_string(priorEdit, 'type')
896
+ if type is not None:
897
+ type = self.parse_order_type(type)
898
+ market = self.safe_market(marketId, market)
899
+ cost = None
900
+ linear = self.safe_bool(market, 'linear')
901
+ if (amount is not None) and (price is not None) and (market is not None):
902
+ if linear:
903
+ cost = Precise.string_mul(amount, price) # in quote
904
+ else:
905
+ cost = Precise.string_div(amount, price) # in base
906
+ contractSize = self.safe_string(market, 'contractSize')
907
+ cost = Precise.string_mul(cost, contractSize)
908
+ takerOrMaker = None
909
+ fillType = self.safe_string(trade, 'fillType')
910
+ if fillType is not None:
911
+ if fillType.find('taker') >= 0:
912
+ takerOrMaker = 'taker'
913
+ elif fillType.find('maker') >= 0:
914
+ takerOrMaker = 'maker'
915
+ isHistoricalExecution = ('takerOrder' in trade)
916
+ if isHistoricalExecution:
917
+ timestamp = self.safe_integer(trade, 'timestamp')
918
+ taker = self.safe_dict(trade, 'takerOrder', {})
919
+ if taker is not None:
920
+ side = self.safe_string_lower(taker, 'direction')
921
+ takerOrMaker = 'taker'
922
+ return self.safe_trade({
923
+ 'info': trade,
924
+ 'id': id,
925
+ 'symbol': self.safe_string(market, 'symbol'),
926
+ 'timestamp': timestamp,
927
+ 'datetime': self.iso8601(timestamp),
928
+ 'order': order,
929
+ 'type': type,
930
+ 'side': side,
931
+ 'takerOrMaker': takerOrMaker,
932
+ 'price': price,
933
+ 'amount': amount if linear else None,
934
+ 'cost': cost,
935
+ 'fee': None,
936
+ })
937
+
938
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
939
+ market = self.market(symbol)
940
+ symbol = market['symbol']
941
+ type = self.safe_string(params, 'orderType', type)
942
+ timeInForce = self.safe_string(params, 'timeInForce')
943
+ postOnly = False
944
+ postOnly, params = self.handle_post_only(type == 'market', type == 'post', params)
945
+ if postOnly:
946
+ type = 'post'
947
+ elif timeInForce == 'ioc':
948
+ type = 'ioc'
949
+ elif type == 'limit':
950
+ type = 'lmt'
951
+ elif type == 'market':
952
+ type = 'mkt'
953
+ request: dict = {
954
+ 'symbol': market['id'],
955
+ 'side': side,
956
+ 'size': self.amount_to_precision(symbol, amount),
957
+ }
958
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'cliOrdId')
959
+ if clientOrderId is not None:
960
+ request['cliOrdId'] = clientOrderId
961
+ triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
962
+ isTriggerOrder = triggerPrice is not None
963
+ stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
964
+ takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
965
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
966
+ isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
967
+ isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
968
+ triggerSignal = self.safe_string(params, 'triggerSignal', 'last')
969
+ reduceOnly = self.safe_value(params, 'reduceOnly')
970
+ if isStopLossOrTakeProfitTrigger or isTriggerOrder:
971
+ request['triggerSignal'] = triggerSignal
972
+ if isTriggerOrder:
973
+ type = 'stp'
974
+ request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
975
+ elif isStopLossOrTakeProfitTrigger:
976
+ reduceOnly = True
977
+ if isStopLossTriggerOrder:
978
+ type = 'stp'
979
+ request['stopPrice'] = self.price_to_precision(symbol, stopLossTriggerPrice)
980
+ elif isTakeProfitTriggerOrder:
981
+ type = 'take_profit'
982
+ request['stopPrice'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
983
+ if reduceOnly:
984
+ request['reduceOnly'] = True
985
+ request['orderType'] = type
986
+ if price is not None:
987
+ request['limitPrice'] = self.price_to_precision(symbol, price)
988
+ params = self.omit(params, ['clientOrderId', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
989
+ return self.extend(request, params)
990
+
991
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
992
+ """
993
+ Create an order on the exchange
994
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-send-order
995
+ :param str symbol: unified market symbol
996
+ :param str type: 'limit' or 'market'
997
+ :param str side: 'buy' or 'sell'
998
+ :param float amount: number of contracts
999
+ :param float [price]: limit order price
1000
+ :param bool [params.reduceOnly]: set if you wish the order to only reduce an existing position, any order which increases an existing position will be rejected, default is False
1001
+ :param bool [params.postOnly]: set if you wish to make a postOnly order, default is False
1002
+ :param str [params.clientOrderId]: UUID The order identity that is specified from the user, It must be globally unique
1003
+ :param float [params.triggerPrice]: the price that a stop order is triggered at
1004
+ :param float [params.stopLossPrice]: the price that a stop loss order is triggered at
1005
+ :param float [params.takeProfitPrice]: the price that a take profit order is triggered at
1006
+ :param str [params.triggerSignal]: for triggerPrice, stopLossPrice and takeProfitPrice orders, the trigger price type, 'last', 'mark' or 'index', default is 'last'
1007
+ """
1008
+ self.load_markets()
1009
+ market = self.market(symbol)
1010
+ orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
1011
+ response = self.privatePostSendorder(orderRequest)
1012
+ #
1013
+ # {
1014
+ # "result": "success",
1015
+ # "sendStatus": {
1016
+ # "order_id": "salf320-e337-47ac-b345-30sdfsalj",
1017
+ # "status": "placed",
1018
+ # "receivedTime": "2022-02-28T19:32:17.122Z",
1019
+ # "orderEvents": [
1020
+ # {
1021
+ # "order": {
1022
+ # "orderId": "salf320-e337-47ac-b345-30sdfsalj",
1023
+ # "cliOrdId": null,
1024
+ # "type": "lmt",
1025
+ # "symbol": "pi_xrpusd",
1026
+ # "side": "buy",
1027
+ # "quantity": 1,
1028
+ # "filled": 0,
1029
+ # "limitPrice": 0.7,
1030
+ # "reduceOnly": False,
1031
+ # "timestamp": "2022-02-28T19:32:17.122Z",
1032
+ # "lastUpdateTimestamp": "2022-02-28T19:32:17.122Z"
1033
+ # },
1034
+ # "reducedQuantity": null,
1035
+ # "type": "PLACE"
1036
+ # }
1037
+ # ]
1038
+ # },
1039
+ # "serverTime": "2022-02-28T19:32:17.122Z"
1040
+ # }
1041
+ #
1042
+ sendStatus = self.safe_value(response, 'sendStatus')
1043
+ status = self.safe_string(sendStatus, 'status')
1044
+ self.verify_order_action_success(status, 'createOrder', ['filled'])
1045
+ return self.parse_order(sendStatus, market)
1046
+
1047
+ def create_orders(self, orders: List[OrderRequest], params={}):
1048
+ """
1049
+ create a list of trade orders
1050
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
1051
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1052
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1053
+ """
1054
+ self.load_markets()
1055
+ ordersRequests = []
1056
+ for i in range(0, len(orders)):
1057
+ rawOrder = orders[i]
1058
+ marketId = self.safe_string(rawOrder, 'symbol')
1059
+ type = self.safe_string(rawOrder, 'type')
1060
+ side = self.safe_string(rawOrder, 'side')
1061
+ amount = self.safe_value(rawOrder, 'amount')
1062
+ price = self.safe_value(rawOrder, 'price')
1063
+ orderParams = self.safe_value(rawOrder, 'params', {})
1064
+ extendedParams = self.extend(orderParams, params) # the request does not accept extra params since it's a list, so we're extending each order with the common params
1065
+ if not ('order_tag' in extendedParams):
1066
+ # order tag is mandatory so we will generate one if not provided
1067
+ extendedParams['order_tag'] = self.sum(i, str(1)) # sequential counter
1068
+ extendedParams['order'] = 'send'
1069
+ orderRequest = self.create_order_request(marketId, type, side, amount, price, extendedParams)
1070
+ ordersRequests.append(orderRequest)
1071
+ request: dict = {
1072
+ 'batchOrder': ordersRequests,
1073
+ }
1074
+ response = self.privatePostBatchorder(self.extend(request, params))
1075
+ #
1076
+ # {
1077
+ # "result": "success",
1078
+ # "serverTime": "2023-10-24T08:40:57.339Z",
1079
+ # "batchStatus": [
1080
+ # {
1081
+ # "status": "requiredArgumentMissing",
1082
+ # "orderEvents": []
1083
+ # },
1084
+ # {
1085
+ # "status": "requiredArgumentMissing",
1086
+ # "orderEvents": []
1087
+ # }
1088
+ # ]
1089
+ # }
1090
+ #
1091
+ data = self.safe_list(response, 'batchStatus', [])
1092
+ return self.parse_orders(data)
1093
+
1094
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1095
+ """
1096
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-edit-order
1097
+ Edit an open order on the exchange
1098
+ :param str id: order id
1099
+ :param str symbol: Not used by Krakenfutures
1100
+ :param str type: Not used by Krakenfutures
1101
+ :param str side: Not used by Krakenfutures
1102
+ :param float amount: Order size
1103
+ :param float [price]: Price to fill order at
1104
+ :param dict [params]: Exchange specific params
1105
+ :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1106
+ """
1107
+ self.load_markets()
1108
+ request: dict = {
1109
+ 'orderId': id,
1110
+ }
1111
+ if amount is not None:
1112
+ request['size'] = amount
1113
+ if price is not None:
1114
+ request['limitPrice'] = price
1115
+ response = self.privatePostEditorder(self.extend(request, params))
1116
+ status = self.safe_string(response['editStatus'], 'status')
1117
+ self.verify_order_action_success(status, 'editOrder', ['filled'])
1118
+ order = self.parse_order(response['editStatus'])
1119
+ order['info'] = response
1120
+ return order
1121
+
1122
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
1123
+ """
1124
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-order
1125
+ Cancel an open order on the exchange
1126
+ :param str id: Order id
1127
+ :param str symbol: Not used by Krakenfutures
1128
+ :param dict [params]: Exchange specific params
1129
+ :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1130
+ """
1131
+ self.load_markets()
1132
+ response = self.privatePostCancelorder(self.extend({'order_id': id}, params))
1133
+ status = self.safe_string(self.safe_value(response, 'cancelStatus', {}), 'status')
1134
+ self.verify_order_action_success(status, 'cancelOrder')
1135
+ order: dict = {}
1136
+ if 'cancelStatus' in response:
1137
+ order = self.parse_order(response['cancelStatus'])
1138
+ return self.extend({'info': response}, order)
1139
+
1140
+ def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
1141
+ """
1142
+ cancel multiple orders
1143
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
1144
+ :param str[] ids: order ids
1145
+ :param str [symbol]: unified market symbol
1146
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1147
+ *
1148
+ * EXCHANGE SPECIFIC PARAMETERS
1149
+ :param str[] [params.clientOrderIds]: max length 10 e.g. ["my_id_1","my_id_2"]
1150
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1151
+ """
1152
+ self.load_markets()
1153
+ orders = []
1154
+ clientOrderIds = self.safe_value(params, 'clientOrderIds', [])
1155
+ clientOrderIdsLength = len(clientOrderIds)
1156
+ if clientOrderIdsLength > 0:
1157
+ for i in range(0, len(clientOrderIds)):
1158
+ orders.append({'order': 'cancel', 'cliOrdId': clientOrderIds[i]})
1159
+ else:
1160
+ for i in range(0, len(ids)):
1161
+ orders.append({'order': 'cancel', 'order_id': ids[i]})
1162
+ request: dict = {
1163
+ 'batchOrder': orders,
1164
+ }
1165
+ response = self.privatePostBatchorder(self.extend(request, params))
1166
+ # {
1167
+ # "result": "success",
1168
+ # "serverTime": "2023-10-23T16:36:51.327Z",
1169
+ # "batchStatus": [
1170
+ # {
1171
+ # "status": "cancelled",
1172
+ # "order_id": "101c2327-f12e-45f2-8445-7502b87afc0b",
1173
+ # "orderEvents": [
1174
+ # {
1175
+ # "uid": "101c2327-f12e-45f2-8445-7502b87afc0b",
1176
+ # "order": {
1177
+ # "orderId": "101c2327-f12e-45f2-8445-7502b87afc0b",
1178
+ # "cliOrdId": null,
1179
+ # "type": "lmt",
1180
+ # "symbol": "PF_LTCUSD",
1181
+ # "side": "buy",
1182
+ # "quantity": "0.10000000000",
1183
+ # "filled": "0E-11",
1184
+ # "limitPrice": "50.00000000000",
1185
+ # "reduceOnly": False,
1186
+ # "timestamp": "2023-10-20T10:29:13.005Z",
1187
+ # "lastUpdateTimestamp": "2023-10-20T10:29:13.005Z"
1188
+ # },
1189
+ # "type": "CANCEL"
1190
+ # }
1191
+ # ]
1192
+ # }
1193
+ # ]
1194
+ # }
1195
+ batchStatus = self.safe_list(response, 'batchStatus', [])
1196
+ return self.parse_orders(batchStatus)
1197
+
1198
+ def cancel_all_orders(self, symbol: Str = None, params={}):
1199
+ """
1200
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-all-orders
1201
+ Cancels all orders on the exchange, including trigger orders
1202
+ :param str symbol: Unified market symbol
1203
+ :param dict [params]: Exchange specific params
1204
+ :returns: Response from exchange api
1205
+ """
1206
+ request: dict = {}
1207
+ if symbol is not None:
1208
+ request['symbol'] = self.market_id(symbol)
1209
+ response = self.privatePostCancelallorders(self.extend(request, params))
1210
+ #
1211
+ # {
1212
+ # result: 'success',
1213
+ # cancelStatus: {
1214
+ # receivedTime: '2024-06-06T01:12:44.814Z',
1215
+ # cancelOnly: 'PF_XRPUSD',
1216
+ # status: 'cancelled',
1217
+ # cancelledOrders: [{order_id: '272fd0ac-45c0-4003-b84d-d39b9e86bd36'}],
1218
+ # orderEvents: [
1219
+ # {
1220
+ # uid: '272fd0ac-45c0-4003-b84d-d39b9e86bd36',
1221
+ # order: {
1222
+ # orderId: '272fd0ac-45c0-4003-b84d-d39b9e86bd36',
1223
+ # cliOrdId: null,
1224
+ # type: 'lmt',
1225
+ # symbol: 'PF_XRPUSD',
1226
+ # side: 'buy',
1227
+ # quantity: '10',
1228
+ # filled: '0',
1229
+ # limitPrice: '0.4',
1230
+ # reduceOnly: False,
1231
+ # timestamp: '2024-06-06T01:11:16.045Z',
1232
+ # lastUpdateTimestamp: '2024-06-06T01:11:16.045Z'
1233
+ # },
1234
+ # type: 'CANCEL'
1235
+ # }
1236
+ # ]
1237
+ # },
1238
+ # serverTime: '2024-06-06T01:12:44.814Z'
1239
+ # }
1240
+ #
1241
+ cancelStatus = self.safe_dict(response, 'cancelStatus')
1242
+ orderEvents = self.safe_list(cancelStatus, 'orderEvents', [])
1243
+ orders = []
1244
+ for i in range(0, len(orderEvents)):
1245
+ orderEvent = self.safe_dict(orderEvents, 0)
1246
+ order = self.safe_dict(orderEvent, 'order', {})
1247
+ orders.append(order)
1248
+ return self.parse_orders(orders)
1249
+
1250
+ def cancel_all_orders_after(self, timeout: Int, params={}):
1251
+ """
1252
+ dead man's switch, cancel all orders after the given timeout
1253
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-dead-man-39-s-switch
1254
+ :param number timeout: time in milliseconds, 0 represents cancel the timer
1255
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1256
+ :returns dict: the api result
1257
+ """
1258
+ self.load_markets()
1259
+ request: dict = {
1260
+ 'timeout': (self.parse_to_int(timeout / 1000)) if (timeout > 0) else 0,
1261
+ }
1262
+ response = self.privatePostCancelallordersafter(self.extend(request, params))
1263
+ #
1264
+ # {
1265
+ # "result": "success",
1266
+ # "serverTime": "2018-06-19T16:51:23.839Z",
1267
+ # "status": {
1268
+ # "currentTime": "2018-06-19T16:51:23.839Z",
1269
+ # "triggerTime": "0"
1270
+ # }
1271
+ # }
1272
+ #
1273
+ return response
1274
+
1275
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1276
+ """
1277
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-get-open-orders
1278
+ Gets all open orders, including trigger orders, for an account from the exchange api
1279
+ :param str symbol: Unified market symbol
1280
+ :param int [since]: Timestamp(ms) of earliest order.(Not used by kraken api but filtered internally by CCXT)
1281
+ :param int [limit]: How many orders to return.(Not used by kraken api but filtered internally by CCXT)
1282
+ :param dict [params]: Exchange specific parameters
1283
+ :returns: An array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1284
+ """
1285
+ self.load_markets()
1286
+ market = None
1287
+ if symbol is not None:
1288
+ market = self.market(symbol)
1289
+ response = self.privateGetOpenorders(params)
1290
+ orders = self.safe_list(response, 'openOrders', [])
1291
+ return self.parse_orders(orders, market, since, limit)
1292
+
1293
+ def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1294
+ """
1295
+ :see: https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
1296
+ Gets all closed orders, including trigger orders, for an account from the exchange api
1297
+ :param str symbol: Unified market symbol
1298
+ :param int [since]: Timestamp(ms) of earliest order.
1299
+ :param int [limit]: How many orders to return.
1300
+ :param dict [params]: Exchange specific parameters
1301
+ :returns: An array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1302
+ """
1303
+ self.load_markets()
1304
+ market = None
1305
+ if symbol is not None:
1306
+ market = self.market(symbol)
1307
+ request: dict = {}
1308
+ if limit is not None:
1309
+ request['count'] = limit
1310
+ if since is not None:
1311
+ request['from'] = since
1312
+ response = self.historyGetOrders(self.extend(request, params))
1313
+ allOrders = self.safe_list(response, 'elements', [])
1314
+ closedOrders = []
1315
+ for i in range(0, len(allOrders)):
1316
+ order = allOrders[i]
1317
+ event = self.safe_dict(order, 'event', {})
1318
+ orderPlaced = self.safe_dict(event, 'OrderPlaced')
1319
+ if orderPlaced is not None:
1320
+ innerOrder = self.safe_dict(orderPlaced, 'order', {})
1321
+ filled = self.safe_string(innerOrder, 'filled')
1322
+ if filled != '0':
1323
+ innerOrder['status'] = 'closed' # status not available in the response
1324
+ closedOrders.append(innerOrder)
1325
+ return self.parse_orders(closedOrders, market, since, limit)
1326
+
1327
+ def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1328
+ """
1329
+ :see: https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
1330
+ Gets all canceled orders, including trigger orders, for an account from the exchange api
1331
+ :param str symbol: Unified market symbol
1332
+ :param int [since]: Timestamp(ms) of earliest order.
1333
+ :param int [limit]: How many orders to return.
1334
+ :param dict [params]: Exchange specific parameters
1335
+ :returns: An array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1336
+ """
1337
+ self.load_markets()
1338
+ market = None
1339
+ if symbol is not None:
1340
+ market = self.market(symbol)
1341
+ request: dict = {}
1342
+ if limit is not None:
1343
+ request['count'] = limit
1344
+ if since is not None:
1345
+ request['from'] = since
1346
+ response = self.historyGetOrders(self.extend(request, params))
1347
+ allOrders = self.safe_list(response, 'elements', [])
1348
+ canceledAndRejected = []
1349
+ for i in range(0, len(allOrders)):
1350
+ order = allOrders[i]
1351
+ event = self.safe_dict(order, 'event', {})
1352
+ orderPlaced = self.safe_dict(event, 'OrderPlaced')
1353
+ if orderPlaced is not None:
1354
+ innerOrder = self.safe_dict(orderPlaced, 'order', {})
1355
+ filled = self.safe_string(innerOrder, 'filled')
1356
+ if filled == '0':
1357
+ innerOrder['status'] = 'canceled' # status not available in the response
1358
+ canceledAndRejected.append(innerOrder)
1359
+ orderCanceled = self.safe_dict(event, 'OrderCancelled')
1360
+ if orderCanceled is not None:
1361
+ innerOrder = self.safe_dict(orderCanceled, 'order', {})
1362
+ innerOrder['status'] = 'canceled' # status not available in the response
1363
+ canceledAndRejected.append(innerOrder)
1364
+ orderRejected = self.safe_dict(event, 'OrderRejected')
1365
+ if orderRejected is not None:
1366
+ innerOrder = self.safe_dict(orderRejected, 'order', {})
1367
+ innerOrder['status'] = 'rejected' # status not available in the response
1368
+ canceledAndRejected.append(innerOrder)
1369
+ return self.parse_orders(canceledAndRejected, market, since, limit)
1370
+
1371
+ def parse_order_type(self, orderType):
1372
+ map: dict = {
1373
+ 'lmt': 'limit',
1374
+ 'mkt': 'market',
1375
+ 'post': 'limit',
1376
+ 'ioc': 'market',
1377
+ }
1378
+ return self.safe_string(map, orderType, orderType)
1379
+
1380
+ def verify_order_action_success(self, status, method, omit=[]):
1381
+ errors: dict = {
1382
+ 'invalidOrderType': InvalidOrder,
1383
+ 'invalidSide': InvalidOrder,
1384
+ 'invalidSize': InvalidOrder,
1385
+ 'invalidPrice': InvalidOrder,
1386
+ 'insufficientAvailableFunds': InsufficientFunds,
1387
+ 'selfFill': ExchangeError,
1388
+ 'tooManySmallOrders': ExchangeError,
1389
+ 'maxPositionViolation': BadRequest,
1390
+ 'marketSuspended': ExchangeNotAvailable,
1391
+ 'marketInactive': ExchangeNotAvailable,
1392
+ 'clientOrderIdAlreadyExist': DuplicateOrderId,
1393
+ 'clientOrderIdTooLong': BadRequest,
1394
+ 'outsidePriceCollar': InvalidOrder,
1395
+ 'postWouldExecute': OrderImmediatelyFillable, # the unplaced order could actually be parsed(with status = "rejected"), but there is self specific error for self
1396
+ 'iocWouldNotExecute': OrderNotFillable, # -||-
1397
+ 'wouldNotReducePosition': ExchangeError,
1398
+ 'orderForEditNotFound': OrderNotFound,
1399
+ 'orderForEditNotAStop': InvalidOrder,
1400
+ 'filled': OrderNotFound,
1401
+ 'notFound': OrderNotFound,
1402
+ }
1403
+ if (status in errors) and not self.in_array(status, omit):
1404
+ raise errors[status](self.id + ': ' + method + ' failed due to ' + status)
1405
+
1406
+ def parse_order_status(self, status: Str):
1407
+ statuses: dict = {
1408
+ 'placed': 'open', # the order was placed successfully
1409
+ 'cancelled': 'canceled', # the order was cancelled successfully
1410
+ 'invalidOrderType': 'rejected', # the order was not placed because orderType is invalid
1411
+ 'invalidSide': 'rejected', # the order was not placed because side is invalid
1412
+ 'invalidSize': 'rejected', # the order was not placed because size is invalid
1413
+ 'invalidPrice': 'rejected', # the order was not placed because limitPrice and/or stopPrice are invalid
1414
+ 'insufficientAvailableFunds': 'rejected', # the order was not placed because available funds are insufficient
1415
+ 'selfFill': 'rejected', # the order was not placed because it would be filled against an existing order belonging to the same account
1416
+ 'tooManySmallOrders': 'rejected', # the order was not placed because the number of small open orders would exceed the permissible limit
1417
+ 'maxPositionViolation': 'rejected', # Order would cause you to exceed your maximum hasattr(self, position) contract.
1418
+ 'marketSuspended': 'rejected', # the order was not placed because the market is suspended
1419
+ 'marketInactive': 'rejected', # the order was not placed because the market is inactive
1420
+ 'clientOrderIdAlreadyExist': 'rejected', # the specified client id already exist
1421
+ 'clientOrderIdTooLong': 'rejected', # the client id is longer than the permissible limit
1422
+ 'outsidePriceCollar': 'rejected', # the limit order crosses the spread but is an order of magnitude away from the mark price - fat finger control
1423
+ # Should the next two be 'expired' ?
1424
+ 'postWouldExecute': 'rejected', # the post-only order would be filled upon placement, thus is cancelled
1425
+ 'iocWouldNotExecute': 'rejected', # the immediate-or-cancel order would not execute.
1426
+ 'wouldNotReducePosition': 'rejected', # the reduce only order would not reduce position.
1427
+ 'edited': 'open', # the order was edited successfully
1428
+ 'orderForEditNotFound': 'rejected', # the requested order for edit has not been found
1429
+ 'orderForEditNotAStop': 'rejected', # the supplied stopPrice cannot be applied because order is not a stop order
1430
+ 'filled': 'closed', # the order was found completely filled and could not be cancelled
1431
+ 'notFound': 'rejected', # the order was not found, either because it had already been cancelled or it never existed
1432
+ 'untouched': 'open', # the entire size of the order is unfilled
1433
+ 'partiallyFilled': 'open', # the size of the order is partially but not entirely filled
1434
+ }
1435
+ return self.safe_string(statuses, status, status)
1436
+
1437
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1438
+ #
1439
+ # LIMIT
1440
+ #
1441
+ # {
1442
+ # "order_id": "179f9af8-e45e-469d-b3e9-2fd4675cb7d0",
1443
+ # "status": "placed",
1444
+ # "receivedTime": "2019-09-05T16:33:50.734Z",
1445
+ # "orderEvents": [
1446
+ # {
1447
+ # "uid": "614a5298-0071-450f-83c6-0617ce8c6bc4",
1448
+ # "order": {
1449
+ # "orderId": "179f9af8-e45e-469d-b3e9-2fd4675cb7d0",
1450
+ # "cliOrdId": null,
1451
+ # "type": "lmt",
1452
+ # "symbol": "pi_xbtusd",
1453
+ # "side": "buy",
1454
+ # "quantity": 10000,
1455
+ # "filled": 0,
1456
+ # "limitPrice": 9400,
1457
+ # "reduceOnly": False,
1458
+ # "timestamp": "2019-09-05T16:33:50.734Z",
1459
+ # "lastUpdateTimestamp": "2019-09-05T16:33:50.734Z"
1460
+ # },
1461
+ # "reducedQuantity": null,
1462
+ # "reason": "WOULD_NOT_REDUCE_POSITION", # REJECTED
1463
+ # "type": "PLACE"
1464
+ # }
1465
+ # ]
1466
+ # }
1467
+ #
1468
+ # CONDITIONAL
1469
+ #
1470
+ # {
1471
+ # "order_id": "1abfd3c6-af93-4b30-91cc-e4a93797f3f5",
1472
+ # "status": "placed",
1473
+ # "receivedTime": "2019-12-05T10:20:50.701Z",
1474
+ # "orderEvents": [
1475
+ # {
1476
+ # "orderTrigger": {
1477
+ # "uid": "1abfd3c6-af93-4b30-91cc-e4a93797f3f5",
1478
+ # "clientId":null,
1479
+ # "type": "lmt", # "ioc" if stop market
1480
+ # "symbol": "pi_xbtusd",
1481
+ # "side": "buy",
1482
+ # "quantity":10,
1483
+ # "limitPrice":15000,
1484
+ # "triggerPrice":9500,
1485
+ # "triggerSide": "trigger_below",
1486
+ # "triggerSignal": "mark_price",
1487
+ # "reduceOnly":false,
1488
+ # "timestamp": "2019-12-05T10:20:50.701Z",
1489
+ # "lastUpdateTimestamp": "2019-12-05T10:20:50.701Z"
1490
+ # },
1491
+ # "type": "PLACE"
1492
+ # }
1493
+ # ]
1494
+ # }
1495
+ #
1496
+ # EXECUTION
1497
+ #
1498
+ # {
1499
+ # "order_id": "61ca5732-3478-42fe-8362-abbfd9465294",
1500
+ # "status": "placed",
1501
+ # "receivedTime": "2019-12-11T17:17:33.888Z",
1502
+ # "orderEvents": [
1503
+ # {
1504
+ # "executionId": "e1ec9f63-2338-4c44-b40a-43486c6732d7",
1505
+ # "price": 7244.5,
1506
+ # "amount": 10,
1507
+ # "orderPriorEdit": null,
1508
+ # "orderPriorExecution": {
1509
+ # "orderId": "61ca5732-3478-42fe-8362-abbfd9465294",
1510
+ # "cliOrdId": null,
1511
+ # "type": "lmt",
1512
+ # "symbol": "pi_xbtusd",
1513
+ # "side": "buy",
1514
+ # "quantity": 10,
1515
+ # "filled": 0,
1516
+ # "limitPrice": 7500,
1517
+ # "reduceOnly": False,
1518
+ # "timestamp": "2019-12-11T17:17:33.888Z",
1519
+ # "lastUpdateTimestamp": "2019-12-11T17:17:33.888Z"
1520
+ # },
1521
+ # "takerReducedQuantity": null,
1522
+ # "type": "EXECUTION"
1523
+ # }
1524
+ # ]
1525
+ # }
1526
+ #
1527
+ # EDIT ORDER
1528
+ #
1529
+ # {
1530
+ # "status": "edited",
1531
+ # "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
1532
+ # "receivedTime": "2019-09-05T16:47:47.521Z",
1533
+ # "orderEvents": [
1534
+ # {
1535
+ # "old": {
1536
+ # "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
1537
+ # "cliOrdId":null,
1538
+ # "type": "lmt",
1539
+ # "symbol": "pi_xbtusd",
1540
+ # "side": "buy",
1541
+ # "quantity":1000,
1542
+ # "filled":0,
1543
+ # "limitPrice":9400.0,
1544
+ # "reduceOnly":false,
1545
+ # "timestamp": "2019-09-05T16:41:35.173Z",
1546
+ # "lastUpdateTimestamp": "2019-09-05T16:41:35.173Z"
1547
+ # },
1548
+ # "new": {
1549
+ # "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
1550
+ # "cliOrdId": null,
1551
+ # "type": "lmt",
1552
+ # "symbol": "pi_xbtusd",
1553
+ # "side": "buy",
1554
+ # "quantity": 1501,
1555
+ # "filled": 0,
1556
+ # "limitPrice": 7200,
1557
+ # "reduceOnly": False,
1558
+ # "timestamp": "2019-09-05T16:41:35.173Z",
1559
+ # "lastUpdateTimestamp": "2019-09-05T16:47:47.519Z"
1560
+ # },
1561
+ # "reducedQuantity": null,
1562
+ # "type": "EDIT"
1563
+ # }
1564
+ # ]
1565
+ # }
1566
+ #
1567
+ # CANCEL ORDER
1568
+ #
1569
+ # {
1570
+ # "status": "cancelled",
1571
+ # "orderEvents": [
1572
+ # {
1573
+ # "uid": "85c40002-3f20-4e87-9302-262626c3531b",
1574
+ # "order": {
1575
+ # "orderId": "85c40002-3f20-4e87-9302-262626c3531b",
1576
+ # "cliOrdId": null,
1577
+ # "type": "lmt",
1578
+ # "symbol": "pi_xbtusd",
1579
+ # "side": "buy",
1580
+ # "quantity": 1000,
1581
+ # "filled": 0,
1582
+ # "limitPrice": 10144,
1583
+ # "stopPrice": null,
1584
+ # "reduceOnly": False,
1585
+ # "timestamp": "2019-08-01T15:26:27.790Z"
1586
+ # },
1587
+ # "type": "CANCEL"
1588
+ # }
1589
+ # ]
1590
+ # }
1591
+ #
1592
+ # cancelAllOrders
1593
+ #
1594
+ # {
1595
+ # "orderId": "85c40002-3f20-4e87-9302-262626c3531b",
1596
+ # "cliOrdId": null,
1597
+ # "type": "lmt",
1598
+ # "symbol": "pi_xbtusd",
1599
+ # "side": "buy",
1600
+ # "quantity": 1000,
1601
+ # "filled": 0,
1602
+ # "limitPrice": 10144,
1603
+ # "stopPrice": null,
1604
+ # "reduceOnly": False,
1605
+ # "timestamp": "2019-08-01T15:26:27.790Z"
1606
+ # }
1607
+ #
1608
+ # FETCH OPEN ORDERS
1609
+ #
1610
+ # {
1611
+ # "order_id": "59302619-41d2-4f0b-941f-7e7914760ad3",
1612
+ # "symbol": "pi_xbtusd",
1613
+ # "side": "sell",
1614
+ # "orderType": "lmt",
1615
+ # "limitPrice": 10640,
1616
+ # "unfilledSize": 304,
1617
+ # "receivedTime": "2019-09-05T17:01:17.410Z",
1618
+ # "status": "untouched",
1619
+ # "filledSize": 0,
1620
+ # "reduceOnly": True,
1621
+ # "lastUpdateTime": "2019-09-05T17:01:17.410Z"
1622
+ # }
1623
+ #
1624
+ # createOrders error
1625
+ # {
1626
+ # "status": "requiredArgumentMissing",
1627
+ # "orderEvents": []
1628
+ # }
1629
+ # closed orders
1630
+ # {
1631
+ # uid: '2f00cd63-e61d-44f8-8569-adabde885941',
1632
+ # timestamp: '1707258274849',
1633
+ # event: {
1634
+ # OrderPlaced: {
1635
+ # order: {
1636
+ # uid: '85805e01-9eed-4395-8360-ed1a228237c9',
1637
+ # accountUid: '406142dd-7c5c-4a8b-acbc-5f16eca30009',
1638
+ # tradeable: 'PF_LTCUSD',
1639
+ # direction: 'Buy',
1640
+ # quantity: '0',
1641
+ # filled: '0.1',
1642
+ # timestamp: '1707258274849',
1643
+ # limitPrice: '69.2200000000',
1644
+ # orderType: 'IoC',
1645
+ # clientId: '',
1646
+ # reduceOnly: False,
1647
+ # lastUpdateTimestamp: '1707258274849'
1648
+ # },
1649
+ # reason: 'new_user_order',
1650
+ # reducedQuantity: '',
1651
+ # algoId: ''
1652
+ # }
1653
+ # }
1654
+ # }
1655
+ #
1656
+ orderEvents = self.safe_value(order, 'orderEvents', [])
1657
+ errorStatus = self.safe_string(order, 'status')
1658
+ orderEventsLength = len(orderEvents)
1659
+ if ('orderEvents' in order) and (errorStatus is not None) and (orderEventsLength == 0):
1660
+ # creteOrders error response
1661
+ return self.safe_order({'info': order, 'status': 'rejected'})
1662
+ details = None
1663
+ isPrior = False
1664
+ fixed = False
1665
+ statusId = None
1666
+ price = None
1667
+ trades = []
1668
+ if orderEventsLength:
1669
+ executions = []
1670
+ for i in range(0, len(orderEvents)):
1671
+ item = orderEvents[i]
1672
+ if self.safe_string(item, 'type') == 'EXECUTION':
1673
+ executions.append(item)
1674
+ # Final order(after placement / editing / execution / canceling)
1675
+ orderTrigger = self.safe_value(item, 'orderTrigger')
1676
+ details = self.safe_value_2(item, 'new', 'order', orderTrigger)
1677
+ if details is not None:
1678
+ isPrior = False
1679
+ fixed = True
1680
+ elif not fixed:
1681
+ orderPriorExecution = self.safe_value(item, 'orderPriorExecution')
1682
+ details = self.safe_value_2(item, 'orderPriorExecution', 'orderPriorEdit')
1683
+ price = self.safe_string(orderPriorExecution, 'limitPrice')
1684
+ if details is not None:
1685
+ isPrior = True
1686
+ trades = self.parse_trades(executions)
1687
+ statusId = self.safe_string(order, 'status')
1688
+ if details is None:
1689
+ details = order
1690
+ if statusId is None:
1691
+ statusId = self.safe_string(details, 'status')
1692
+ # This may be incorrectly marked as "open" if only execution report is given,
1693
+ # but will be fixed below
1694
+ status = self.parse_order_status(statusId)
1695
+ isClosed = self.in_array(status, ['canceled', 'rejected', 'closed'])
1696
+ marketId = self.safe_string(details, 'symbol')
1697
+ market = self.safe_market(marketId, market)
1698
+ timestamp = self.parse8601(self.safe_string_2(details, 'timestamp', 'receivedTime'))
1699
+ lastUpdateTimestamp = self.parse8601(self.safe_string(details, 'lastUpdateTime'))
1700
+ if price is None:
1701
+ price = self.safe_string(details, 'limitPrice')
1702
+ amount = self.safe_string(details, 'quantity')
1703
+ filled = self.safe_string_2(details, 'filledSize', 'filled', '0.0')
1704
+ remaining = self.safe_string(details, 'unfilledSize')
1705
+ average = None
1706
+ filled2 = '0.0'
1707
+ tradesLength = len(trades)
1708
+ if tradesLength > 0:
1709
+ vwapSum = '0.0'
1710
+ for i in range(0, len(trades)):
1711
+ trade = trades[i]
1712
+ tradeAmount = self.safe_string(trade, 'amount')
1713
+ tradePrice = self.safe_string(trade, 'price')
1714
+ filled2 = Precise.string_add(filled2, tradeAmount)
1715
+ vwapSum = Precise.string_add(vwapSum, Precise.string_mul(tradeAmount, tradePrice))
1716
+ average = Precise.string_div(vwapSum, filled2)
1717
+ if (amount is not None) and (not isClosed) and isPrior and Precise.string_ge(filled2, amount):
1718
+ status = 'closed'
1719
+ isClosed = True
1720
+ if isPrior:
1721
+ filled = Precise.string_add(filled, filled2)
1722
+ else:
1723
+ filled = Precise.string_max(filled, filled2)
1724
+ if remaining is None:
1725
+ if isPrior:
1726
+ if amount is not None:
1727
+ # remaining amount before execution minus executed amount
1728
+ remaining = Precise.string_sub(amount, filled2)
1729
+ else:
1730
+ remaining = amount
1731
+ # if fetchOpenOrders are parsed
1732
+ if (amount is None) and (not isPrior) and (remaining is not None):
1733
+ amount = Precise.string_add(filled, remaining)
1734
+ cost = None
1735
+ if (filled is not None) and (market is not None):
1736
+ whichPrice = average if (average is not None) else price
1737
+ if whichPrice is not None:
1738
+ if market['linear']:
1739
+ cost = Precise.string_mul(filled, whichPrice) # in quote
1740
+ else:
1741
+ cost = Precise.string_div(filled, whichPrice) # in base
1742
+ id = self.safe_string_2(order, 'order_id', 'orderId')
1743
+ if id is None:
1744
+ id = self.safe_string_2(details, 'orderId', 'uid')
1745
+ type = self.safe_string_lower_2(details, 'type', 'orderType')
1746
+ timeInForce = 'gtc'
1747
+ if type == 'ioc' or self.parse_order_type(type) == 'market':
1748
+ timeInForce = 'ioc'
1749
+ return self.safe_order({
1750
+ 'info': order,
1751
+ 'id': id,
1752
+ 'clientOrderId': self.safe_string_n(details, ['clientOrderId', 'clientId', 'cliOrdId']),
1753
+ 'timestamp': timestamp,
1754
+ 'datetime': self.iso8601(timestamp),
1755
+ 'lastTradeTimestamp': None,
1756
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1757
+ 'symbol': self.safe_string(market, 'symbol'),
1758
+ 'type': self.parse_order_type(type),
1759
+ 'timeInForce': timeInForce,
1760
+ 'postOnly': type == 'post',
1761
+ 'reduceOnly': self.safe_value(details, 'reduceOnly'),
1762
+ 'side': self.safe_string(details, 'side'),
1763
+ 'price': price,
1764
+ 'stopPrice': self.safe_string(details, 'triggerPrice'),
1765
+ 'triggerPrice': self.safe_string(details, 'triggerPrice'),
1766
+ 'amount': amount,
1767
+ 'cost': cost,
1768
+ 'average': average,
1769
+ 'filled': filled,
1770
+ 'remaining': remaining,
1771
+ 'status': status,
1772
+ 'fee': None,
1773
+ 'fees': None,
1774
+ 'trades': trades,
1775
+ })
1776
+
1777
+ def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1778
+ """
1779
+ fetch all trades made by the user
1780
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-data-get-your-fills
1781
+ :param str symbol: unified market symbol
1782
+ :param int [since]: *not used by the api* the earliest time in ms to fetch trades for
1783
+ :param int [limit]: the maximum number of trades structures to retrieve
1784
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1785
+ :param int [params.until]: the latest time in ms to fetch entries for
1786
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1787
+ """
1788
+ self.load_markets()
1789
+ market = None
1790
+ if symbol is not None:
1791
+ market = self.market(symbol)
1792
+ response = self.privateGetFills(params)
1793
+ #
1794
+ # {
1795
+ # "result": "success",
1796
+ # "serverTime": "2016-02-25T09:45:53.818Z",
1797
+ # "fills": [
1798
+ # {
1799
+ # "fillTime": "2016-02-25T09:47:01.000Z",
1800
+ # "order_id": "c18f0c17-9971-40e6-8e5b-10df05d422f0",
1801
+ # "fill_id": "522d4e08-96e7-4b44-9694-bfaea8fe215e",
1802
+ # "cliOrdId": "d427f920-ec55-4c18-ba95-5fe241513b30", # EXTRA
1803
+ # "symbol": "fi_xbtusd_180615",
1804
+ # "side": "buy",
1805
+ # "size": 2000,
1806
+ # "price": 4255,
1807
+ # "fillType": "maker"
1808
+ # },
1809
+ # ...
1810
+ # ]
1811
+ # }
1812
+ #
1813
+ return self.parse_trades(response['fills'], market, since, limit)
1814
+
1815
+ def fetch_balance(self, params={}) -> Balances:
1816
+ """
1817
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-account-information-get-wallets
1818
+ Fetch the balance for a sub-account, all sub-account balances are inside 'info' in the response
1819
+ :param dict [params]: Exchange specific parameters
1820
+ :param str [params.type]: The sub-account type to query the balance of, possible values include 'flex', 'cash'/'main'/'funding', or a market symbol * defaults to 'flex' *
1821
+ :param str [params.symbol]: A unified market symbol, when assigned the balance for a trading market that matches the symbol is returned
1822
+ :returns: A `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1823
+ """
1824
+ self.load_markets()
1825
+ type = self.safe_string_2(params, 'type', 'account')
1826
+ symbol = self.safe_string(params, 'symbol')
1827
+ params = self.omit(params, ['type', 'account', 'symbol'])
1828
+ response = self.privateGetAccounts(params)
1829
+ #
1830
+ # {
1831
+ # "result": "success",
1832
+ # "accounts": {
1833
+ # "fi_xbtusd": {
1834
+ # "auxiliary": {usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0"},
1835
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1836
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1837
+ # "balances": {xbt: "0.0"},
1838
+ # "currency": "xbt",
1839
+ # "type": "marginAccount"
1840
+ # },
1841
+ # "cash": {
1842
+ # "balances": {
1843
+ # "eur": "0.0",
1844
+ # "gbp": "0.0",
1845
+ # "bch": "0.0",
1846
+ # "xrp": "2.20188538338",
1847
+ # "usd": "0.0",
1848
+ # "eth": "0.0",
1849
+ # "usdt": "0.0",
1850
+ # "ltc": "0.0",
1851
+ # "usdc": "0.0",
1852
+ # "xbt": "0.0"
1853
+ # },
1854
+ # "type": "cashAccount"
1855
+ # },
1856
+ # "fv_xrpxbt": {
1857
+ # "auxiliary": {usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0"},
1858
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1859
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1860
+ # "balances": {xbt: "0.0"},
1861
+ # "currency": "xbt",
1862
+ # "type": "marginAccount"
1863
+ # },
1864
+ # "fi_xrpusd": {
1865
+ # "auxiliary": {usd: "0", pv: '11.0', pnl: '0.0', af: '11.0', funding: "0.0"},
1866
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1867
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1868
+ # "balances": {xrp: "11.0"},
1869
+ # "currency": "xrp",
1870
+ # "type": "marginAccount"
1871
+ # },
1872
+ # "fi_ethusd": {
1873
+ # "auxiliary": {usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0"},
1874
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1875
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1876
+ # "balances": {eth: "0.0"},
1877
+ # "currency": "eth",
1878
+ # "type": "marginAccount"
1879
+ # },
1880
+ # "fi_ltcusd": {
1881
+ # "auxiliary": {usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0"},
1882
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1883
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1884
+ # "balances": {ltc: "0.0"},
1885
+ # "currency": "ltc",
1886
+ # "type": "marginAccount"
1887
+ # },
1888
+ # "fi_bchusd": {
1889
+ # "auxiliary": {usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0"},
1890
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1891
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1892
+ # "balances": {bch: "0.0"},
1893
+ # "currency": "bch",
1894
+ # "type": "marginAccount"
1895
+ # },
1896
+ # "flex": {
1897
+ # "currencies": {},
1898
+ # "initialMargin": "0.0",
1899
+ # "initialMarginWithOrders": "0.0",
1900
+ # "maintenanceMargin": "0.0",
1901
+ # "balanceValue": "0.0",
1902
+ # "portfolioValue": "0.0",
1903
+ # "collateralValue": "0.0",
1904
+ # "pnl": "0.0",
1905
+ # "unrealizedFunding": "0.0",
1906
+ # "totalUnrealized": "0.0",
1907
+ # "totalUnrealizedAsMargin": "0.0",
1908
+ # "availableMargin": "0.0",
1909
+ # "marginEquity": "0.0",
1910
+ # "type": "multiCollateralMarginAccount"
1911
+ # }
1912
+ # },
1913
+ # "serverTime": "2022-04-12T07:48:07.475Z"
1914
+ # }
1915
+ #
1916
+ datetime = self.safe_string(response, 'serverTime')
1917
+ if type == 'marginAccount' or type == 'margin':
1918
+ if symbol is None:
1919
+ raise ArgumentsRequired(self.id + ' fetchBalance requires symbol argument for margin accounts')
1920
+ type = symbol
1921
+ if type is None:
1922
+ type = 'flex' if (symbol is None) else symbol
1923
+ accountName = self.parse_account(type)
1924
+ accounts = self.safe_value(response, 'accounts')
1925
+ account = self.safe_value(accounts, accountName)
1926
+ if account is None:
1927
+ type = '' if (type is None) else type
1928
+ symbol = '' if (symbol is None) else symbol
1929
+ raise BadRequest(self.id + ' fetchBalance has no account for ' + type)
1930
+ balance = self.parse_balance(account)
1931
+ balance['info'] = response
1932
+ balance['timestamp'] = self.parse8601(datetime)
1933
+ balance['datetime'] = datetime
1934
+ return balance
1935
+
1936
+ def parse_balance(self, response) -> Balances:
1937
+ #
1938
+ # cashAccount
1939
+ #
1940
+ # {
1941
+ # "balances": {
1942
+ # "eur": "0.0",
1943
+ # "gbp": "0.0",
1944
+ # "bch": "0.0",
1945
+ # "xrp": "2.20188538338",
1946
+ # "usd": "0.0",
1947
+ # "eth": "0.0",
1948
+ # "usdt": "0.0",
1949
+ # "ltc": "0.0",
1950
+ # "usdc": "0.0",
1951
+ # "xbt": "0.0"
1952
+ # },
1953
+ # "type": "cashAccount"
1954
+ # }
1955
+ #
1956
+ # marginAccount e,g, fi_xrpusd
1957
+ #
1958
+ # {
1959
+ # "auxiliary": {
1960
+ # "usd": "0",
1961
+ # "pv": "11.0",
1962
+ # "pnl": "0.0",
1963
+ # "af": "11.0",
1964
+ # "funding": "0.0"
1965
+ # },
1966
+ # "marginRequirements": {im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0"},
1967
+ # "triggerEstimates": {im: '0', mm: '0', lt: "0", tt: "0"},
1968
+ # "balances": {xrp: "11.0"},
1969
+ # "currency": "xrp",
1970
+ # "type": "marginAccount"
1971
+ # }
1972
+ #
1973
+ # flex/multiCollateralMarginAccount
1974
+ #
1975
+ # {
1976
+ # "currencies": {
1977
+ # "USDT": {
1978
+ # "quantity": "1",
1979
+ # "value": "1.0001",
1980
+ # "collateral": "0.9477197625",
1981
+ # "available": "1.0"
1982
+ # }
1983
+ # },
1984
+ # "initialMargin": "0.0",
1985
+ # "initialMarginWithOrders": "0.0",
1986
+ # "maintenanceMargin": "0.0",
1987
+ # "balanceValue": "1.0",
1988
+ # "portfolioValue": "1.0",
1989
+ # "collateralValue": "0.95",
1990
+ # "pnl": "0.0",
1991
+ # "unrealizedFunding": "0.0",
1992
+ # "totalUnrealized": "0.0",
1993
+ # "totalUnrealizedAsMargin": "0.0",
1994
+ # "availableMargin": "0.95",
1995
+ # "marginEquity": "0.95",
1996
+ # "type": "multiCollateralMarginAccount"
1997
+ # }
1998
+ #
1999
+ accountType = self.safe_string_2(response, 'accountType', 'type')
2000
+ isFlex = (accountType == 'multiCollateralMarginAccount')
2001
+ isCash = (accountType == 'cashAccount')
2002
+ balances = self.safe_value_2(response, 'balances', 'currencies', {})
2003
+ result: dict = {}
2004
+ currencyIds = list(balances.keys())
2005
+ for i in range(0, len(currencyIds)):
2006
+ currencyId = currencyIds[i]
2007
+ balance = balances[currencyId]
2008
+ code = self.safe_currency_code(currencyId)
2009
+ splitCode = code.split('_')
2010
+ codeLength = len(splitCode)
2011
+ if codeLength > 1:
2012
+ continue # Removes contract codes like PI_XRPUSD
2013
+ account = self.account()
2014
+ if isFlex:
2015
+ account['total'] = self.safe_string(balance, 'quantity')
2016
+ account['free'] = self.safe_string(balance, 'available')
2017
+ elif isCash:
2018
+ account['used'] = '0.0'
2019
+ account['total'] = balance
2020
+ else:
2021
+ auxiliary = self.safe_value(response, 'auxiliary')
2022
+ account['free'] = self.safe_string(auxiliary, 'af')
2023
+ account['total'] = self.safe_string(auxiliary, 'pv')
2024
+ result[code] = account
2025
+ return self.safe_balance(result)
2026
+
2027
+ def fetch_funding_rates(self, symbols: Strings = None, params={}):
2028
+ """
2029
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-tickers
2030
+ fetch the current funding rates
2031
+ :param str[] symbols: unified market symbols
2032
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2033
+ :returns Order[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2034
+ """
2035
+ self.load_markets()
2036
+ marketIds = self.market_ids(symbols)
2037
+ response = self.publicGetTickers(params)
2038
+ tickers = self.safe_value(response, 'tickers')
2039
+ fundingRates = []
2040
+ for i in range(0, len(tickers)):
2041
+ entry = tickers[i]
2042
+ entry_symbol = self.safe_value(entry, 'symbol')
2043
+ if marketIds is not None:
2044
+ if not self.in_array(entry_symbol, marketIds):
2045
+ continue
2046
+ market = self.safe_market(entry_symbol)
2047
+ parsed = self.parse_funding_rate(entry, market)
2048
+ fundingRates.append(parsed)
2049
+ return self.index_by(fundingRates, 'symbol')
2050
+
2051
+ def parse_funding_rate(self, ticker, market: Market = None):
2052
+ #
2053
+ # {"ask": 26.283,
2054
+ # "askSize": 4.6,
2055
+ # "bid": 26.201,
2056
+ # "bidSize": 190,
2057
+ # "fundingRate": -0.000944642727438883,
2058
+ # "fundingRatePrediction": -0.000872671532340275,
2059
+ # "indexPrice": 26.253,
2060
+ # "last": 26.3,
2061
+ # "lastSize": 0.1,
2062
+ # "lastTime": "2023-06-11T18:55:28.958Z",
2063
+ # "markPrice": 26.239,
2064
+ # "open24h": 26.3,
2065
+ # "openInterest": 641.1,
2066
+ # "pair": "COMP:USD",
2067
+ # "postOnly": False,
2068
+ # "suspended": False,
2069
+ # "symbol": "pf_compusd",
2070
+ # "tag": "perpetual",
2071
+ # "vol24h": 0.1,
2072
+ # "volumeQuote": 2.63}
2073
+ #
2074
+ fundingRateMultiplier = '8' # https://support.kraken.com/hc/en-us/articles/9618146737172-Perpetual-Contracts-Funding-Rate-Method-Prior-to-September-29-2022
2075
+ marketId = self.safe_string(ticker, 'symbol')
2076
+ symbol = self.symbol(marketId)
2077
+ timestamp = self.parse8601(self.safe_string(ticker, 'lastTime'))
2078
+ indexPrice = self.safe_number(ticker, 'indexPrice')
2079
+ markPriceString = self.safe_string(ticker, 'markPrice')
2080
+ markPrice = self.parse_number(markPriceString)
2081
+ fundingRateString = self.safe_string(ticker, 'fundingRate')
2082
+ fundingRateResult = Precise.string_div(Precise.string_mul(fundingRateString, fundingRateMultiplier), markPriceString)
2083
+ fundingRate = self.parse_number(fundingRateResult)
2084
+ nextFundingRateString = self.safe_string(ticker, 'fundingRatePrediction')
2085
+ nextFundingRateResult = Precise.string_div(Precise.string_mul(nextFundingRateString, fundingRateMultiplier), markPriceString)
2086
+ nextFundingRate = self.parse_number(nextFundingRateResult)
2087
+ return {
2088
+ 'info': ticker,
2089
+ 'symbol': symbol,
2090
+ 'markPrice': markPrice,
2091
+ 'indexPrice': indexPrice,
2092
+ 'interestRate': None,
2093
+ 'estimatedSettlePrice': None,
2094
+ 'timestamp': timestamp,
2095
+ 'datetime': self.iso8601(timestamp),
2096
+ 'fundingRate': fundingRate,
2097
+ 'fundingTimestamp': None,
2098
+ 'fundingDatetime': None,
2099
+ 'nextFundingRate': nextFundingRate,
2100
+ 'nextFundingTimestamp': None,
2101
+ 'nextFundingDatetime': None,
2102
+ 'previousFundingRate': None,
2103
+ 'previousFundingTimestamp': None,
2104
+ 'previousFundingDatetime': None,
2105
+ }
2106
+
2107
+ def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2108
+ """
2109
+ fetches historical funding rate prices
2110
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-funding-rates-historical-funding-rates
2111
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2112
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
2113
+ :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
2114
+ :param dict [params]: extra parameters specific to the api endpoint
2115
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2116
+ """
2117
+ if symbol is None:
2118
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
2119
+ self.load_markets()
2120
+ market = self.market(symbol)
2121
+ if not market['swap']:
2122
+ raise BadRequest(self.id + ' fetchFundingRateHistory() supports swap contracts only')
2123
+ request: dict = {
2124
+ 'symbol': market['id'].upper(),
2125
+ }
2126
+ response = self.publicGetHistoricalfundingrates(self.extend(request, params))
2127
+ #
2128
+ # {
2129
+ # "rates": [
2130
+ # {
2131
+ # "timestamp": '2018-08-31T16:00:00.000Z',
2132
+ # "fundingRate": '2.18900669884E-7',
2133
+ # "relativeFundingRate": '0.000060779960000000'
2134
+ # },
2135
+ # ...
2136
+ # ]
2137
+ # }
2138
+ #
2139
+ rates = self.safe_value(response, 'rates')
2140
+ result = []
2141
+ for i in range(0, len(rates)):
2142
+ item = rates[i]
2143
+ datetime = self.safe_string(item, 'timestamp')
2144
+ result.append({
2145
+ 'info': item,
2146
+ 'symbol': symbol,
2147
+ 'fundingRate': self.safe_number(item, 'relativeFundingRate'),
2148
+ 'timestamp': self.parse8601(datetime),
2149
+ 'datetime': datetime,
2150
+ })
2151
+ sorted = self.sort_by(result, 'timestamp')
2152
+ return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
2153
+
2154
+ def fetch_positions(self, symbols: Strings = None, params={}):
2155
+ """
2156
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-account-information-get-open-positions
2157
+ Fetches current contract trading positions
2158
+ :param str[] symbols: List of unified symbols
2159
+ :param dict [params]: Not used by krakenfutures
2160
+ :returns: Parsed exchange response for positions
2161
+ """
2162
+ self.load_markets()
2163
+ request: dict = {}
2164
+ response = self.privateGetOpenpositions(request)
2165
+ #
2166
+ # {
2167
+ # "result": "success",
2168
+ # "openPositions": [
2169
+ # {
2170
+ # "side": "long",
2171
+ # "symbol": "pi_xrpusd",
2172
+ # "price": "0.7533",
2173
+ # "fillTime": "2022-03-03T22:51:16.566Z",
2174
+ # "size": "230",
2175
+ # "unrealizedFunding": "-0.001878596918214635"
2176
+ # }
2177
+ # ],
2178
+ # "serverTime": "2022-03-03T22:51:16.566Z"
2179
+ # }
2180
+ #
2181
+ result = self.parse_positions(response)
2182
+ return self.filter_by_array_positions(result, 'symbol', symbols, False)
2183
+
2184
+ def parse_positions(self, response, symbols: Strings = None, params={}):
2185
+ result = []
2186
+ positions = self.safe_value(response, 'openPositions')
2187
+ for i in range(0, len(positions)):
2188
+ position = self.parse_position(positions[i])
2189
+ result.append(position)
2190
+ return result
2191
+
2192
+ def parse_position(self, position: dict, market: Market = None):
2193
+ # cross
2194
+ # {
2195
+ # "side": "long",
2196
+ # "symbol": "pi_xrpusd",
2197
+ # "price": "0.7533",
2198
+ # "fillTime": "2022-03-03T22:51:16.566Z",
2199
+ # "size": "230",
2200
+ # "unrealizedFunding": "-0.001878596918214635"
2201
+ # }
2202
+ #
2203
+ # isolated
2204
+ # {
2205
+ # "side":"long",
2206
+ # "symbol":"pf_ftmusd",
2207
+ # "price":"0.4921",
2208
+ # "fillTime":"2023-02-22T11:37:16.685Z",
2209
+ # "size":"1",
2210
+ # "unrealizedFunding":"-8.155240068885155E-8",
2211
+ # "pnlCurrency":"USD",
2212
+ # "maxFixedLeverage":"1.0"
2213
+ # }
2214
+ #
2215
+ leverage = self.safe_number(position, 'maxFixedLeverage')
2216
+ marginType = 'cross'
2217
+ if leverage is not None:
2218
+ marginType = 'isolated'
2219
+ datetime = self.safe_string(position, 'fillTime')
2220
+ marketId = self.safe_string(position, 'symbol')
2221
+ market = self.safe_market(marketId, market)
2222
+ return {
2223
+ 'info': position,
2224
+ 'symbol': market['symbol'],
2225
+ 'timestamp': self.parse8601(datetime),
2226
+ 'datetime': datetime,
2227
+ 'initialMargin': None,
2228
+ 'initialMarginPercentage': None,
2229
+ 'maintenanceMargin': None,
2230
+ 'maintenanceMarginPercentage': None,
2231
+ 'entryPrice': self.safe_number(position, 'price'),
2232
+ 'notional': None,
2233
+ 'leverage': leverage,
2234
+ 'unrealizedPnl': None,
2235
+ 'contracts': self.safe_number(position, 'size'),
2236
+ 'contractSize': self.safe_number(market, 'contractSize'),
2237
+ 'marginRatio': None,
2238
+ 'liquidationPrice': None,
2239
+ 'markPrice': None,
2240
+ 'collateral': None,
2241
+ 'marginType': marginType,
2242
+ 'side': self.safe_string(position, 'side'),
2243
+ 'percentage': None,
2244
+ }
2245
+
2246
+ def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
2247
+ """
2248
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-instrument-details-get-instruments
2249
+ retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
2250
+ :param str[]|None symbols: list of unified market symbols
2251
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2252
+ :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
2253
+ """
2254
+ self.load_markets()
2255
+ response = self.publicGetInstruments(params)
2256
+ #
2257
+ # {
2258
+ # "result": "success",
2259
+ # "instruments": [
2260
+ # {
2261
+ # "symbol": "fi_ethusd_180928",
2262
+ # "type": "futures_inverse", # futures_vanilla # spot index
2263
+ # "underlying": "rr_ethusd",
2264
+ # "lastTradingTime": "2018-09-28T15:00:00.000Z",
2265
+ # "tickSize": 0.1,
2266
+ # "contractSize": 1,
2267
+ # "tradeable": True,
2268
+ # "marginLevels": [
2269
+ # {
2270
+ # "contracts":0,
2271
+ # "initialMargin":0.02,
2272
+ # "maintenanceMargin":0.01
2273
+ # },
2274
+ # {
2275
+ # "contracts":250000,
2276
+ # "initialMargin":0.04,
2277
+ # "maintenanceMargin":0.02
2278
+ # },
2279
+ # ...
2280
+ # ],
2281
+ # "isin": "GB00JVMLMP88",
2282
+ # "retailMarginLevels": [
2283
+ # {
2284
+ # "contracts": 0,
2285
+ # "initialMargin": 0.5,
2286
+ # "maintenanceMargin": 0.25
2287
+ # }
2288
+ # ],
2289
+ # "tags": [],
2290
+ # },
2291
+ # {
2292
+ # "symbol": "in_xbtusd",
2293
+ # "type": "spot index",
2294
+ # "tradeable":false
2295
+ # }
2296
+ # ]
2297
+ # "serverTime": "2018-07-19T11:32:39.433Z"
2298
+ # }
2299
+ #
2300
+ data = self.safe_list(response, 'instruments')
2301
+ return self.parse_leverage_tiers(data, symbols, 'symbol')
2302
+
2303
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
2304
+ """
2305
+ * @ignore
2306
+ * @param info Exchange market response for 1 market
2307
+ * @param market CCXT market
2308
+ """
2309
+ #
2310
+ # {
2311
+ # "symbol": "fi_ethusd_180928",
2312
+ # "type": "futures_inverse", # futures_vanilla # spot index
2313
+ # "underlying": "rr_ethusd",
2314
+ # "lastTradingTime": "2018-09-28T15:00:00.000Z",
2315
+ # "tickSize": 0.1,
2316
+ # "contractSize": 1,
2317
+ # "tradeable": True,
2318
+ # "marginLevels": [
2319
+ # {
2320
+ # "contracts":0,
2321
+ # "initialMargin":0.02,
2322
+ # "maintenanceMargin":0.01
2323
+ # },
2324
+ # {
2325
+ # "contracts":250000,
2326
+ # "initialMargin":0.04,
2327
+ # "maintenanceMargin":0.02
2328
+ # },
2329
+ # ...
2330
+ # ],
2331
+ # "isin": "GB00JVMLMP88",
2332
+ # "retailMarginLevels": [
2333
+ # {
2334
+ # "contracts": 0,
2335
+ # "initialMargin": 0.5,
2336
+ # "maintenanceMargin": 0.25
2337
+ # }
2338
+ # ],
2339
+ # "tags": [],
2340
+ # }
2341
+ #
2342
+ marginLevels = self.safe_value(info, 'marginLevels')
2343
+ id = self.safe_string(info, 'symbol')
2344
+ market = self.safe_market(id, market)
2345
+ tiers = []
2346
+ for i in range(0, len(marginLevels)):
2347
+ tier = marginLevels[i]
2348
+ initialMargin = self.safe_string(tier, 'initialMargin')
2349
+ notionalFloor = self.safe_number(tier, 'contracts')
2350
+ if i != 0:
2351
+ tiersLength = len(tiers)
2352
+ previousTier = tiers[tiersLength - 1]
2353
+ previousTier['notionalCap'] = notionalFloor
2354
+ tiers.append({
2355
+ 'tier': self.sum(i, 1),
2356
+ 'currency': market['quote'],
2357
+ 'notionalFloor': notionalFloor,
2358
+ 'notionalCap': None,
2359
+ 'maintenanceMarginRate': self.safe_number(tier, 'maintenanceMargin'),
2360
+ 'maxLeverage': self.parse_number(Precise.string_div('1', initialMargin)),
2361
+ 'info': tier,
2362
+ })
2363
+ return tiers
2364
+
2365
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2366
+ #
2367
+ # transfer
2368
+ #
2369
+ # {
2370
+ # "result": "success",
2371
+ # "serverTime": "2022-04-12T01:22:53.420Z"
2372
+ # }
2373
+ #
2374
+ datetime = self.safe_string(transfer, 'serverTime')
2375
+ return {
2376
+ 'info': transfer,
2377
+ 'id': None,
2378
+ 'timestamp': self.parse8601(datetime),
2379
+ 'datetime': datetime,
2380
+ 'currency': self.safe_string(currency, 'code'),
2381
+ 'amount': None,
2382
+ 'fromAccount': None,
2383
+ 'toAccount': None,
2384
+ 'status': self.safe_string(transfer, 'result'),
2385
+ }
2386
+
2387
+ def parse_account(self, account):
2388
+ accountByType: dict = {
2389
+ 'main': 'cash',
2390
+ 'funding': 'cash',
2391
+ 'future': 'cash',
2392
+ 'futures': 'cash',
2393
+ 'cashAccount': 'cash',
2394
+ 'multiCollateralMarginAccount': 'flex',
2395
+ 'multiCollateral': 'flex',
2396
+ 'multiCollateralMargin': 'flex',
2397
+ }
2398
+ if account in accountByType:
2399
+ return accountByType[account]
2400
+ elif account in self.markets:
2401
+ market = self.market(account)
2402
+ marketId = market['id']
2403
+ splitId = marketId.split('_')
2404
+ if market['inverse']:
2405
+ return 'fi_' + self.safe_string(splitId, 1)
2406
+ else:
2407
+ return 'fv_' + self.safe_string(splitId, 1)
2408
+ else:
2409
+ return account
2410
+
2411
+ def transfer_out(self, code: str, amount, params={}):
2412
+ """
2413
+ transfer from futures wallet to spot wallet
2414
+ :param str code: Unified currency code
2415
+ :param float amount: Size of the transfer
2416
+ :param dict [params]: Exchange specific parameters
2417
+ :returns: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2418
+ """
2419
+ return self.transfer(code, amount, 'future', 'spot', params)
2420
+
2421
+ def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2422
+ """
2423
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-transfers-initiate-wallet-transfer
2424
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-transfers-initiate-withdrawal-to-spot-wallet
2425
+ transfers currencies between sub-accounts
2426
+ :param str code: Unified currency code
2427
+ :param float amount: Size of the transfer
2428
+ :param str fromAccount: 'main'/'funding'/'future', 'flex', or a unified market symbol
2429
+ :param str toAccount: 'main'/'funding', 'flex', 'spot' or a unified market symbol
2430
+ :param dict [params]: Exchange specific parameters
2431
+ :returns: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2432
+ """
2433
+ self.load_markets()
2434
+ currency = self.currency(code)
2435
+ if fromAccount == 'spot':
2436
+ raise BadRequest(self.id + ' transfer does not yet support transfers from spot')
2437
+ request: dict = {
2438
+ 'amount': amount,
2439
+ }
2440
+ response = None
2441
+ if toAccount == 'spot':
2442
+ if self.parse_account(fromAccount) != 'cash':
2443
+ raise BadRequest(self.id + ' transfer cannot transfer from ' + fromAccount + ' to ' + toAccount)
2444
+ request['currency'] = currency['id']
2445
+ response = self.privatePostWithdrawal(self.extend(request, params))
2446
+ else:
2447
+ request['fromAccount'] = self.parse_account(fromAccount)
2448
+ request['toAccount'] = self.parse_account(toAccount)
2449
+ request['unit'] = currency['id']
2450
+ response = self.privatePostTransfer(self.extend(request, params))
2451
+ #
2452
+ # {
2453
+ # "result": "success",
2454
+ # "serverTime": "2022-04-12T01:22:53.420Z"
2455
+ # }
2456
+ #
2457
+ transfer = self.parse_transfer(response, currency)
2458
+ return self.extend(transfer, {
2459
+ 'amount': amount,
2460
+ 'fromAccount': fromAccount,
2461
+ 'toAccount': toAccount,
2462
+ })
2463
+
2464
+ def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2465
+ """
2466
+ set the level of leverage for a market
2467
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-set-the-leverage-setting-for-a-market
2468
+ :param float leverage: the rate of leverage
2469
+ :param str symbol: unified market symbol
2470
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2471
+ :returns dict: response from the exchange
2472
+ """
2473
+ if symbol is None:
2474
+ raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
2475
+ self.load_markets()
2476
+ request: dict = {
2477
+ 'maxLeverage': leverage,
2478
+ 'symbol': self.market_id(symbol).upper(),
2479
+ }
2480
+ #
2481
+ # {result: "success", serverTime: "2023-08-01T09:40:32.345Z"}
2482
+ #
2483
+ return self.privatePutLeveragepreferences(self.extend(request, params))
2484
+
2485
+ def fetch_leverages(self, symbols: Strings = None, params={}) -> Leverages:
2486
+ """
2487
+ fetch the set leverage for all contract and margin markets
2488
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-get-the-leverage-setting-for-a-market
2489
+ :param str[] [symbols]: a list of unified market symbols
2490
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2491
+ :returns dict: a list of `leverage structures <https://docs.ccxt.com/#/?id=leverage-structure>`
2492
+ """
2493
+ self.load_markets()
2494
+ response = self.privateGetLeveragepreferences(params)
2495
+ #
2496
+ # {
2497
+ # "result": "success",
2498
+ # "serverTime": "2024-03-06T02:35:46.336Z",
2499
+ # "leveragePreferences": [
2500
+ # {
2501
+ # "symbol": "PF_ETHUSD",
2502
+ # "maxLeverage": 30.00
2503
+ # },
2504
+ # ]
2505
+ # }
2506
+ #
2507
+ leveragePreferences = self.safe_list(response, 'leveragePreferences', [])
2508
+ return self.parse_leverages(leveragePreferences, symbols, 'symbol')
2509
+
2510
+ def fetch_leverage(self, symbol: str, params={}) -> Leverage:
2511
+ """
2512
+ fetch the set leverage for a market
2513
+ :see: https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-get-the-leverage-setting-for-a-market
2514
+ :param str symbol: unified market symbol
2515
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2516
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
2517
+ """
2518
+ if symbol is None:
2519
+ raise ArgumentsRequired(self.id + ' fetchLeverage() requires a symbol argument')
2520
+ self.load_markets()
2521
+ market = self.market(symbol)
2522
+ request: dict = {
2523
+ 'symbol': self.market_id(symbol).upper(),
2524
+ }
2525
+ response = self.privateGetLeveragepreferences(self.extend(request, params))
2526
+ #
2527
+ # {
2528
+ # "result": "success",
2529
+ # "serverTime": "2023-08-01T09:54:08.900Z",
2530
+ # "leveragePreferences": [{symbol: "PF_LTCUSD", maxLeverage: "5.00"}]
2531
+ # }
2532
+ #
2533
+ leveragePreferences = self.safe_list(response, 'leveragePreferences', [])
2534
+ data = self.safe_dict(leveragePreferences, 0, {})
2535
+ return self.parse_leverage(data, market)
2536
+
2537
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
2538
+ marketId = self.safe_string(leverage, 'symbol')
2539
+ leverageValue = self.safe_integer(leverage, 'maxLeverage')
2540
+ return {
2541
+ 'info': leverage,
2542
+ 'symbol': self.safe_symbol(marketId, market),
2543
+ 'marginMode': None,
2544
+ 'longLeverage': leverageValue,
2545
+ 'shortLeverage': leverageValue,
2546
+ }
2547
+
2548
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2549
+ if response is None:
2550
+ return None
2551
+ if code == 429:
2552
+ raise DDoSProtection(self.id + ' ' + body)
2553
+ errors = self.safe_value(response, 'errors')
2554
+ firstError = self.safe_value(errors, 0)
2555
+ firtErrorMessage = self.safe_string(firstError, 'message')
2556
+ message = self.safe_string(response, 'error', firtErrorMessage)
2557
+ if message is None:
2558
+ return None
2559
+ feedback = self.id + ' ' + body
2560
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2561
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2562
+ if code == 400:
2563
+ raise BadRequest(feedback)
2564
+ raise ExchangeError(feedback) # unknown message
2565
+
2566
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2567
+ apiVersions = self.safe_value(self.options['versions'], api, {})
2568
+ methodVersions = self.safe_value(apiVersions, method, {})
2569
+ defaultVersion = self.safe_string(methodVersions, path, self.version)
2570
+ version = self.safe_string(params, 'version', defaultVersion)
2571
+ params = self.omit(params, 'version')
2572
+ apiAccess = self.safe_value(self.options['access'], api, {})
2573
+ methodAccess = self.safe_value(apiAccess, method, {})
2574
+ access = self.safe_string(methodAccess, path, 'public')
2575
+ endpoint = version + '/' + self.implode_params(path, params)
2576
+ params = self.omit(params, self.extract_params(path))
2577
+ query = endpoint
2578
+ postData = ''
2579
+ if path == 'batchorder':
2580
+ postData = 'json=' + self.json(params)
2581
+ body = postData
2582
+ elif params:
2583
+ postData = self.urlencode(params)
2584
+ query += '?' + postData
2585
+ url = self.urls['api'][api] + query
2586
+ if api == 'private' or access == 'private':
2587
+ self.check_required_credentials()
2588
+ auth = postData + '/api/'
2589
+ if api != 'private':
2590
+ auth += api + '/'
2591
+ auth += endpoint # 1
2592
+ hash = self.hash(self.encode(auth), 'sha256', 'binary') # 2
2593
+ secret = self.base64_to_binary(self.secret) # 3
2594
+ signature = self.hmac(hash, secret, hashlib.sha512, 'base64') # 4-5
2595
+ headers = {
2596
+ 'Content-Type': 'application/x-www-form-urlencoded',
2597
+ 'Accept': 'application/json',
2598
+ 'APIKey': self.apiKey,
2599
+ 'Authent': signature,
2600
+ }
2601
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}