ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__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 (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/bitfinex2.py DELETED
@@ -1,3552 +0,0 @@
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.bitfinex2 import ImplicitAPI
8
- import hashlib
9
- from ccxt.base.types import Balances, Currencies, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
- from typing import List
11
- from ccxt.base.errors import ExchangeError
12
- from ccxt.base.errors import AuthenticationError
13
- from ccxt.base.errors import PermissionDenied
14
- from ccxt.base.errors import ArgumentsRequired
15
- from ccxt.base.errors import BadRequest
16
- from ccxt.base.errors import BadSymbol
17
- from ccxt.base.errors import InsufficientFunds
18
- from ccxt.base.errors import InvalidAddress
19
- from ccxt.base.errors import InvalidOrder
20
- from ccxt.base.errors import OrderNotFound
21
- from ccxt.base.errors import NotSupported
22
- from ccxt.base.errors import RateLimitExceeded
23
- from ccxt.base.errors import ExchangeNotAvailable
24
- from ccxt.base.errors import OnMaintenance
25
- from ccxt.base.errors import InvalidNonce
26
- from ccxt.base.decimal_to_precision import ROUND
27
- from ccxt.base.decimal_to_precision import TRUNCATE
28
- from ccxt.base.decimal_to_precision import DECIMAL_PLACES
29
- from ccxt.base.decimal_to_precision import SIGNIFICANT_DIGITS
30
- from ccxt.base.precise import Precise
31
-
32
-
33
- class bitfinex2(Exchange, ImplicitAPI):
34
-
35
- def describe(self):
36
- return self.deep_extend(super(bitfinex2, self).describe(), {
37
- 'id': 'bitfinex2',
38
- 'name': 'Bitfinex',
39
- 'countries': ['VG'],
40
- 'version': 'v2',
41
- 'certified': False,
42
- 'pro': True,
43
- # new metainfo interface
44
- 'has': {
45
- 'CORS': None,
46
- 'spot': True,
47
- 'margin': True,
48
- 'swap': True,
49
- 'future': False,
50
- 'option': False,
51
- 'addMargin': False,
52
- 'borrowCrossMargin': False,
53
- 'borrowIsolatedMargin': False,
54
- 'cancelAllOrders': True,
55
- 'cancelOrder': True,
56
- 'cancelOrders': True,
57
- 'createDepositAddress': True,
58
- 'createLimitOrder': True,
59
- 'createMarketOrder': True,
60
- 'createOrder': True,
61
- 'createPostOnlyOrder': True,
62
- 'createReduceOnlyOrder': True,
63
- 'createStopLimitOrder': True,
64
- 'createStopMarketOrder': True,
65
- 'createStopOrder': True,
66
- 'createTrailingAmountOrder': True,
67
- 'createTrailingPercentOrder': False,
68
- 'createTriggerOrder': True,
69
- 'editOrder': True,
70
- 'fetchBalance': True,
71
- 'fetchBorrowInterest': False,
72
- 'fetchBorrowRate': False,
73
- 'fetchBorrowRateHistories': False,
74
- 'fetchBorrowRateHistory': False,
75
- 'fetchBorrowRates': False,
76
- 'fetchBorrowRatesPerSymbol': False,
77
- 'fetchClosedOrder': True,
78
- 'fetchClosedOrders': True,
79
- 'fetchCrossBorrowRate': False,
80
- 'fetchCrossBorrowRates': False,
81
- 'fetchCurrencies': True,
82
- 'fetchDepositAddress': True,
83
- 'fetchDepositsWithdrawals': True,
84
- 'fetchFundingHistory': False,
85
- 'fetchFundingRate': True,
86
- 'fetchFundingRateHistory': True,
87
- 'fetchFundingRates': True,
88
- 'fetchIndexOHLCV': False,
89
- 'fetchIsolatedBorrowRate': False,
90
- 'fetchIsolatedBorrowRates': False,
91
- 'fetchLedger': True,
92
- 'fetchLeverage': False,
93
- 'fetchLeverageTiers': False,
94
- 'fetchLiquidations': True,
95
- 'fetchMarginMode': False,
96
- 'fetchMarketLeverageTiers': False,
97
- 'fetchMarkOHLCV': False,
98
- 'fetchMyTrades': True,
99
- 'fetchOHLCV': True,
100
- 'fetchOpenInterest': True,
101
- 'fetchOpenInterestHistory': True,
102
- 'fetchOpenOrder': True,
103
- 'fetchOpenOrders': True,
104
- 'fetchOrder': True,
105
- 'fetchOrderBook': True,
106
- 'fetchOrderBooks': False,
107
- 'fetchOrderTrades': True,
108
- 'fetchPosition': False,
109
- 'fetchPositionMode': False,
110
- 'fetchPositions': True,
111
- 'fetchPremiumIndexOHLCV': False,
112
- 'fetchStatus': True,
113
- 'fetchTickers': True,
114
- 'fetchTime': False,
115
- 'fetchTradingFee': False,
116
- 'fetchTradingFees': True,
117
- 'fetchTransactionFees': None,
118
- 'fetchTransactions': 'emulated',
119
- 'reduceMargin': False,
120
- 'repayCrossMargin': False,
121
- 'repayIsolatedMargin': False,
122
- 'setLeverage': False,
123
- 'setMargin': True,
124
- 'setMarginMode': False,
125
- 'setPositionMode': False,
126
- 'signIn': False,
127
- 'transfer': True,
128
- 'withdraw': True,
129
- },
130
- 'timeframes': {
131
- '1m': '1m',
132
- '5m': '5m',
133
- '15m': '15m',
134
- '30m': '30m',
135
- '1h': '1h',
136
- '3h': '3h',
137
- '4h': '4h',
138
- '6h': '6h',
139
- '12h': '12h',
140
- '1d': '1D',
141
- '1w': '7D',
142
- '2w': '14D',
143
- '1M': '1M',
144
- },
145
- # cheapest endpoint is 240 requests per minute => ~ 4 requests per second =>( 1000ms / 4 ) = 250ms between requests on average
146
- 'rateLimit': 250,
147
- 'urls': {
148
- 'logo': 'https://user-images.githubusercontent.com/1294454/27766244-e328a50c-5ed2-11e7-947b-041416579bb3.jpg',
149
- 'api': {
150
- 'v1': 'https://api.bitfinex.com',
151
- 'public': 'https://api-pub.bitfinex.com',
152
- 'private': 'https://api.bitfinex.com',
153
- },
154
- 'www': 'https://www.bitfinex.com',
155
- 'doc': [
156
- 'https://docs.bitfinex.com/v2/docs/',
157
- 'https://github.com/bitfinexcom/bitfinex-api-node',
158
- ],
159
- 'fees': 'https://www.bitfinex.com/fees',
160
- },
161
- 'api': {
162
- 'public': {
163
- 'get': {
164
- 'conf/{config}': 2.7, # 90 requests a minute, 90/60 = 1.5, 1000 / (250 * 2.66) = 1.503, use 2.7 instead of 2.66 to ensure rateLimitExceeded is not triggered
165
- 'conf/pub:{action}:{object}': 2.7,
166
- 'conf/pub:{action}:{object}:{detail}': 2.7,
167
- 'conf/pub:map:{object}': 2.7,
168
- 'conf/pub:map:{object}:{detail}': 2.7,
169
- 'conf/pub:map:currency:{detail}': 2.7,
170
- 'conf/pub:map:currency:sym': 2.7, # maps symbols to their API symbols, BAB > BCH
171
- 'conf/pub:map:currency:label': 2.7, # verbose friendly names, BNT > Bancor
172
- 'conf/pub:map:currency:unit': 2.7, # maps symbols to unit of measure where applicable
173
- 'conf/pub:map:currency:undl': 2.7, # maps derivatives symbols to their underlying currency
174
- 'conf/pub:map:currency:pool': 2.7, # maps symbols to underlying network/protocol they operate on
175
- 'conf/pub:map:currency:explorer': 2.7, # maps symbols to their recognised block explorer URLs
176
- 'conf/pub:map:currency:tx:fee': 2.7, # maps currencies to their withdrawal fees https://github.com/ccxt/ccxt/issues/7745
177
- 'conf/pub:map:tx:method': 2.7,
178
- 'conf/pub:list:{object}': 2.7,
179
- 'conf/pub:list:{object}:{detail}': 2.7,
180
- 'conf/pub:list:currency': 2.7,
181
- 'conf/pub:list:pair:exchange': 2.7,
182
- 'conf/pub:list:pair:margin': 2.7,
183
- 'conf/pub:list:pair:futures': 2.7,
184
- 'conf/pub:list:competitions': 2.7,
185
- 'conf/pub:info:{object}': 2.7,
186
- 'conf/pub:info:{object}:{detail}': 2.7,
187
- 'conf/pub:info:pair': 2.7,
188
- 'conf/pub:info:pair:futures': 2.7,
189
- 'conf/pub:info:tx:status': 2.7, # [deposit, withdrawal] statuses 1 = active, 0 = maintenance
190
- 'conf/pub:fees': 2.7,
191
- 'platform/status': 8, # 30 requests per minute = 0.5 requests per second =>( 1000ms / rateLimit ) / 0.5 = 8
192
- 'tickers': 2.7, # 90 requests a minute = 1.5 requests per second =>( 1000 / rateLimit ) / 1.5 = 2.666666666
193
- 'ticker/{symbol}': 2.7,
194
- 'tickers/hist': 2.7,
195
- 'trades/{symbol}/hist': 2.7,
196
- 'book/{symbol}/{precision}': 1, # 240 requests a minute
197
- 'book/{symbol}/P0': 1,
198
- 'book/{symbol}/P1': 1,
199
- 'book/{symbol}/P2': 1,
200
- 'book/{symbol}/P3': 1,
201
- 'book/{symbol}/R0': 1,
202
- 'stats1/{key}:{size}:{symbol}:{side}/{section}': 2.7,
203
- 'stats1/{key}:{size}:{symbol}:{side}/last': 2.7,
204
- 'stats1/{key}:{size}:{symbol}:{side}/hist': 2.7,
205
- 'stats1/{key}:{size}:{symbol}/{section}': 2.7,
206
- 'stats1/{key}:{size}:{symbol}/last': 2.7,
207
- 'stats1/{key}:{size}:{symbol}/hist': 2.7,
208
- 'stats1/{key}:{size}:{symbol}:long/last': 2.7,
209
- 'stats1/{key}:{size}:{symbol}:long/hist': 2.7,
210
- 'stats1/{key}:{size}:{symbol}:short/last': 2.7,
211
- 'stats1/{key}:{size}:{symbol}:short/hist': 2.7,
212
- 'candles/trade:{timeframe}:{symbol}:{period}/{section}': 2.7,
213
- 'candles/trade:{timeframe}:{symbol}/{section}': 2.7,
214
- 'candles/trade:{timeframe}:{symbol}/last': 2.7,
215
- 'candles/trade:{timeframe}:{symbol}/hist': 2.7,
216
- 'status/{type}': 2.7,
217
- 'status/deriv': 2.7,
218
- 'status/deriv/{symbol}/hist': 2.7,
219
- 'liquidations/hist': 80, # 3 requests a minute = 0.05 requests a second =>( 1000ms / rateLimit ) / 0.05 = 80
220
- 'rankings/{key}:{timeframe}:{symbol}/{section}': 2.7,
221
- 'rankings/{key}:{timeframe}:{symbol}/hist': 2.7,
222
- 'pulse/hist': 2.7,
223
- 'pulse/profile/{nickname}': 2.7,
224
- 'funding/stats/{symbol}/hist': 10, # ratelimit not in docs
225
- },
226
- 'post': {
227
- 'calc/trade/avg': 2.7,
228
- 'calc/fx': 2.7,
229
- },
230
- },
231
- 'private': {
232
- 'post': {
233
- # 'auth/r/orders/{symbol}/new', # outdated
234
- # 'auth/r/stats/perf:{timeframe}/hist', # outdated
235
- 'auth/r/wallets': 2.7,
236
- 'auth/r/wallets/hist': 2.7,
237
- 'auth/r/orders': 2.7,
238
- 'auth/r/orders/{symbol}': 2.7,
239
- 'auth/w/order/submit': 2.7,
240
- 'auth/w/order/update': 2.7,
241
- 'auth/w/order/cancel': 2.7,
242
- 'auth/w/order/multi': 2.7,
243
- 'auth/w/order/cancel/multi': 2.7,
244
- 'auth/r/orders/{symbol}/hist': 2.7,
245
- 'auth/r/orders/hist': 2.7,
246
- 'auth/r/order/{symbol}:{id}/trades': 2.7,
247
- 'auth/r/trades/{symbol}/hist': 2.7,
248
- 'auth/r/trades/hist': 2.7,
249
- 'auth/r/ledgers/{currency}/hist': 2.7,
250
- 'auth/r/ledgers/hist': 2.7,
251
- 'auth/r/info/margin/{key}': 2.7,
252
- 'auth/r/info/margin/base': 2.7,
253
- 'auth/r/info/margin/sym_all': 2.7,
254
- 'auth/r/positions': 2.7,
255
- 'auth/w/position/claim': 2.7,
256
- 'auth/w/position/increase:': 2.7,
257
- 'auth/r/position/increase/info': 2.7,
258
- 'auth/r/positions/hist': 2.7,
259
- 'auth/r/positions/audit': 2.7,
260
- 'auth/r/positions/snap': 2.7,
261
- 'auth/w/deriv/collateral/set': 2.7,
262
- 'auth/w/deriv/collateral/limits': 2.7,
263
- 'auth/r/funding/offers': 2.7,
264
- 'auth/r/funding/offers/{symbol}': 2.7,
265
- 'auth/w/funding/offer/submit': 2.7,
266
- 'auth/w/funding/offer/cancel': 2.7,
267
- 'auth/w/funding/offer/cancel/all': 2.7,
268
- 'auth/w/funding/close': 2.7,
269
- 'auth/w/funding/auto': 2.7,
270
- 'auth/w/funding/keep': 2.7,
271
- 'auth/r/funding/offers/{symbol}/hist': 2.7,
272
- 'auth/r/funding/offers/hist': 2.7,
273
- 'auth/r/funding/loans': 2.7,
274
- 'auth/r/funding/loans/hist': 2.7,
275
- 'auth/r/funding/loans/{symbol}': 2.7,
276
- 'auth/r/funding/loans/{symbol}/hist': 2.7,
277
- 'auth/r/funding/credits': 2.7,
278
- 'auth/r/funding/credits/hist': 2.7,
279
- 'auth/r/funding/credits/{symbol}': 2.7,
280
- 'auth/r/funding/credits/{symbol}/hist': 2.7,
281
- 'auth/r/funding/trades/{symbol}/hist': 2.7,
282
- 'auth/r/funding/trades/hist': 2.7,
283
- 'auth/r/info/funding/{key}': 2.7,
284
- 'auth/r/info/user': 2.7,
285
- 'auth/r/summary': 2.7,
286
- 'auth/r/logins/hist': 2.7,
287
- 'auth/r/permissions': 2.7,
288
- 'auth/w/token': 2.7,
289
- 'auth/r/audit/hist': 2.7,
290
- 'auth/w/transfer': 2.7, # ratelimit not in docs...
291
- 'auth/w/deposit/address': 24, # 10 requests a minute = 0.166 requests per second =>( 1000ms / rateLimit ) / 0.166 = 24
292
- 'auth/w/deposit/invoice': 24, # ratelimit not in docs
293
- 'auth/w/withdraw': 24, # ratelimit not in docs
294
- 'auth/r/movements/{currency}/hist': 2.7,
295
- 'auth/r/movements/hist': 2.7,
296
- 'auth/r/alerts': 5.34, # 45 requests a minute = 0.75 requests per second =>( 1000ms / rateLimit ) / 0.749 => 5.34
297
- 'auth/w/alert/set': 2.7,
298
- 'auth/w/alert/price:{symbol}:{price}/del': 2.7,
299
- 'auth/w/alert/{type}:{symbol}:{price}/del': 2.7,
300
- 'auth/calc/order/avail': 2.7,
301
- 'auth/w/settings/set': 2.7,
302
- 'auth/r/settings': 2.7,
303
- 'auth/w/settings/del': 2.7,
304
- 'auth/r/pulse/hist': 2.7,
305
- 'auth/w/pulse/add': 16, # 15 requests a minute = 0.25 requests per second =>( 1000ms / rateLimit ) / 0.25 => 16
306
- 'auth/w/pulse/del': 2.7,
307
- },
308
- },
309
- },
310
- 'fees': {
311
- 'trading': {
312
- 'feeSide': 'get',
313
- 'percentage': True,
314
- 'tierBased': True,
315
- 'maker': self.parse_number('0.001'),
316
- 'taker': self.parse_number('0.002'),
317
- 'tiers': {
318
- 'taker': [
319
- [self.parse_number('0'), self.parse_number('0.002')],
320
- [self.parse_number('500000'), self.parse_number('0.002')],
321
- [self.parse_number('1000000'), self.parse_number('0.002')],
322
- [self.parse_number('2500000'), self.parse_number('0.002')],
323
- [self.parse_number('5000000'), self.parse_number('0.002')],
324
- [self.parse_number('7500000'), self.parse_number('0.002')],
325
- [self.parse_number('10000000'), self.parse_number('0.0018')],
326
- [self.parse_number('15000000'), self.parse_number('0.0016')],
327
- [self.parse_number('20000000'), self.parse_number('0.0014')],
328
- [self.parse_number('25000000'), self.parse_number('0.0012')],
329
- [self.parse_number('30000000'), self.parse_number('0.001')],
330
- ],
331
- 'maker': [
332
- [self.parse_number('0'), self.parse_number('0.001')],
333
- [self.parse_number('500000'), self.parse_number('0.0008')],
334
- [self.parse_number('1000000'), self.parse_number('0.0006')],
335
- [self.parse_number('2500000'), self.parse_number('0.0004')],
336
- [self.parse_number('5000000'), self.parse_number('0.0002')],
337
- [self.parse_number('7500000'), self.parse_number('0')],
338
- [self.parse_number('10000000'), self.parse_number('0')],
339
- [self.parse_number('15000000'), self.parse_number('0')],
340
- [self.parse_number('20000000'), self.parse_number('0')],
341
- [self.parse_number('25000000'), self.parse_number('0')],
342
- [self.parse_number('30000000'), self.parse_number('0')],
343
- ],
344
- },
345
- },
346
- 'funding': {
347
- 'withdraw': {},
348
- },
349
- },
350
- 'precisionMode': SIGNIFICANT_DIGITS,
351
- 'options': {
352
- 'precision': 'R0', # P0, P1, P2, P3, P4, R0
353
- # convert 'EXCHANGE MARKET' to lowercase 'market'
354
- # convert 'EXCHANGE LIMIT' to lowercase 'limit'
355
- # everything else remains uppercase
356
- 'exchangeTypes': {
357
- # 'MARKET': None,
358
- 'EXCHANGE MARKET': 'market',
359
- # 'LIMIT': None,
360
- 'EXCHANGE LIMIT': 'limit',
361
- # 'STOP': None,
362
- 'EXCHANGE STOP': 'market',
363
- # 'TRAILING STOP': None,
364
- # 'EXCHANGE TRAILING STOP': None,
365
- # 'FOK': None,
366
- 'EXCHANGE FOK': 'limit',
367
- # 'STOP LIMIT': None,
368
- 'EXCHANGE STOP LIMIT': 'limit',
369
- # 'IOC': None,
370
- 'EXCHANGE IOC': 'limit',
371
- },
372
- # convert 'market' to 'EXCHANGE MARKET'
373
- # convert 'limit' 'EXCHANGE LIMIT'
374
- # everything else remains
375
- 'orderTypes': {
376
- 'market': 'EXCHANGE MARKET',
377
- 'limit': 'EXCHANGE LIMIT',
378
- },
379
- 'fiat': {
380
- 'USD': 'USD',
381
- 'EUR': 'EUR',
382
- 'JPY': 'JPY',
383
- 'GBP': 'GBP',
384
- 'CHN': 'CHN',
385
- },
386
- # actually the correct names unlike the v1
387
- # we don't want to self.extend self with accountsByType in v1
388
- 'v2AccountsByType': {
389
- 'spot': 'exchange',
390
- 'exchange': 'exchange',
391
- 'funding': 'funding',
392
- 'margin': 'margin',
393
- 'derivatives': 'margin',
394
- 'future': 'margin',
395
- 'swap': 'margin',
396
- },
397
- 'withdraw': {
398
- 'includeFee': False,
399
- },
400
- },
401
- 'exceptions': {
402
- 'exact': {
403
- '11010': RateLimitExceeded,
404
- '10001': PermissionDenied, # api_key: permission invalid(#10001)
405
- '10020': BadRequest,
406
- '10100': AuthenticationError,
407
- '10114': InvalidNonce,
408
- '20060': OnMaintenance,
409
- # {"code":503,"error":"temporarily_unavailable","error_description":"Sorry, the service is temporarily unavailable. See https://www.bitfinex.com/ for more info."}
410
- 'temporarily_unavailable': ExchangeNotAvailable,
411
- },
412
- 'broad': {
413
- 'address': InvalidAddress,
414
- 'available balance is only': InsufficientFunds,
415
- 'not enough exchange balance': InsufficientFunds,
416
- 'Order not found': OrderNotFound,
417
- 'symbol: invalid': BadSymbol,
418
- 'Invalid order': InvalidOrder,
419
- },
420
- },
421
- 'commonCurrencies': {
422
- 'UST': 'USDT',
423
- 'EUTF0': 'EURT',
424
- 'USTF0': 'USDT',
425
- 'ALG': 'ALGO', # https://github.com/ccxt/ccxt/issues/6034
426
- 'AMP': 'AMPL',
427
- 'ATO': 'ATOM', # https://github.com/ccxt/ccxt/issues/5118
428
- 'BCHABC': 'XEC',
429
- 'BCHN': 'BCH',
430
- 'DAT': 'DATA',
431
- 'DOG': 'MDOGE',
432
- 'DSH': 'DASH',
433
- 'EDO': 'PNT',
434
- 'EUS': 'EURS',
435
- 'EUT': 'EURT',
436
- 'HTX': 'HT',
437
- 'IDX': 'ID',
438
- 'IOT': 'IOTA',
439
- 'IQX': 'IQ',
440
- 'LUNA': 'LUNC',
441
- 'LUNA2': 'LUNA',
442
- 'MNA': 'MANA',
443
- 'ORS': 'ORS Group', # conflict with Origin Sport #3230
444
- 'PAS': 'PASS',
445
- 'QSH': 'QASH',
446
- 'QTM': 'QTUM',
447
- 'RBT': 'RBTC',
448
- 'SNG': 'SNGLS',
449
- 'STJ': 'STORJ',
450
- 'TERRAUST': 'USTC',
451
- 'TSD': 'TUSD',
452
- 'YGG': 'YEED', # conflict with Yield Guild Games
453
- 'YYW': 'YOYOW',
454
- 'UDC': 'USDC',
455
- 'VSY': 'VSYS',
456
- 'WAX': 'WAXP',
457
- 'XCH': 'XCHF',
458
- 'ZBT': 'ZB',
459
- },
460
- })
461
-
462
- def is_fiat(self, code):
463
- return(code in self.options['fiat'])
464
-
465
- def get_currency_id(self, code):
466
- return 'f' + code
467
-
468
- def get_currency_name(self, code):
469
- # temporary fix for transpiler recognition, even though self is in parent class
470
- if code in self.options['currencyNames']:
471
- return self.options['currencyNames'][code]
472
- raise NotSupported(self.id + ' ' + code + ' not supported for withdrawal')
473
-
474
- def amount_to_precision(self, symbol, amount):
475
- # https://docs.bitfinex.com/docs/introduction#amount-precision
476
- # The amount field allows up to 8 decimals.
477
- # Anything exceeding self will be rounded to the 8th decimal.
478
- symbol = self.safe_symbol(symbol)
479
- return self.decimal_to_precision(amount, TRUNCATE, self.markets[symbol]['precision']['amount'], DECIMAL_PLACES)
480
-
481
- def price_to_precision(self, symbol, price):
482
- symbol = self.safe_symbol(symbol)
483
- price = self.decimal_to_precision(price, ROUND, self.markets[symbol]['precision']['price'], self.precisionMode)
484
- # https://docs.bitfinex.com/docs/introduction#price-precision
485
- # The precision level of all trading prices is based on significant figures.
486
- # All pairs on Bitfinex use up to 5 significant digits and up to 8 decimals(e.g. 1.2345, 123.45, 1234.5, 0.00012345).
487
- # Prices submit with a precision larger than 5 will be cut by the API.
488
- return self.decimal_to_precision(price, TRUNCATE, 8, DECIMAL_PLACES)
489
-
490
- def fetch_status(self, params={}):
491
- """
492
- the latest known information on the availability of the exchange API
493
- :see: https://docs.bitfinex.com/reference/rest-public-platform-status
494
- :param dict [params]: extra parameters specific to the exchange API endpoint
495
- :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
496
- """
497
- #
498
- # [1] # operative
499
- # [0] # maintenance
500
- #
501
- response = self.publicGetPlatformStatus(params)
502
- statusRaw = self.safe_string(response, 0)
503
- return {
504
- 'status': self.safe_string({'0': 'maintenance', '1': 'ok'}, statusRaw, statusRaw),
505
- 'updated': None,
506
- 'eta': None,
507
- 'url': None,
508
- 'info': response,
509
- }
510
-
511
- def fetch_markets(self, params={}) -> List[Market]:
512
- """
513
- retrieves data on all markets for bitfinex2
514
- :see: https://docs.bitfinex.com/reference/rest-public-conf
515
- :param dict [params]: extra parameters specific to the exchange API endpoint
516
- :returns dict[]: an array of objects representing market data
517
- """
518
- spotMarketsInfo = self.publicGetConfPubInfoPair(params)
519
- futuresMarketsInfo = self.publicGetConfPubInfoPairFutures(params)
520
- spotMarketsInfo = self.safe_value(spotMarketsInfo, 0, [])
521
- futuresMarketsInfo = self.safe_value(futuresMarketsInfo, 0, [])
522
- markets = self.array_concat(spotMarketsInfo, futuresMarketsInfo)
523
- marginIds = self.publicGetConfPubListPairMargin(params)
524
- marginIds = self.safe_value(marginIds, 0, [])
525
- #
526
- # [
527
- # "1INCH:USD",
528
- # [
529
- # null,
530
- # null,
531
- # null,
532
- # "2.0",
533
- # "100000.0",
534
- # null,
535
- # null,
536
- # null,
537
- # null,
538
- # null,
539
- # null,
540
- # null
541
- # ]
542
- # ]
543
- #
544
- result = []
545
- for i in range(0, len(markets)):
546
- pair = markets[i]
547
- id = self.safe_string_upper(pair, 0)
548
- market = self.safe_value(pair, 1, {})
549
- spot = True
550
- if id.find('F0') >= 0:
551
- spot = False
552
- swap = not spot
553
- baseId = None
554
- quoteId = None
555
- if id.find(':') >= 0:
556
- parts = id.split(':')
557
- baseId = parts[0]
558
- quoteId = parts[1]
559
- else:
560
- baseId = id[0:3]
561
- quoteId = id[3:6]
562
- base = self.safe_currency_code(baseId)
563
- quote = self.safe_currency_code(quoteId)
564
- splitBase = base.split('F0')
565
- splitQuote = quote.split('F0')
566
- base = self.safe_string(splitBase, 0)
567
- quote = self.safe_string(splitQuote, 0)
568
- symbol = base + '/' + quote
569
- baseId = self.get_currency_id(baseId)
570
- quoteId = self.get_currency_id(quoteId)
571
- settle = None
572
- settleId = None
573
- if swap:
574
- settle = quote
575
- settleId = quote
576
- symbol = symbol + ':' + settle
577
- minOrderSizeString = self.safe_string(market, 3)
578
- maxOrderSizeString = self.safe_string(market, 4)
579
- margin = False
580
- if spot and self.in_array(id, marginIds):
581
- margin = True
582
- result.append({
583
- 'id': 't' + id,
584
- 'symbol': symbol,
585
- 'base': base,
586
- 'quote': quote,
587
- 'settle': settle,
588
- 'baseId': baseId,
589
- 'quoteId': quoteId,
590
- 'settleId': settleId,
591
- 'type': 'spot' if spot else 'swap',
592
- 'spot': spot,
593
- 'margin': margin,
594
- 'swap': swap,
595
- 'future': False,
596
- 'option': False,
597
- 'active': True,
598
- 'contract': swap,
599
- 'linear': True if swap else None,
600
- 'inverse': False if swap else None,
601
- 'contractSize': self.parse_number('1') if swap else None,
602
- 'expiry': None,
603
- 'expiryDatetime': None,
604
- 'strike': None,
605
- 'optionType': None,
606
- 'precision': {
607
- 'amount': int('8'), # https://github.com/ccxt/ccxt/issues/7310
608
- 'price': int('5'),
609
- },
610
- 'limits': {
611
- 'leverage': {
612
- 'min': None,
613
- 'max': None,
614
- },
615
- 'amount': {
616
- 'min': self.parse_number(minOrderSizeString),
617
- 'max': self.parse_number(maxOrderSizeString),
618
- },
619
- 'price': {
620
- 'min': self.parse_number('1e-8'),
621
- 'max': None,
622
- },
623
- 'cost': {
624
- 'min': None,
625
- 'max': None,
626
- },
627
- },
628
- 'created': None, # todo: the api needs revision for extra params & endpoints for possibility of returning a timestamp for self
629
- 'info': market,
630
- })
631
- return result
632
-
633
- def fetch_currencies(self, params={}) -> Currencies:
634
- """
635
- fetches all available currencies on an exchange
636
- :see: https://docs.bitfinex.com/reference/rest-public-conf
637
- :param dict [params]: extra parameters specific to the exchange API endpoint
638
- :returns dict: an associative dictionary of currencies
639
- """
640
- labels = [
641
- 'pub:list:currency',
642
- 'pub:map:currency:sym', # maps symbols to their API symbols, BAB > BCH
643
- 'pub:map:currency:label', # verbose friendly names, BNT > Bancor
644
- 'pub:map:currency:unit', # maps symbols to unit of measure where applicable
645
- 'pub:map:currency:undl', # maps derivatives symbols to their underlying currency
646
- 'pub:map:currency:pool', # maps symbols to underlying network/protocol they operate on
647
- 'pub:map:currency:explorer', # maps symbols to their recognised block explorer URLs
648
- 'pub:map:currency:tx:fee', # maps currencies to their withdrawal fees https://github.com/ccxt/ccxt/issues/7745,
649
- 'pub:map:tx:method', # maps withdrawal/deposit methods to their API symbols
650
- ]
651
- config = ','.join(labels)
652
- request: dict = {
653
- 'config': config,
654
- }
655
- response = self.publicGetConfConfig(self.extend(request, params))
656
- #
657
- # [
658
- #
659
- # a list of symbols
660
- # ["AAA","ABS","ADA"],
661
- #
662
- # # sym
663
- # # maps symbols to their API symbols, BAB > BCH
664
- # [
665
- # ["BAB", "BCH"],
666
- # ["CNHT", "CNHt"],
667
- # ["DSH", "DASH"],
668
- # ["IOT", "IOTA"],
669
- # ["LES", "LEO-EOS"],
670
- # ["LET", "LEO-ERC20"],
671
- # ["STJ", "STORJ"],
672
- # ["TSD", "TUSD"],
673
- # ["UDC", "USDC"],
674
- # ["USK", "USDK"],
675
- # ["UST", "USDt"],
676
- # ["USTF0", "USDt0"],
677
- # ["XCH", "XCHF"],
678
- # ["YYW", "YOYOW"],
679
- # # ...
680
- # ],
681
- # # label
682
- # # verbose friendly names, BNT > Bancor
683
- # [
684
- # ["BAB", "Bitcoin Cash"],
685
- # ["BCH", "Bitcoin Cash"],
686
- # ["LEO", "Unus Sed LEO"],
687
- # ["LES", "Unus Sed LEO(EOS)"],
688
- # ["LET", "Unus Sed LEO(ERC20)"],
689
- # # ...
690
- # ],
691
- # # unit
692
- # # maps symbols to unit of measure where applicable
693
- # [
694
- # ["IOT", "Mi|MegaIOTA"],
695
- # ],
696
- # # undl
697
- # # maps derivatives symbols to their underlying currency
698
- # [
699
- # ["USTF0", "UST"],
700
- # ["BTCF0", "BTC"],
701
- # ["ETHF0", "ETH"],
702
- # ],
703
- # # pool
704
- # # maps symbols to underlying network/protocol they operate on
705
- # [
706
- # ['SAN', 'ETH'], ['OMG', 'ETH'], ['AVT', 'ETH'], ["EDO", "ETH"],
707
- # ['ESS', 'ETH'], ['ATD', 'EOS'], ['ADD', 'EOS'], ["MTO", "EOS"],
708
- # ['PNK', 'ETH'], ['BAB', 'BCH'], ['WLO', 'XLM'], ["VLD", "ETH"],
709
- # ['BTT', 'TRX'], ['IMP', 'ETH'], ['SCR', 'ETH'], ["GNO", "ETH"],
710
- # # ...
711
- # ],
712
- # # explorer
713
- # # maps symbols to their recognised block explorer URLs
714
- # [
715
- # [
716
- # "AIO",
717
- # [
718
- # "https://mainnet.aion.network",
719
- # "https://mainnet.aion.network/#/account/VAL",
720
- # "https://mainnet.aion.network/#/transaction/VAL"
721
- # ]
722
- # ],
723
- # # ...
724
- # ],
725
- # # fee
726
- # # maps currencies to their withdrawal fees
727
- # [
728
- # ["AAA",[0,0]],
729
- # ["ABS",[0,131.3]],
730
- # ["ADA",[0,0.3]],
731
- # ],
732
- # ]
733
- #
734
- indexed: dict = {
735
- 'sym': self.index_by(self.safe_value(response, 1, []), 0),
736
- 'label': self.index_by(self.safe_value(response, 2, []), 0),
737
- 'unit': self.index_by(self.safe_value(response, 3, []), 0),
738
- 'undl': self.index_by(self.safe_value(response, 4, []), 0),
739
- 'pool': self.index_by(self.safe_value(response, 5, []), 0),
740
- 'explorer': self.index_by(self.safe_value(response, 6, []), 0),
741
- 'fees': self.index_by(self.safe_value(response, 7, []), 0),
742
- }
743
- ids = self.safe_value(response, 0, [])
744
- result: dict = {}
745
- for i in range(0, len(ids)):
746
- id = ids[i]
747
- if id.find('F0') >= 0:
748
- # we get a lot of F0 currencies, skip those
749
- continue
750
- code = self.safe_currency_code(id)
751
- label = self.safe_value(indexed['label'], id, [])
752
- name = self.safe_string(label, 1)
753
- pool = self.safe_value(indexed['pool'], id, [])
754
- rawType = self.safe_string(pool, 1)
755
- type = 'other' if (rawType is None) else 'crypto'
756
- feeValues = self.safe_value(indexed['fees'], id, [])
757
- fees = self.safe_value(feeValues, 1, [])
758
- fee = self.safe_number(fees, 1)
759
- undl = self.safe_value(indexed['undl'], id, [])
760
- precision = '8' # default precision, todo: fix "magic constants"
761
- fid = 'f' + id
762
- result[code] = {
763
- 'id': fid,
764
- 'uppercaseId': id,
765
- 'code': code,
766
- 'info': [id, label, pool, feeValues, undl],
767
- 'type': type,
768
- 'name': name,
769
- 'active': True,
770
- 'deposit': None,
771
- 'withdraw': None,
772
- 'fee': fee,
773
- 'precision': int(precision),
774
- 'limits': {
775
- 'amount': {
776
- 'min': self.parse_number(self.parse_precision(precision)),
777
- 'max': None,
778
- },
779
- 'withdraw': {
780
- 'min': fee,
781
- 'max': None,
782
- },
783
- },
784
- 'networks': {},
785
- }
786
- networks: dict = {}
787
- currencyNetworks = self.safe_value(response, 8, [])
788
- cleanId = id.replace('F0', '')
789
- for j in range(0, len(currencyNetworks)):
790
- pair = currencyNetworks[j]
791
- networkId = self.safe_string(pair, 0)
792
- currencyId = self.safe_string(self.safe_value(pair, 1, []), 0)
793
- if currencyId == cleanId:
794
- network = self.safe_network(networkId)
795
- networks[network] = {
796
- 'info': networkId,
797
- 'id': networkId.lower(),
798
- 'network': networkId,
799
- 'active': None,
800
- 'deposit': None,
801
- 'withdraw': None,
802
- 'fee': None,
803
- 'precision': None,
804
- 'limits': {
805
- 'withdraw': {
806
- 'min': None,
807
- 'max': None,
808
- },
809
- },
810
- }
811
- keysNetworks = list(networks.keys())
812
- networksLength = len(keysNetworks)
813
- if networksLength > 0:
814
- result[code]['networks'] = networks
815
- return result
816
-
817
- def safe_network(self, networkId):
818
- networksById: dict = {
819
- 'BITCOIN': 'BTC',
820
- 'LITECOIN': 'LTC',
821
- 'ETHEREUM': 'ERC20',
822
- 'TETHERUSE': 'ERC20',
823
- 'TETHERUSO': 'OMNI',
824
- 'TETHERUSL': 'LIQUID',
825
- 'TETHERUSX': 'TRC20',
826
- 'TETHERUSS': 'EOS',
827
- 'TETHERUSDTAVAX': 'AVAX',
828
- 'TETHERUSDTSOL': 'SOL',
829
- 'TETHERUSDTALG': 'ALGO',
830
- 'TETHERUSDTBCH': 'BCH',
831
- 'TETHERUSDTKSM': 'KSM',
832
- 'TETHERUSDTDVF': 'DVF',
833
- 'TETHERUSDTOMG': 'OMG',
834
- }
835
- return self.safe_string(networksById, networkId, networkId)
836
-
837
- def fetch_balance(self, params={}) -> Balances:
838
- """
839
- query for balance and get the amount of funds available for trading or funds locked in orders
840
- :see: https://docs.bitfinex.com/reference/rest-auth-wallets
841
- :param dict [params]: extra parameters specific to the exchange API endpoint
842
- :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
843
- """
844
- # self api call does not return the 'used' amount - use the v1 version instead(which also returns zero balances)
845
- # there is a difference between self and the v1 api, namely trading wallet is called margin in v2
846
- self.load_markets()
847
- accountsByType = self.safe_value(self.options, 'v2AccountsByType', {})
848
- requestedType = self.safe_string(params, 'type', 'exchange')
849
- accountType = self.safe_string(accountsByType, requestedType, requestedType)
850
- if accountType is None:
851
- keys = list(accountsByType.keys())
852
- raise ExchangeError(self.id + ' fetchBalance() type parameter must be one of ' + ', '.join(keys))
853
- isDerivative = requestedType == 'derivatives'
854
- query = self.omit(params, 'type')
855
- response = self.privatePostAuthRWallets(query)
856
- result: dict = {'info': response}
857
- for i in range(0, len(response)):
858
- balance = response[i]
859
- account = self.account()
860
- interest = self.safe_string(balance, 3)
861
- if interest != '0':
862
- account['debt'] = interest
863
- type = self.safe_string(balance, 0)
864
- currencyId = self.safe_string_lower(balance, 1, '')
865
- start = len(currencyId) - 2
866
- isDerivativeCode = currencyId[start:] == 'f0'
867
- # self will only filter the derivative codes if the requestedType is 'derivatives'
868
- derivativeCondition = (not isDerivative or isDerivativeCode)
869
- if (accountType == type) and derivativeCondition:
870
- code = self.safe_currency_code(currencyId)
871
- account['total'] = self.safe_string(balance, 2)
872
- account['free'] = self.safe_string(balance, 4)
873
- result[code] = account
874
- return self.safe_balance(result)
875
-
876
- def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
877
- """
878
- transfer currency internally between wallets on the same account
879
- :see: https://docs.bitfinex.com/reference/rest-auth-transfer
880
- :param str code: unified currency code
881
- :param float amount: amount to transfer
882
- :param str fromAccount: account to transfer from
883
- :param str toAccount: account to transfer to
884
- :param dict [params]: extra parameters specific to the exchange API endpoint
885
- :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
886
- """
887
- # transferring between derivatives wallet and regular wallet is not documented in their API
888
- # however we support it in CCXT(from just looking at web inspector)
889
- self.load_markets()
890
- accountsByType = self.safe_value(self.options, 'v2AccountsByType', {})
891
- fromId = self.safe_string(accountsByType, fromAccount)
892
- if fromId is None:
893
- keys = list(accountsByType.keys())
894
- raise ArgumentsRequired(self.id + ' transfer() fromAccount must be one of ' + ', '.join(keys))
895
- toId = self.safe_string(accountsByType, toAccount)
896
- if toId is None:
897
- keys = list(accountsByType.keys())
898
- raise ArgumentsRequired(self.id + ' transfer() toAccount must be one of ' + ', '.join(keys))
899
- currency = self.currency(code)
900
- fromCurrencyId = self.convert_derivatives_id(currency, fromAccount)
901
- toCurrencyId = self.convert_derivatives_id(currency, toAccount)
902
- requestedAmount = self.currency_to_precision(code, amount)
903
- # self request is slightly different from v1 fromAccount -> from
904
- request: dict = {
905
- 'amount': requestedAmount,
906
- 'currency': fromCurrencyId,
907
- 'currency_to': toCurrencyId,
908
- 'from': fromId,
909
- 'to': toId,
910
- }
911
- response = self.privatePostAuthWTransfer(self.extend(request, params))
912
- #
913
- # [
914
- # 1616451183763,
915
- # "acc_tf",
916
- # null,
917
- # null,
918
- # [
919
- # 1616451183763,
920
- # "exchange",
921
- # "margin",
922
- # null,
923
- # "UST",
924
- # "UST",
925
- # null,
926
- # 1
927
- # ],
928
- # null,
929
- # "SUCCESS",
930
- # "1.0 Tether USDt transfered from Exchange to Margin"
931
- # ]
932
- #
933
- error = self.safe_string(response, 0)
934
- if error == 'error':
935
- message = self.safe_string(response, 2, '')
936
- # same message v1
937
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, self.id + ' ' + message)
938
- raise ExchangeError(self.id + ' ' + message)
939
- return self.parse_transfer({'result': response}, currency)
940
-
941
- def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
942
- #
943
- # transfer
944
- #
945
- # [
946
- # 1616451183763,
947
- # "acc_tf",
948
- # null,
949
- # null,
950
- # [
951
- # 1616451183763,
952
- # "exchange",
953
- # "margin",
954
- # null,
955
- # "UST",
956
- # "UST",
957
- # null,
958
- # 1
959
- # ],
960
- # null,
961
- # "SUCCESS",
962
- # "1.0 Tether USDt transfered from Exchange to Margin"
963
- # ]
964
- #
965
- result = self.safe_list(transfer, 'result')
966
- timestamp = self.safe_integer(result, 0)
967
- info = self.safe_value(result, 4)
968
- fromAccount = self.safe_string(info, 1)
969
- toAccount = self.safe_string(info, 2)
970
- currencyId = self.safe_string(info, 5)
971
- status = self.safe_string(result, 6)
972
- return {
973
- 'id': None,
974
- 'timestamp': timestamp,
975
- 'datetime': self.iso8601(timestamp),
976
- 'status': self.parse_transfer_status(status),
977
- 'amount': self.safe_number(info, 7),
978
- 'currency': self.safe_currency_code(currencyId, currency),
979
- 'fromAccount': fromAccount,
980
- 'toAccount': toAccount,
981
- 'info': result,
982
- }
983
-
984
- def parse_transfer_status(self, status: Str) -> Str:
985
- statuses: dict = {
986
- 'SUCCESS': 'ok',
987
- 'ERROR': 'failed',
988
- 'FAILURE': 'failed',
989
- }
990
- return self.safe_string(statuses, status, status)
991
-
992
- def convert_derivatives_id(self, currency, type):
993
- # there is a difference between self and the v1 api, namely trading wallet is called margin in v2
994
- # {
995
- # "id": "fUSTF0",
996
- # "code": "USTF0",
997
- # "info": ['USTF0', [], [], [], ["USTF0", "UST"]],
998
- info = self.safe_value(currency, 'info')
999
- transferId = self.safe_string(info, 0)
1000
- underlying = self.safe_value(info, 4, [])
1001
- currencyId = None
1002
- if type == 'derivatives':
1003
- currencyId = self.safe_string(underlying, 0, transferId)
1004
- start = len(currencyId) - 2
1005
- isDerivativeCode = currencyId[start:] == 'F0'
1006
- if not isDerivativeCode:
1007
- currencyId = currencyId + 'F0'
1008
- elif type != 'margin':
1009
- currencyId = self.safe_string(underlying, 1, transferId)
1010
- else:
1011
- currencyId = transferId
1012
- return currencyId
1013
-
1014
- def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1015
- """
1016
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1017
- :see: https://docs.bitfinex.com/reference/rest-public-book
1018
- :param str symbol: unified symbol of the market to fetch the order book for
1019
- :param int [limit]: the maximum amount of order book entries to return, bitfinex only allows 1, 25, or 100
1020
- :param dict [params]: extra parameters specific to the exchange API endpoint
1021
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1022
- """
1023
- self.load_markets()
1024
- precision = self.safe_value(self.options, 'precision', 'R0')
1025
- market = self.market(symbol)
1026
- request: dict = {
1027
- 'symbol': market['id'],
1028
- 'precision': precision,
1029
- }
1030
- if limit is not None:
1031
- request['len'] = limit
1032
- fullRequest = self.extend(request, params)
1033
- orderbook = self.publicGetBookSymbolPrecision(fullRequest)
1034
- timestamp = self.milliseconds()
1035
- result: dict = {
1036
- 'symbol': market['symbol'],
1037
- 'bids': [],
1038
- 'asks': [],
1039
- 'timestamp': timestamp,
1040
- 'datetime': self.iso8601(timestamp),
1041
- 'nonce': None,
1042
- }
1043
- priceIndex = 1 if (fullRequest['precision'] == 'R0') else 0
1044
- for i in range(0, len(orderbook)):
1045
- order = orderbook[i]
1046
- price = self.safe_number(order, priceIndex)
1047
- signedAmount = self.safe_string(order, 2)
1048
- amount = Precise.string_abs(signedAmount)
1049
- side = 'bids' if Precise.string_gt(signedAmount, '0') else 'asks'
1050
- result[side].append([price, self.parse_number(amount)])
1051
- result['bids'] = self.sort_by(result['bids'], 0, True)
1052
- result['asks'] = self.sort_by(result['asks'], 0)
1053
- return result
1054
-
1055
- def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1056
- #
1057
- # on trading pairs(ex. tBTCUSD)
1058
- #
1059
- # {
1060
- # 'result': [
1061
- # SYMBOL,
1062
- # BID,
1063
- # BID_SIZE,
1064
- # ASK,
1065
- # ASK_SIZE,
1066
- # DAILY_CHANGE,
1067
- # DAILY_CHANGE_RELATIVE,
1068
- # LAST_PRICE,
1069
- # VOLUME,
1070
- # HIGH,
1071
- # LOW
1072
- # ]
1073
- # }
1074
- #
1075
- #
1076
- # on funding currencies(ex. fUSD)
1077
- #
1078
- # {
1079
- # 'result': [
1080
- # SYMBOL,
1081
- # FRR,
1082
- # BID,
1083
- # BID_PERIOD,
1084
- # BID_SIZE,
1085
- # ASK,
1086
- # ASK_PERIOD,
1087
- # ASK_SIZE,
1088
- # DAILY_CHANGE,
1089
- # DAILY_CHANGE_RELATIVE,
1090
- # LAST_PRICE,
1091
- # VOLUME,
1092
- # HIGH,
1093
- # LOW,
1094
- # _PLACEHOLDER,
1095
- # _PLACEHOLDER,
1096
- # FRR_AMOUNT_AVAILABLE
1097
- # ]
1098
- # }
1099
- #
1100
- result = self.safe_list(ticker, 'result')
1101
- symbol = self.safe_symbol(None, market)
1102
- length = len(result)
1103
- last = self.safe_string(result, length - 4)
1104
- percentage = self.safe_string(result, length - 5)
1105
- return self.safe_ticker({
1106
- 'symbol': symbol,
1107
- 'timestamp': None,
1108
- 'datetime': None,
1109
- 'high': self.safe_string(result, length - 2),
1110
- 'low': self.safe_string(result, length - 1),
1111
- 'bid': self.safe_string(result, length - 10),
1112
- 'bidVolume': self.safe_string(result, length - 9),
1113
- 'ask': self.safe_string(result, length - 8),
1114
- 'askVolume': self.safe_string(result, length - 7),
1115
- 'vwap': None,
1116
- 'open': None,
1117
- 'close': last,
1118
- 'last': last,
1119
- 'previousClose': None,
1120
- 'change': self.safe_string(result, length - 6),
1121
- 'percentage': Precise.string_mul(percentage, '100'),
1122
- 'average': None,
1123
- 'baseVolume': self.safe_string(result, length - 3),
1124
- 'quoteVolume': None,
1125
- 'info': result,
1126
- }, market)
1127
-
1128
- def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1129
- """
1130
- fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1131
- :see: https://docs.bitfinex.com/reference/rest-public-tickers
1132
- :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1133
- :param dict [params]: extra parameters specific to the exchange API endpoint
1134
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1135
- """
1136
- self.load_markets()
1137
- symbols = self.market_symbols(symbols)
1138
- request: dict = {}
1139
- if symbols is not None:
1140
- ids = self.market_ids(symbols)
1141
- request['symbols'] = ','.join(ids)
1142
- else:
1143
- request['symbols'] = 'ALL'
1144
- tickers = self.publicGetTickers(self.extend(request, params))
1145
- #
1146
- # [
1147
- # # on trading pairs(ex. tBTCUSD)
1148
- # [
1149
- # SYMBOL,
1150
- # BID,
1151
- # BID_SIZE,
1152
- # ASK,
1153
- # ASK_SIZE,
1154
- # DAILY_CHANGE,
1155
- # DAILY_CHANGE_RELATIVE,
1156
- # LAST_PRICE,
1157
- # VOLUME,
1158
- # HIGH,
1159
- # LOW
1160
- # ],
1161
- # # on funding currencies(ex. fUSD)
1162
- # [
1163
- # SYMBOL,
1164
- # FRR,
1165
- # BID,
1166
- # BID_PERIOD,
1167
- # BID_SIZE,
1168
- # ASK,
1169
- # ASK_PERIOD,
1170
- # ASK_SIZE,
1171
- # DAILY_CHANGE,
1172
- # DAILY_CHANGE_RELATIVE,
1173
- # LAST_PRICE,
1174
- # VOLUME,
1175
- # HIGH,
1176
- # LOW,
1177
- # _PLACEHOLDER,
1178
- # _PLACEHOLDER,
1179
- # FRR_AMOUNT_AVAILABLE
1180
- # ],
1181
- # ...
1182
- # ]
1183
- #
1184
- result: dict = {}
1185
- for i in range(0, len(tickers)):
1186
- ticker = tickers[i]
1187
- marketId = self.safe_string(ticker, 0)
1188
- market = self.safe_market(marketId)
1189
- symbol = market['symbol']
1190
- result[symbol] = self.parse_ticker({'result': ticker}, market)
1191
- return self.filter_by_array_tickers(result, 'symbol', symbols)
1192
-
1193
- def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1194
- """
1195
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1196
- :see: https://docs.bitfinex.com/reference/rest-public-ticker
1197
- :param str symbol: unified symbol of the market to fetch the ticker for
1198
- :param dict [params]: extra parameters specific to the exchange API endpoint
1199
- :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1200
- """
1201
- self.load_markets()
1202
- market = self.market(symbol)
1203
- request: dict = {
1204
- 'symbol': market['id'],
1205
- }
1206
- ticker = self.publicGetTickerSymbol(self.extend(request, params))
1207
- result: dict = {'result': ticker}
1208
- return self.parse_ticker(result, market)
1209
-
1210
- def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1211
- #
1212
- # fetchTrades(public)
1213
- #
1214
- # [
1215
- # ID,
1216
- # MTS, # timestamp
1217
- # AMOUNT,
1218
- # PRICE
1219
- # ]
1220
- #
1221
- # fetchMyTrades(private)
1222
- #
1223
- # [
1224
- # ID,
1225
- # PAIR,
1226
- # MTS_CREATE,
1227
- # ORDER_ID,
1228
- # EXEC_AMOUNT,
1229
- # EXEC_PRICE,
1230
- # ORDER_TYPE,
1231
- # ORDER_PRICE,
1232
- # MAKER,
1233
- # FEE,
1234
- # FEE_CURRENCY,
1235
- # ...
1236
- # ]
1237
- #
1238
- tradeList = self.safe_list(trade, 'result', [])
1239
- tradeLength = len(tradeList)
1240
- isPrivate = (tradeLength > 5)
1241
- id = self.safe_string(tradeList, 0)
1242
- amountIndex = 4 if isPrivate else 2
1243
- side = None
1244
- amountString = self.safe_string(tradeList, amountIndex)
1245
- priceIndex = 5 if isPrivate else 3
1246
- priceString = self.safe_string(tradeList, priceIndex)
1247
- if amountString[0] == '-':
1248
- side = 'sell'
1249
- amountString = Precise.string_abs(amountString)
1250
- else:
1251
- side = 'buy'
1252
- orderId = None
1253
- takerOrMaker = None
1254
- type = None
1255
- fee = None
1256
- symbol = self.safe_symbol(None, market)
1257
- timestampIndex = 2 if isPrivate else 1
1258
- timestamp = self.safe_integer(tradeList, timestampIndex)
1259
- if isPrivate:
1260
- marketId = tradeList[1]
1261
- symbol = self.safe_symbol(marketId)
1262
- orderId = self.safe_string(tradeList, 3)
1263
- maker = self.safe_integer(tradeList, 8)
1264
- takerOrMaker = 'maker' if (maker == 1) else 'taker'
1265
- feeCostString = self.safe_string(tradeList, 9)
1266
- feeCostString = Precise.string_neg(feeCostString)
1267
- feeCurrencyId = self.safe_string(tradeList, 10)
1268
- feeCurrency = self.safe_currency_code(feeCurrencyId)
1269
- fee = {
1270
- 'cost': feeCostString,
1271
- 'currency': feeCurrency,
1272
- }
1273
- orderType = tradeList[6]
1274
- type = self.safe_string(self.options['exchangeTypes'], orderType)
1275
- return self.safe_trade({
1276
- 'id': id,
1277
- 'timestamp': timestamp,
1278
- 'datetime': self.iso8601(timestamp),
1279
- 'symbol': symbol,
1280
- 'order': orderId,
1281
- 'side': side,
1282
- 'type': type,
1283
- 'takerOrMaker': takerOrMaker,
1284
- 'price': priceString,
1285
- 'amount': amountString,
1286
- 'cost': None,
1287
- 'fee': fee,
1288
- 'info': tradeList,
1289
- }, market)
1290
-
1291
- def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1292
- """
1293
- get the list of most recent trades for a particular symbol
1294
- :see: https://docs.bitfinex.com/reference/rest-public-trades
1295
- :param str symbol: unified symbol of the market to fetch trades for
1296
- :param int [since]: timestamp in ms of the earliest trade to fetch
1297
- :param int [limit]: the maximum amount of trades to fetch, default 120, max 10000
1298
- :param dict [params]: extra parameters specific to the exchange API endpoint
1299
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1300
- :param int [params.until]: the latest time in ms to fetch entries for
1301
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1302
- """
1303
- self.load_markets()
1304
- paginate = False
1305
- paginate, params = self.handle_option_and_params(params, 'fetchTrades', 'paginate')
1306
- if paginate:
1307
- return self.fetch_paginated_call_dynamic('fetchTrades', symbol, since, limit, params, 10000)
1308
- market = self.market(symbol)
1309
- sort = '-1'
1310
- request: dict = {
1311
- 'symbol': market['id'],
1312
- }
1313
- if since is not None:
1314
- request['start'] = since
1315
- sort = '1'
1316
- if limit is not None:
1317
- request['limit'] = min(limit, 10000) # default 120, max 10000
1318
- request['sort'] = sort
1319
- request, params = self.handle_until_option('end', request, params)
1320
- response = self.publicGetTradesSymbolHist(self.extend(request, params))
1321
- #
1322
- # [
1323
- # [
1324
- # ID,
1325
- # MTS, # timestamp
1326
- # AMOUNT,
1327
- # PRICE
1328
- # ]
1329
- # ]
1330
- #
1331
- trades = self.sort_by(response, 1)
1332
- tradesList = []
1333
- for i in range(0, len(trades)):
1334
- tradesList.append({'result': trades[i]}) # convert to array of dicts to match parseOrder signature
1335
- return self.parse_trades(tradesList, market, None, limit)
1336
-
1337
- def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = 100, params={}) -> List[list]:
1338
- """
1339
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1340
- :see: https://docs.bitfinex.com/reference/rest-public-candles
1341
- :param str symbol: unified symbol of the market to fetch OHLCV data for
1342
- :param str timeframe: the length of time each candle represents
1343
- :param int [since]: timestamp in ms of the earliest candle to fetch
1344
- :param int [limit]: the maximum amount of candles to fetch, default 100 max 10000
1345
- :param dict [params]: extra parameters specific to the exchange API endpoint
1346
- :returns int[][]: A list of candles ordered, open, high, low, close, volume
1347
- :param int [params.until]: timestamp in ms of the latest candle to fetch
1348
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1349
- """
1350
- self.load_markets()
1351
- paginate = False
1352
- paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
1353
- if paginate:
1354
- return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 10000)
1355
- market = self.market(symbol)
1356
- if limit is None:
1357
- limit = 10000
1358
- else:
1359
- limit = min(limit, 10000)
1360
- request: dict = {
1361
- 'symbol': market['id'],
1362
- 'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
1363
- 'sort': 1,
1364
- 'limit': limit,
1365
- }
1366
- if since is not None:
1367
- request['start'] = since
1368
- request, params = self.handle_until_option('end', request, params)
1369
- response = self.publicGetCandlesTradeTimeframeSymbolHist(self.extend(request, params))
1370
- #
1371
- # [
1372
- # [1591503840000,0.025069,0.025068,0.025069,0.025068,1.97828998],
1373
- # [1591504500000,0.025065,0.025065,0.025065,0.025065,1.0164],
1374
- # [1591504620000,0.025062,0.025062,0.025062,0.025062,0.5],
1375
- # ]
1376
- #
1377
- return self.parse_ohlcvs(response, market, timeframe, since, limit)
1378
-
1379
- def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1380
- #
1381
- # [
1382
- # 1457539800000,
1383
- # 0.02594,
1384
- # 0.02594,
1385
- # 0.02594,
1386
- # 0.02594,
1387
- # 0.1
1388
- # ]
1389
- #
1390
- return [
1391
- self.safe_integer(ohlcv, 0),
1392
- self.safe_number(ohlcv, 1),
1393
- self.safe_number(ohlcv, 3),
1394
- self.safe_number(ohlcv, 4),
1395
- self.safe_number(ohlcv, 2),
1396
- self.safe_number(ohlcv, 5),
1397
- ]
1398
-
1399
- def parse_order_status(self, status: Str):
1400
- if status is None:
1401
- return status
1402
- parts = status.split(' ')
1403
- state = self.safe_string(parts, 0)
1404
- statuses: dict = {
1405
- 'ACTIVE': 'open',
1406
- 'PARTIALLY': 'open',
1407
- 'EXECUTED': 'closed',
1408
- 'CANCELED': 'canceled',
1409
- 'INSUFFICIENT': 'canceled',
1410
- 'POSTONLY CANCELED': 'canceled',
1411
- 'RSN_DUST': 'rejected',
1412
- 'RSN_PAUSE': 'rejected',
1413
- 'IOC CANCELED': 'canceled',
1414
- 'FILLORKILL CANCELED': 'canceled',
1415
- }
1416
- return self.safe_string(statuses, state, status)
1417
-
1418
- def parse_order_flags(self, flags):
1419
- # flags can be added to each other...
1420
- flagValues: dict = {
1421
- '1024': ['reduceOnly'],
1422
- '4096': ['postOnly'],
1423
- '5120': ['reduceOnly', 'postOnly'],
1424
- # '64': 'hidden', # The hidden order option ensures an order does not appear in the order book
1425
- # '512': 'close', # Close position if position present.
1426
- # '16384': 'OCO', # The one cancels other order option allows you to place a pair of orders stipulating that if one order is executed fully or partially, then the other is automatically canceled.
1427
- # '524288': 'No Var Rates' # Excludes variable rate funding offers from matching against self order, if on margin
1428
- }
1429
- return self.safe_value(flagValues, flags, None)
1430
-
1431
- def parse_time_in_force(self, orderType):
1432
- orderTypes: dict = {
1433
- 'EXCHANGE IOC': 'IOC',
1434
- 'EXCHANGE FOK': 'FOK',
1435
- 'IOC': 'IOC', # Margin
1436
- 'FOK': 'FOK', # Margin
1437
- }
1438
- return self.safe_string(orderTypes, orderType, 'GTC')
1439
-
1440
- def parse_order(self, order: dict, market: Market = None) -> Order:
1441
- orderList = self.safe_list(order, 'result')
1442
- id = self.safe_string(orderList, 0)
1443
- marketId = self.safe_string(orderList, 3)
1444
- symbol = self.safe_symbol(marketId)
1445
- # https://github.com/ccxt/ccxt/issues/6686
1446
- # timestamp = self.safe_timestamp(orderObject, 5)
1447
- timestamp = self.safe_integer(orderList, 5)
1448
- remaining = Precise.string_abs(self.safe_string(orderList, 6))
1449
- signedAmount = self.safe_string(orderList, 7)
1450
- amount = Precise.string_abs(signedAmount)
1451
- side = 'sell' if Precise.string_lt(signedAmount, '0') else 'buy'
1452
- orderType = self.safe_string(orderList, 8)
1453
- type = self.safe_string(self.safe_value(self.options, 'exchangeTypes'), orderType)
1454
- timeInForce = self.parse_time_in_force(orderType)
1455
- rawFlags = self.safe_string(orderList, 12)
1456
- flags = self.parse_order_flags(rawFlags)
1457
- postOnly = False
1458
- if flags is not None:
1459
- for i in range(0, len(flags)):
1460
- if flags[i] == 'postOnly':
1461
- postOnly = True
1462
- price = self.safe_string(orderList, 16)
1463
- stopPrice = None
1464
- if (orderType == 'EXCHANGE STOP') or (orderType == 'EXCHANGE STOP LIMIT'):
1465
- price = None
1466
- stopPrice = self.safe_string(orderList, 16)
1467
- if orderType == 'EXCHANGE STOP LIMIT':
1468
- price = self.safe_string(orderList, 19)
1469
- status = None
1470
- statusString = self.safe_string(orderList, 13)
1471
- if statusString is not None:
1472
- parts = statusString.split(' @ ')
1473
- status = self.parse_order_status(self.safe_string(parts, 0))
1474
- average = self.safe_string(orderList, 17)
1475
- clientOrderId = self.safe_string(orderList, 2)
1476
- return self.safe_order({
1477
- 'info': orderList,
1478
- 'id': id,
1479
- 'clientOrderId': clientOrderId,
1480
- 'timestamp': timestamp,
1481
- 'datetime': self.iso8601(timestamp),
1482
- 'lastTradeTimestamp': None,
1483
- 'symbol': symbol,
1484
- 'type': type,
1485
- 'timeInForce': timeInForce,
1486
- 'postOnly': postOnly,
1487
- 'side': side,
1488
- 'price': price,
1489
- 'stopPrice': stopPrice,
1490
- 'triggerPrice': stopPrice,
1491
- 'amount': amount,
1492
- 'cost': None,
1493
- 'average': average,
1494
- 'filled': None,
1495
- 'remaining': remaining,
1496
- 'status': status,
1497
- 'fee': None,
1498
- 'trades': None,
1499
- }, market)
1500
-
1501
- def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1502
- """
1503
- * @ignore
1504
- helper function to build an order request
1505
- :param str symbol: unified symbol of the market to create an order in
1506
- :param str type: 'market' or 'limit'
1507
- :param str side: 'buy' or 'sell'
1508
- :param float amount: how much you want to trade in units of the base currency
1509
- :param float [price]: the price of the order, in units of the quote currency, ignored in market orders
1510
- :param dict [params]: extra parameters specific to the exchange API endpoint
1511
- :param float [params.stopPrice]: The price at which a trigger order is triggered at
1512
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1513
- :param bool [params.postOnly]:
1514
- :param bool [params.reduceOnly]: Ensures that the executed order does not flip the opened position.
1515
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
1516
- :param int [params.lev]: leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1517
- :param str [params.price_traling]: The trailing price for a trailing stop order
1518
- :param str [params.price_aux_limit]: Order price for stop limit orders
1519
- :param str [params.price_oco_stop]: OCO stop price
1520
- :returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
1521
- """
1522
- market = self.market(symbol)
1523
- amountString = self.amount_to_precision(symbol, amount)
1524
- amountString = amountString if (side == 'buy') else Precise.string_neg(amountString)
1525
- request: dict = {
1526
- 'symbol': market['id'],
1527
- 'amount': amountString,
1528
- }
1529
- stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1530
- trailingAmount = self.safe_string(params, 'trailingAmount')
1531
- timeInForce = self.safe_string(params, 'timeInForce')
1532
- postOnlyParam = self.safe_bool(params, 'postOnly', False)
1533
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1534
- clientOrderId = self.safe_value_2(params, 'cid', 'clientOrderId')
1535
- orderType = type.upper()
1536
- if trailingAmount is not None:
1537
- orderType = 'TRAILING STOP'
1538
- request['price_trailing'] = trailingAmount
1539
- elif stopPrice is not None:
1540
- # request['price'] is taken for stop orders
1541
- request['price'] = self.price_to_precision(symbol, stopPrice)
1542
- if type == 'limit':
1543
- orderType = 'STOP LIMIT'
1544
- request['price_aux_limit'] = self.price_to_precision(symbol, price)
1545
- else:
1546
- orderType = 'STOP'
1547
- ioc = (timeInForce == 'IOC')
1548
- fok = (timeInForce == 'FOK')
1549
- postOnly = (postOnlyParam or (timeInForce == 'PO'))
1550
- if (ioc or fok) and (price is None):
1551
- raise InvalidOrder(self.id + ' createOrder() requires a price argument with IOC and FOK orders')
1552
- if (ioc or fok) and (type == 'market'):
1553
- raise InvalidOrder(self.id + ' createOrder() does not allow market IOC and FOK orders')
1554
- if (type != 'market') and (stopPrice is None):
1555
- request['price'] = self.price_to_precision(symbol, price)
1556
- if ioc:
1557
- orderType = 'IOC'
1558
- elif fok:
1559
- orderType = 'FOK'
1560
- marginMode = None
1561
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
1562
- if market['spot'] and (marginMode is None):
1563
- # The EXCHANGE prefix is only required for non margin spot markets
1564
- orderType = 'EXCHANGE ' + orderType
1565
- request['type'] = orderType
1566
- # flag values may be summed to combine flags
1567
- flags = 0
1568
- if postOnly:
1569
- flags = self.sum(flags, 4096)
1570
- if reduceOnly:
1571
- flags = self.sum(flags, 1024)
1572
- if flags != 0:
1573
- request['flags'] = flags
1574
- if clientOrderId is not None:
1575
- request['cid'] = clientOrderId
1576
- params = self.omit(params, ['triggerPrice', 'stopPrice', 'timeInForce', 'postOnly', 'reduceOnly', 'trailingAmount', 'clientOrderId'])
1577
- return self.extend(request, params)
1578
-
1579
- def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1580
- """
1581
- create an order on the exchange
1582
- :see: https://docs.bitfinex.com/reference/rest-auth-submit-order
1583
- :param str symbol: unified CCXT market symbol
1584
- :param str type: 'limit' or 'market'
1585
- :param str side: 'buy' or 'sell'
1586
- :param float amount: the amount of currency to trade
1587
- :param float [price]: price of the order
1588
- :param dict [params]: extra parameters specific to the exchange API endpoint
1589
- :param float [params.stopPrice]: the price that triggers a trigger order
1590
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1591
- :param boolean [params.postOnly]: set to True if you want to make a post only order
1592
- :param boolean [params.reduceOnly]: indicates that the order is to reduce the size of a position
1593
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
1594
- :param int [params.lev]: leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1595
- :param str [params.price_aux_limit]: order price for stop limit orders
1596
- :param str [params.price_oco_stop]: OCO stop price
1597
- :param str [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
1598
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1599
- """
1600
- self.load_markets()
1601
- market = self.market(symbol)
1602
- request = self.create_order_request(symbol, type, side, amount, price, params)
1603
- response = self.privatePostAuthWOrderSubmit(request)
1604
- #
1605
- # [
1606
- # 1653325121, # Timestamp in milliseconds
1607
- # "on-req", # Purpose of notification('on-req', 'oc-req', "uca", 'fon-req', "foc-req")
1608
- # null, # unique ID of the message
1609
- # null,
1610
- # [
1611
- # [
1612
- # 95412102131, # Order ID
1613
- # null, # Group ID
1614
- # 1653325121798, # Client Order ID
1615
- # "tDOGE:UST", # Market ID
1616
- # 1653325121798, # Millisecond timestamp of creation
1617
- # 1653325121798, # Millisecond timestamp of update
1618
- # -10, # Amount(Positive means buy, negative means sell)
1619
- # -10, # Original amount
1620
- # "EXCHANGE LIMIT", # Type of the order: LIMIT, EXCHANGE LIMIT, MARKET, EXCHANGE MARKET, STOP, EXCHANGE STOP, STOP LIMIT, EXCHANGE STOP LIMIT, TRAILING STOP, EXCHANGE TRAILING STOP, FOK, EXCHANGE FOK, IOC, EXCHANGE IOC.
1621
- # null, # Previous order type(stop-limit orders are converted to limit orders so for them previous type is always STOP)
1622
- # null, # Millisecond timestamp of Time-In-Force: automatic order cancellation
1623
- # null, # _PLACEHOLDER
1624
- # 4096, # Flags, see parseOrderFlags()
1625
- # "ACTIVE", # Order Status, see parseOrderStatus()
1626
- # null, # _PLACEHOLDER
1627
- # null, # _PLACEHOLDER
1628
- # 0.071, # Price(Stop Price for stop-limit orders, Limit Price for limit orders)
1629
- # 0, # Average Price
1630
- # 0, # Trailing Price
1631
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1632
- # null, # _PLACEHOLDER
1633
- # null, # _PLACEHOLDER
1634
- # null, # _PLACEHOLDER
1635
- # 0, # Hidden(0 if False, 1 if True)
1636
- # 0, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
1637
- # null, # _PLACEHOLDER
1638
- # null, # _PLACEHOLDER
1639
- # null, # _PLACEHOLDER
1640
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
1641
- # null, # _PLACEHOLDER
1642
- # null, # _PLACEHOLDER
1643
- # {"$F7":1} # additional meta information about the order( $F7 = IS_POST_ONLY(0 if False, 1 if True), $F33 = Leverage(int))
1644
- # ]
1645
- # ],
1646
- # null, # CODE(work in progress)
1647
- # "SUCCESS", # Status of the request
1648
- # "Submitting 1 orders." # Message
1649
- # ]
1650
- #
1651
- status = self.safe_string(response, 6)
1652
- if status != 'SUCCESS':
1653
- errorCode = response[5]
1654
- errorText = response[7]
1655
- raise ExchangeError(self.id + ' ' + response[6] + ': ' + errorText + '(#' + errorCode + ')')
1656
- orders = self.safe_list(response, 4, [])
1657
- order = self.safe_list(orders, 0)
1658
- return self.parse_order(self.extend({'result': order}), market)
1659
-
1660
- def create_orders(self, orders: List[OrderRequest], params={}):
1661
- """
1662
- create a list of trade orders
1663
- :see: https://docs.bitfinex.com/reference/rest-auth-order-multi
1664
- :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
1665
- :param dict [params]: extra parameters specific to the exchange API endpoint
1666
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1667
- """
1668
- self.load_markets()
1669
- ordersRequests = []
1670
- for i in range(0, len(orders)):
1671
- rawOrder = orders[i]
1672
- symbol = self.safe_string(rawOrder, 'symbol')
1673
- type = self.safe_string(rawOrder, 'type')
1674
- side = self.safe_string(rawOrder, 'side')
1675
- amount = self.safe_number(rawOrder, 'amount')
1676
- price = self.safe_number(rawOrder, 'price')
1677
- orderParams = self.safe_dict(rawOrder, 'params', {})
1678
- orderRequest = self.create_order_request(symbol, type, side, amount, price, orderParams)
1679
- ordersRequests.append(['on', orderRequest])
1680
- request: dict = {
1681
- 'ops': ordersRequests,
1682
- }
1683
- response = self.privatePostAuthWOrderMulti(request)
1684
- #
1685
- # [
1686
- # 1706762515553,
1687
- # "ox_multi-req",
1688
- # null,
1689
- # null,
1690
- # [
1691
- # [
1692
- # 1706762515,
1693
- # "on-req",
1694
- # null,
1695
- # null,
1696
- # [
1697
- # [139567428547,null,1706762515551,"tBTCUST",1706762515551,1706762515551,0.0001,0.0001,"EXCHANGE LIMIT",null,null,null,0,"ACTIVE",null,null,35000,0,0,0,null,null,null,0,0,null,null,null,"API>BFX",null,null,{}]
1698
- # ],
1699
- # null,
1700
- # "SUCCESS",
1701
- # "Submitting 1 orders."
1702
- # ],
1703
- # ],
1704
- # null,
1705
- # "SUCCESS",
1706
- # "Submitting 2 order operations."
1707
- # ]
1708
- #
1709
- results = []
1710
- data = self.safe_list(response, 4, [])
1711
- for i in range(0, len(data)):
1712
- entry = data[i]
1713
- individualOrder = entry[4]
1714
- results.append({'result': individualOrder[0]})
1715
- return self.parse_orders(results)
1716
-
1717
- def cancel_all_orders(self, symbol: Str = None, params={}):
1718
- """
1719
- cancel all open orders
1720
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-orders-multiple
1721
- :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1722
- :param dict [params]: extra parameters specific to the exchange API endpoint
1723
- :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1724
- """
1725
- self.load_markets()
1726
- request: dict = {
1727
- 'all': 1,
1728
- }
1729
- response = self.privatePostAuthWOrderCancelMulti(self.extend(request, params))
1730
- orders = self.safe_list(response, 4, [])
1731
- ordersList = []
1732
- for i in range(0, len(orders)):
1733
- ordersList.append({'result': orders[i]})
1734
- return self.parse_orders(ordersList)
1735
-
1736
- def cancel_order(self, id: str, symbol: Str = None, params={}):
1737
- """
1738
- cancels an open order
1739
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-order
1740
- :param str id: order id
1741
- :param str symbol: Not used by bitfinex2 cancelOrder()
1742
- :param dict [params]: extra parameters specific to the exchange API endpoint
1743
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1744
- """
1745
- self.load_markets()
1746
- cid = self.safe_value_2(params, 'cid', 'clientOrderId') # client order id
1747
- request = None
1748
- if cid is not None:
1749
- cidDate = self.safe_value(params, 'cidDate') # client order id date
1750
- if cidDate is None:
1751
- raise InvalidOrder(self.id + " canceling an order by clientOrderId('cid') requires both 'cid' and 'cid_date'('YYYY-MM-DD')")
1752
- request = {
1753
- 'cid': cid,
1754
- 'cid_date': cidDate,
1755
- }
1756
- params = self.omit(params, ['cid', 'clientOrderId'])
1757
- else:
1758
- request = {
1759
- 'id': int(id),
1760
- }
1761
- response = self.privatePostAuthWOrderCancel(self.extend(request, params))
1762
- order = self.safe_value(response, 4)
1763
- orderObject = {'result': order}
1764
- return self.parse_order(orderObject)
1765
-
1766
- def cancel_orders(self, ids, symbol: Str = None, params={}):
1767
- """
1768
- cancel multiple orders at the same time
1769
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-orders-multiple
1770
- :param str[] ids: order ids
1771
- :param str symbol: unified market symbol, default is None
1772
- :param dict [params]: extra parameters specific to the exchange API endpoint
1773
- :returns dict: an array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1774
- """
1775
- self.load_markets()
1776
- for i in range(0, len(ids)):
1777
- ids[i] = self.parse_to_numeric(ids[i])
1778
- request: dict = {
1779
- 'id': ids,
1780
- }
1781
- market = None
1782
- if symbol is not None:
1783
- market = self.market(symbol)
1784
- response = self.privatePostAuthWOrderCancelMulti(self.extend(request, params))
1785
- #
1786
- # [
1787
- # 1706740198811,
1788
- # "oc_multi-req",
1789
- # null,
1790
- # null,
1791
- # [
1792
- # [
1793
- # 139530205057,
1794
- # null,
1795
- # 1706740132275,
1796
- # "tBTCF0:USTF0",
1797
- # 1706740132276,
1798
- # 1706740132276,
1799
- # 0.0001,
1800
- # 0.0001,
1801
- # "LIMIT",
1802
- # null,
1803
- # null,
1804
- # null,
1805
- # 0,
1806
- # "ACTIVE",
1807
- # null,
1808
- # null,
1809
- # 39000,
1810
- # 0,
1811
- # 0,
1812
- # 0,
1813
- # null,
1814
- # null,
1815
- # null,
1816
- # 0,
1817
- # 0,
1818
- # null,
1819
- # null,
1820
- # null,
1821
- # "API>BFX",
1822
- # null,
1823
- # null,
1824
- # {
1825
- # "lev": 10,
1826
- # "$F33": 10
1827
- # }
1828
- # ],
1829
- # ],
1830
- # null,
1831
- # "SUCCESS",
1832
- # "Submitting 2 order cancellations."
1833
- # ]
1834
- #
1835
- orders = self.safe_list(response, 4, [])
1836
- ordersList = []
1837
- for i in range(0, len(orders)):
1838
- ordersList.append({'result': orders[i]})
1839
- return self.parse_orders(ordersList, market)
1840
-
1841
- def fetch_open_order(self, id: str, symbol: Str = None, params={}):
1842
- """
1843
- fetch an open order by it's id
1844
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1845
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1846
- :param str id: order id
1847
- :param str symbol: unified market symbol, default is None
1848
- :param dict [params]: extra parameters specific to the exchange API endpoint
1849
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1850
- """
1851
- request: dict = {
1852
- 'id': [int(id)],
1853
- }
1854
- orders = self.fetch_open_orders(symbol, None, None, self.extend(request, params))
1855
- order = self.safe_value(orders, 0)
1856
- if order is None:
1857
- raise OrderNotFound(self.id + ' order ' + id + ' not found')
1858
- return order
1859
-
1860
- def fetch_closed_order(self, id: str, symbol: Str = None, params={}):
1861
- """
1862
- fetch an open order by it's id
1863
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1864
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1865
- :param str id: order id
1866
- :param str symbol: unified market symbol, default is None
1867
- :param dict [params]: extra parameters specific to the exchange API endpoint
1868
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1869
- """
1870
- request: dict = {
1871
- 'id': [int(id)],
1872
- }
1873
- orders = self.fetch_closed_orders(symbol, None, None, self.extend(request, params))
1874
- order = self.safe_value(orders, 0)
1875
- if order is None:
1876
- raise OrderNotFound(self.id + ' order ' + id + ' not found')
1877
- return order
1878
-
1879
- def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1880
- """
1881
- fetch all unfilled currently open orders
1882
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1883
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1884
- :param str symbol: unified market symbol
1885
- :param int [since]: the earliest time in ms to fetch open orders for
1886
- :param int [limit]: the maximum number of open orders structures to retrieve
1887
- :param dict [params]: extra parameters specific to the exchange API endpoint
1888
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1889
- """
1890
- self.load_markets()
1891
- request: dict = {}
1892
- market = None
1893
- response = None
1894
- if symbol is None:
1895
- response = self.privatePostAuthROrders(self.extend(request, params))
1896
- else:
1897
- market = self.market(symbol)
1898
- request['symbol'] = market['id']
1899
- response = self.privatePostAuthROrdersSymbol(self.extend(request, params))
1900
- #
1901
- # [
1902
- # [
1903
- # 95408916206, # Order ID
1904
- # null, # Group Order ID
1905
- # 1653322349926, # Client Order ID
1906
- # "tDOGE:UST", # Market ID
1907
- # 1653322349926, # Created Timestamp in milliseconds
1908
- # 1653322349927, # Updated Timestamp in milliseconds
1909
- # -10, # Amount remaining(Positive means buy, negative means sell)
1910
- # -10, # Original amount
1911
- # "EXCHANGE LIMIT", # Order type
1912
- # null, # Previous Order Type
1913
- # null, # _PLACEHOLDER
1914
- # null, # _PLACEHOLDER
1915
- # 0, # Flags, see parseOrderFlags()
1916
- # "ACTIVE", # Order Status, see parseOrderStatus()
1917
- # null, # _PLACEHOLDER
1918
- # null, # _PLACEHOLDER
1919
- # 0.11, # Price
1920
- # 0, # Average Price
1921
- # 0, # Trailing Price
1922
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1923
- # null, # _PLACEHOLDER
1924
- # null, # _PLACEHOLDER
1925
- # null, # _PLACEHOLDER
1926
- # 0, # Hidden(0 if False, 1 if True)
1927
- # 0, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
1928
- # null, # _PLACEHOLDER
1929
- # null, # _PLACEHOLDER
1930
- # null, # _PLACEHOLDER
1931
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
1932
- # null, # _PLACEHOLDER
1933
- # null, # _PLACEHOLDER
1934
- # {"$F7":1} # additional meta information about the order( $F7 = IS_POST_ONLY(0 if False, 1 if True), $F33 = Leverage(int))
1935
- # ],
1936
- # ]
1937
- #
1938
- ordersList = []
1939
- for i in range(0, len(response)):
1940
- ordersList.append({'result': response[i]})
1941
- return self.parse_orders(ordersList, market, since, limit)
1942
-
1943
- def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1944
- """
1945
- fetches information on multiple closed orders made by the user
1946
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1947
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1948
- :param str symbol: unified market symbol of the market orders were made in
1949
- :param int [since]: the earliest time in ms to fetch orders for
1950
- :param int [limit]: the maximum number of order structures to retrieve
1951
- :param dict [params]: extra parameters specific to the exchange API endpoint
1952
- :param int [params.until]: the latest time in ms to fetch entries for
1953
- :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)
1954
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1955
- """
1956
- # returns the most recent closed or canceled orders up to circa two weeks ago
1957
- self.load_markets()
1958
- paginate = False
1959
- paginate, params = self.handle_option_and_params(params, 'fetchClosedOrders', 'paginate')
1960
- if paginate:
1961
- return self.fetch_paginated_call_dynamic('fetchClosedOrders', symbol, since, limit, params)
1962
- request: dict = {}
1963
- if since is not None:
1964
- request['start'] = since
1965
- if limit is not None:
1966
- request['limit'] = limit # default 25, max 2500
1967
- request, params = self.handle_until_option('end', request, params)
1968
- market = None
1969
- response = None
1970
- if symbol is None:
1971
- response = self.privatePostAuthROrdersHist(self.extend(request, params))
1972
- else:
1973
- market = self.market(symbol)
1974
- request['symbol'] = market['id']
1975
- response = self.privatePostAuthROrdersSymbolHist(self.extend(request, params))
1976
- #
1977
- # [
1978
- # [
1979
- # 95412102131, # Order ID
1980
- # null, # Group Order ID
1981
- # 1653325121798, # Client Order ID
1982
- # "tDOGE:UST", # Market ID
1983
- # 1653325122000, # Created Timestamp in milliseconds
1984
- # 1653325122000, # Updated Timestamp in milliseconds
1985
- # -10, # Amount remaining(Positive means buy, negative means sell)
1986
- # -10, # Original amount
1987
- # "EXCHANGE LIMIT", # Order type
1988
- # null, # Previous Order Type
1989
- # null, # Millisecond timestamp of Time-In-Force: automatic order cancellation
1990
- # null, # _PLACEHOLDER
1991
- # "4096", # Flags, see parseOrderFlags()
1992
- # "POSTONLY CANCELED", # Order Status, see parseOrderStatus()
1993
- # null, # _PLACEHOLDER
1994
- # null, # _PLACEHOLDER
1995
- # 0.071, # Price
1996
- # 0, # Average Price
1997
- # 0, # Trailing Price
1998
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1999
- # null, # _PLACEHOLDER
2000
- # null, # _PLACEHOLDER
2001
- # null, # _PLACEHOLDER
2002
- # 0, # Notify(0 if False, 1 if True)
2003
- # 0, # Hidden(0 if False, 1 if True)
2004
- # null, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
2005
- # null, # _PLACEHOLDER
2006
- # null, # _PLACEHOLDER
2007
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
2008
- # null, # _PLACEHOLDER
2009
- # null, # _PLACEHOLDER
2010
- # {"_$F7":1} # additional meta information about the order( _$F7 = IS_POST_ONLY(0 if False, 1 if True), _$F33 = Leverage(int))
2011
- # ]
2012
- # ]
2013
- #
2014
- ordersList = []
2015
- for i in range(0, len(response)):
2016
- ordersList.append({'result': response[i]})
2017
- return self.parse_orders(ordersList, market, since, limit)
2018
-
2019
- def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2020
- """
2021
- fetch all the trades made from a single order
2022
- :see: https://docs.bitfinex.com/reference/rest-auth-order-trades
2023
- :param str id: order id
2024
- :param str symbol: unified market symbol
2025
- :param int [since]: the earliest time in ms to fetch trades for
2026
- :param int [limit]: the maximum number of trades to retrieve
2027
- :param dict [params]: extra parameters specific to the exchange API endpoint
2028
- :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2029
- """
2030
- if symbol is None:
2031
- raise ArgumentsRequired(self.id + ' fetchOrderTrades() requires a symbol argument')
2032
- self.load_markets()
2033
- market = self.market(symbol)
2034
- orderId = int(id)
2035
- request: dict = {
2036
- 'id': orderId,
2037
- 'symbol': market['id'],
2038
- }
2039
- # valid for trades upto 10 days old
2040
- response = self.privatePostAuthROrderSymbolIdTrades(self.extend(request, params))
2041
- tradesList = []
2042
- for i in range(0, len(response)):
2043
- tradesList.append({'result': response[i]}) # convert to array of dicts to match parseOrder signature
2044
- return self.parse_trades(tradesList, market, since, limit)
2045
-
2046
- def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2047
- """
2048
- fetch all trades made by the user
2049
- :see: https://docs.bitfinex.com/reference/rest-auth-trades
2050
- :see: https://docs.bitfinex.com/reference/rest-auth-trades-by-symbol
2051
- :param str symbol: unified market symbol
2052
- :param int [since]: the earliest time in ms to fetch trades for
2053
- :param int [limit]: the maximum number of trades structures to retrieve
2054
- :param dict [params]: extra parameters specific to the exchange API endpoint
2055
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2056
- """
2057
- self.load_markets()
2058
- market = None
2059
- request: dict = {
2060
- 'end': self.milliseconds(),
2061
- }
2062
- if since is not None:
2063
- request['start'] = since
2064
- if limit is not None:
2065
- request['limit'] = limit # default 25, max 1000
2066
- response = None
2067
- if symbol is not None:
2068
- market = self.market(symbol)
2069
- request['symbol'] = market['id']
2070
- response = self.privatePostAuthRTradesSymbolHist(self.extend(request, params))
2071
- else:
2072
- response = self.privatePostAuthRTradesHist(self.extend(request, params))
2073
- tradesList = []
2074
- for i in range(0, len(response)):
2075
- tradesList.append({'result': response[i]}) # convert to array of dicts to match parseOrder signature
2076
- return self.parse_trades(tradesList, market, since, limit)
2077
-
2078
- def create_deposit_address(self, code: str, params={}):
2079
- """
2080
- create a currency deposit address
2081
- :see: https://docs.bitfinex.com/reference/rest-auth-deposit-address
2082
- :param str code: unified currency code of the currency for the deposit address
2083
- :param dict [params]: extra parameters specific to the exchange API endpoint
2084
- :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2085
- """
2086
- self.load_markets()
2087
- request: dict = {
2088
- 'op_renew': 1,
2089
- }
2090
- return self.fetch_deposit_address(code, self.extend(request, params))
2091
-
2092
- def fetch_deposit_address(self, code: str, params={}):
2093
- """
2094
- fetch the deposit address for a currency associated with self account
2095
- :see: https://docs.bitfinex.com/reference/rest-auth-deposit-address
2096
- :param str code: unified currency code
2097
- :param dict [params]: extra parameters specific to the exchange API endpoint
2098
- :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2099
- """
2100
- self.load_markets()
2101
- currency = self.currency(code)
2102
- # if not provided explicitly we will try to match using the currency name
2103
- network = self.safe_string(params, 'network', code)
2104
- currencyNetworks = self.safe_value(currency, 'networks', {})
2105
- currencyNetwork = self.safe_value(currencyNetworks, network)
2106
- networkId = self.safe_string(currencyNetwork, 'id')
2107
- if networkId is None:
2108
- raise ArgumentsRequired(self.id + " fetchDepositAddress() could not find a network for '" + code + "'. You can specify it by providing the 'network' value inside params")
2109
- wallet = self.safe_string(params, 'wallet', 'exchange') # 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
2110
- params = self.omit(params, 'network', 'wallet')
2111
- request: dict = {
2112
- 'method': networkId,
2113
- 'wallet': wallet,
2114
- 'op_renew': 0, # a value of 1 will generate a new address
2115
- }
2116
- response = self.privatePostAuthWDepositAddress(self.extend(request, params))
2117
- #
2118
- # [
2119
- # 1582269616687, # MTS Millisecond Time Stamp of the update
2120
- # "acc_dep", # TYPE Purpose of notification "acc_dep" for account deposit
2121
- # null, # MESSAGE_ID unique ID of the message
2122
- # null, # not documented
2123
- # [
2124
- # null, # PLACEHOLDER
2125
- # "BITCOIN", # METHOD Method of deposit
2126
- # "BTC", # CURRENCY_CODE Currency code of new address
2127
- # null, # PLACEHOLDER
2128
- # "1BC9PZqpUmjyEB54uggn8TFKj49zSDYzqG", # ADDRESS
2129
- # null, # POOL_ADDRESS
2130
- # ],
2131
- # null, # CODE null or integer work in progress
2132
- # "SUCCESS", # STATUS Status of the notification, SUCCESS, ERROR, FAILURE
2133
- # "success", # TEXT Text of the notification
2134
- # ]
2135
- #
2136
- result = self.safe_value(response, 4, [])
2137
- poolAddress = self.safe_string(result, 5)
2138
- address = self.safe_string(result, 4) if (poolAddress is None) else poolAddress
2139
- tag = None if (poolAddress is None) else self.safe_string(result, 4)
2140
- self.check_address(address)
2141
- return {
2142
- 'currency': code,
2143
- 'address': address,
2144
- 'tag': tag,
2145
- 'network': None,
2146
- 'info': response,
2147
- }
2148
-
2149
- def parse_transaction_status(self, status: Str):
2150
- statuses: dict = {
2151
- 'SUCCESS': 'ok',
2152
- 'COMPLETED': 'ok',
2153
- 'ERROR': 'failed',
2154
- 'FAILURE': 'failed',
2155
- 'CANCELED': 'canceled',
2156
- 'PENDING APPROVAL': 'pending',
2157
- 'PENDING': 'pending',
2158
- 'PENDING REVIEW': 'pending',
2159
- 'PENDING CANCELLATION': 'pending',
2160
- 'SENDING': 'pending',
2161
- 'USER APPROVED': 'pending',
2162
- }
2163
- return self.safe_string(statuses, status, status)
2164
-
2165
- def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2166
- #
2167
- # withdraw
2168
- #
2169
- # [
2170
- # 1582271520931, # MTS Millisecond Time Stamp of the update
2171
- # "acc_wd-req", # TYPE Purpose of notification "acc_wd-req" account withdrawal request
2172
- # null, # MESSAGE_ID unique ID of the message
2173
- # null, # not documented
2174
- # [
2175
- # 0, # WITHDRAWAL_ID Unique Withdrawal ID
2176
- # null, # PLACEHOLDER
2177
- # "bitcoin", # METHOD Method of withdrawal
2178
- # null, # PAYMENT_ID Payment ID if relevant
2179
- # "exchange", # WALLET Sending wallet
2180
- # 1, # AMOUNT Amount of Withdrawal less fee
2181
- # null, # PLACEHOLDER
2182
- # null, # PLACEHOLDER
2183
- # 0.0004, # WITHDRAWAL_FEE Fee on withdrawal
2184
- # ],
2185
- # null, # CODE null or integer Work in progress
2186
- # "SUCCESS", # STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
2187
- # "Invalid bitcoin address(abcdef)", # TEXT Text of the notification
2188
- # ]
2189
- #
2190
- # fetchDepositsWithdrawals
2191
- #
2192
- # [
2193
- # 13293039, # ID
2194
- # "ETH", # CURRENCY
2195
- # "ETHEREUM", # CURRENCY_NAME
2196
- # null,
2197
- # null,
2198
- # 1574175052000, # MTS_STARTED
2199
- # 1574181326000, # MTS_UPDATED
2200
- # null,
2201
- # null,
2202
- # "CANCELED", # STATUS
2203
- # null,
2204
- # null,
2205
- # -0.24, # AMOUNT, negative for withdrawals
2206
- # -0.00135, # FEES
2207
- # null,
2208
- # null,
2209
- # "0x38110e0Fc932CB2BE...........", # DESTINATION_ADDRESS
2210
- # null,
2211
- # null,
2212
- # null,
2213
- # "0x523ec8945500.....................................", # TRANSACTION_ID
2214
- # "Purchase of 100 pizzas", # WITHDRAW_TRANSACTION_NOTE, might also be: null
2215
- # ]
2216
- #
2217
- transactionLength = len(transaction)
2218
- timestamp = None
2219
- updated = None
2220
- code = None
2221
- amount = None
2222
- id = None
2223
- status = None
2224
- tag = None
2225
- type = None
2226
- feeCost = None
2227
- txid = None
2228
- addressTo = None
2229
- network = None
2230
- comment = None
2231
- if transactionLength == 8:
2232
- data = self.safe_value(transaction, 4, [])
2233
- timestamp = self.safe_integer(transaction, 0)
2234
- if currency is not None:
2235
- code = currency['code']
2236
- feeCost = self.safe_string(data, 8)
2237
- if feeCost is not None:
2238
- feeCost = Precise.string_abs(feeCost)
2239
- amount = self.safe_number(data, 5)
2240
- id = self.safe_string(data, 0)
2241
- status = 'ok'
2242
- if id == 0:
2243
- id = None
2244
- status = 'failed'
2245
- tag = self.safe_string(data, 3)
2246
- type = 'withdrawal'
2247
- elif transactionLength == 22:
2248
- id = self.safe_string(transaction, 0)
2249
- currencyId = self.safe_string(transaction, 1)
2250
- code = self.safe_currency_code(currencyId, currency)
2251
- networkId = self.safe_string(transaction, 2)
2252
- network = self.safe_network(networkId)
2253
- timestamp = self.safe_integer(transaction, 5)
2254
- updated = self.safe_integer(transaction, 6)
2255
- status = self.parse_transaction_status(self.safe_string(transaction, 9))
2256
- signedAmount = self.safe_string(transaction, 12)
2257
- amount = Precise.string_abs(signedAmount)
2258
- if signedAmount is not None:
2259
- if Precise.string_lt(signedAmount, '0'):
2260
- type = 'withdrawal'
2261
- else:
2262
- type = 'deposit'
2263
- feeCost = self.safe_string(transaction, 13)
2264
- if feeCost is not None:
2265
- feeCost = Precise.string_abs(feeCost)
2266
- addressTo = self.safe_string(transaction, 16)
2267
- txid = self.safe_string(transaction, 20)
2268
- comment = self.safe_string(transaction, 21)
2269
- return {
2270
- 'info': transaction,
2271
- 'id': id,
2272
- 'txid': txid,
2273
- 'type': type,
2274
- 'currency': code,
2275
- 'network': network,
2276
- 'amount': self.parse_number(amount),
2277
- 'status': status,
2278
- 'timestamp': timestamp,
2279
- 'datetime': self.iso8601(timestamp),
2280
- 'address': addressTo, # self is actually the tag for XRP transfers(the address is missing)
2281
- 'addressFrom': None,
2282
- 'addressTo': addressTo,
2283
- 'tag': tag, # refix it properly for the tag from description
2284
- 'tagFrom': None,
2285
- 'tagTo': tag,
2286
- 'updated': updated,
2287
- 'comment': comment,
2288
- 'internal': None,
2289
- 'fee': {
2290
- 'currency': code,
2291
- 'cost': self.parse_number(feeCost),
2292
- 'rate': None,
2293
- },
2294
- }
2295
-
2296
- def fetch_trading_fees(self, params={}) -> TradingFees:
2297
- """
2298
- fetch the trading fees for multiple markets
2299
- :see: https://docs.bitfinex.com/reference/rest-auth-summary
2300
- :param dict [params]: extra parameters specific to the exchange API endpoint
2301
- :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
2302
- """
2303
- self.load_markets()
2304
- response = self.privatePostAuthRSummary(params)
2305
- #
2306
- # Response Spec:
2307
- # [
2308
- # PLACEHOLDER,
2309
- # PLACEHOLDER,
2310
- # PLACEHOLDER,
2311
- # PLACEHOLDER,
2312
- # [
2313
- # [
2314
- # MAKER_FEE,
2315
- # MAKER_FEE,
2316
- # MAKER_FEE,
2317
- # PLACEHOLDER,
2318
- # PLACEHOLDER,
2319
- # DERIV_REBATE
2320
- # ],
2321
- # [
2322
- # TAKER_FEE_TO_CRYPTO,
2323
- # TAKER_FEE_TO_STABLE,
2324
- # TAKER_FEE_TO_FIAT,
2325
- # PLACEHOLDER,
2326
- # PLACEHOLDER,
2327
- # DERIV_TAKER_FEE
2328
- # ]
2329
- # ],
2330
- # PLACEHOLDER,
2331
- # PLACEHOLDER,
2332
- # PLACEHOLDER,
2333
- # PLACEHOLDER,
2334
- # {
2335
- # LEO_LEV,
2336
- # LEO_AMOUNT_AVG
2337
- # }
2338
- # ]
2339
- #
2340
- # Example response:
2341
- #
2342
- # [
2343
- # null,
2344
- # null,
2345
- # null,
2346
- # null,
2347
- # [
2348
- # [0.001, 0.001, 0.001, null, null, 0.0002],
2349
- # [0.002, 0.002, 0.002, null, null, 0.00065]
2350
- # ],
2351
- # [
2352
- # [
2353
- # {
2354
- # "curr": "Total(USD)",
2355
- # "vol": "0",
2356
- # "vol_safe": "0",
2357
- # "vol_maker": "0",
2358
- # "vol_BFX": "0",
2359
- # "vol_BFX_safe": "0",
2360
- # "vol_BFX_maker": "0"
2361
- # }
2362
- # ],
2363
- # {},
2364
- # 0
2365
- # ],
2366
- # [null, {}, 0],
2367
- # null,
2368
- # null,
2369
- # {leo_lev: "0", leo_amount_avg: "0"}
2370
- # ]
2371
- #
2372
- result: dict = {}
2373
- fiat = self.safe_value(self.options, 'fiat', {})
2374
- feeData = self.safe_value(response, 4, [])
2375
- makerData = self.safe_value(feeData, 0, [])
2376
- takerData = self.safe_value(feeData, 1, [])
2377
- makerFee = self.safe_number(makerData, 0)
2378
- makerFeeFiat = self.safe_number(makerData, 2)
2379
- makerFeeDeriv = self.safe_number(makerData, 5)
2380
- takerFee = self.safe_number(takerData, 0)
2381
- takerFeeFiat = self.safe_number(takerData, 2)
2382
- takerFeeDeriv = self.safe_number(takerData, 5)
2383
- for i in range(0, len(self.symbols)):
2384
- symbol = self.symbols[i]
2385
- market = self.market(symbol)
2386
- fee = {
2387
- 'info': response,
2388
- 'symbol': symbol,
2389
- 'percentage': True,
2390
- 'tierBased': True,
2391
- }
2392
- if market['quote'] in fiat:
2393
- fee['maker'] = makerFeeFiat
2394
- fee['taker'] = takerFeeFiat
2395
- elif market['contract']:
2396
- fee['maker'] = makerFeeDeriv
2397
- fee['taker'] = takerFeeDeriv
2398
- else: # TODO check if stable coin
2399
- fee['maker'] = makerFee
2400
- fee['taker'] = takerFee
2401
- result[symbol] = fee
2402
- return result
2403
-
2404
- def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2405
- """
2406
- fetch history of deposits and withdrawals
2407
- :see: https://docs.bitfinex.com/reference/movement-info
2408
- :see: https://docs.bitfinex.com/reference/rest-auth-movements
2409
- :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2410
- :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2411
- :param int [limit]: max number of deposit/withdrawals to return, default is None
2412
- :param dict [params]: extra parameters specific to the exchange API endpoint
2413
- :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2414
- """
2415
- self.load_markets()
2416
- currency = None
2417
- request: dict = {}
2418
- if since is not None:
2419
- request['start'] = since
2420
- if limit is not None:
2421
- request['limit'] = limit # max 1000
2422
- response = None
2423
- if code is not None:
2424
- currency = self.currency(code)
2425
- request['currency'] = currency['uppercaseId']
2426
- response = self.privatePostAuthRMovementsCurrencyHist(self.extend(request, params))
2427
- else:
2428
- response = self.privatePostAuthRMovementsHist(self.extend(request, params))
2429
- #
2430
- # [
2431
- # [
2432
- # 13293039, # ID
2433
- # "ETH", # CURRENCY
2434
- # "ETHEREUM", # CURRENCY_NAME
2435
- # null,
2436
- # null,
2437
- # 1574175052000, # MTS_STARTED
2438
- # 1574181326000, # MTS_UPDATED
2439
- # null,
2440
- # null,
2441
- # "CANCELED", # STATUS
2442
- # null,
2443
- # null,
2444
- # -0.24, # AMOUNT, negative for withdrawals
2445
- # -0.00135, # FEES
2446
- # null,
2447
- # null,
2448
- # "0x38110e0Fc932CB2BE...........", # DESTINATION_ADDRESS
2449
- # null,
2450
- # null,
2451
- # null,
2452
- # "0x523ec8945500.....................................", # TRANSACTION_ID
2453
- # "Purchase of 100 pizzas", # WITHDRAW_TRANSACTION_NOTE, might also be: null
2454
- # ]
2455
- # ]
2456
- #
2457
- return self.parse_transactions(response, currency, since, limit)
2458
-
2459
- def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2460
- """
2461
- make a withdrawal
2462
- :see: https://docs.bitfinex.com/reference/rest-auth-withdraw
2463
- :param str code: unified currency code
2464
- :param float amount: the amount to withdraw
2465
- :param str address: the address to withdraw to
2466
- :param str tag:
2467
- :param dict [params]: extra parameters specific to the exchange API endpoint
2468
- :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2469
- """
2470
- self.check_address(address)
2471
- self.load_markets()
2472
- currency = self.currency(code)
2473
- # if not provided explicitly we will try to match using the currency name
2474
- network = self.safe_string(params, 'network', code)
2475
- params = self.omit(params, 'network')
2476
- currencyNetworks = self.safe_value(currency, 'networks', {})
2477
- currencyNetwork = self.safe_value(currencyNetworks, network)
2478
- networkId = self.safe_string(currencyNetwork, 'id')
2479
- if networkId is None:
2480
- raise ArgumentsRequired(self.id + " withdraw() could not find a network for '" + code + "'. You can specify it by providing the 'network' value inside params")
2481
- wallet = self.safe_string(params, 'wallet', 'exchange') # 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
2482
- params = self.omit(params, 'network', 'wallet')
2483
- request: dict = {
2484
- 'method': networkId,
2485
- 'wallet': wallet,
2486
- 'amount': self.number_to_string(amount),
2487
- 'address': address,
2488
- }
2489
- if tag is not None:
2490
- request['payment_id'] = tag
2491
- withdrawOptions = self.safe_value(self.options, 'withdraw', {})
2492
- includeFee = self.safe_bool(withdrawOptions, 'includeFee', False)
2493
- if includeFee:
2494
- request['fee_deduct'] = 1
2495
- response = self.privatePostAuthWWithdraw(self.extend(request, params))
2496
- #
2497
- # [
2498
- # 1582271520931, # MTS Millisecond Time Stamp of the update
2499
- # "acc_wd-req", # TYPE Purpose of notification "acc_wd-req" account withdrawal request
2500
- # null, # MESSAGE_ID unique ID of the message
2501
- # null, # not documented
2502
- # [
2503
- # 0, # WITHDRAWAL_ID Unique Withdrawal ID
2504
- # null, # PLACEHOLDER
2505
- # "bitcoin", # METHOD Method of withdrawal
2506
- # null, # PAYMENT_ID Payment ID if relevant
2507
- # "exchange", # WALLET Sending wallet
2508
- # 1, # AMOUNT Amount of Withdrawal less fee
2509
- # null, # PLACEHOLDER
2510
- # null, # PLACEHOLDER
2511
- # 0.0004, # WITHDRAWAL_FEE Fee on withdrawal
2512
- # ],
2513
- # null, # CODE null or integer Work in progress
2514
- # "SUCCESS", # STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
2515
- # "Invalid bitcoin address(abcdef)", # TEXT Text of the notification
2516
- # ]
2517
- #
2518
- # in case of failure:
2519
- #
2520
- # [
2521
- # "error",
2522
- # 10001,
2523
- # "Momentary balance check. Please wait few seconds and try the transfer again."
2524
- # ]
2525
- #
2526
- statusMessage = self.safe_string(response, 0)
2527
- if statusMessage == 'error':
2528
- feedback = self.id + ' ' + response
2529
- message = self.safe_string(response, 2, '')
2530
- # same message v1
2531
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2532
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2533
- raise ExchangeError(feedback) # unknown message
2534
- text = self.safe_string(response, 7)
2535
- if text != 'success':
2536
- self.throw_broadly_matched_exception(self.exceptions['broad'], text, text)
2537
- transaction = self.parse_transaction(response, currency)
2538
- return self.extend(transaction, {
2539
- 'address': address,
2540
- })
2541
-
2542
- def fetch_positions(self, symbols: Strings = None, params={}):
2543
- """
2544
- fetch all open positions
2545
- :see: https://docs.bitfinex.com/reference/rest-auth-positions
2546
- :param str[]|None symbols: list of unified market symbols
2547
- :param dict [params]: extra parameters specific to the exchange API endpoint
2548
- :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2549
- """
2550
- self.load_markets()
2551
- symbols = self.market_symbols(symbols)
2552
- response = self.privatePostAuthRPositions(params)
2553
- #
2554
- # [
2555
- # [
2556
- # "tBTCUSD", # SYMBOL
2557
- # "ACTIVE", # STATUS
2558
- # 0.0195, # AMOUNT
2559
- # 8565.0267019, # BASE_PRICE
2560
- # 0, # MARGIN_FUNDING
2561
- # 0, # MARGIN_FUNDING_TYPE
2562
- # -0.33455568705000516, # PL
2563
- # -0.0003117550117425625, # PL_PERC
2564
- # 7045.876419249083, # PRICE_LIQ
2565
- # 3.0673001895895604, # LEVERAGE
2566
- # null, # _PLACEHOLDER
2567
- # 142355652, # POSITION_ID
2568
- # 1574002216000, # MTS_CREATE
2569
- # 1574002216000, # MTS_UPDATE
2570
- # null, # _PLACEHOLDER
2571
- # 0, # TYPE
2572
- # null, # _PLACEHOLDER
2573
- # 0, # COLLATERAL
2574
- # 0, # COLLATERAL_MIN
2575
- # # META
2576
- # {
2577
- # "reason":"TRADE",
2578
- # "order_id":34271018124,
2579
- # "liq_stage":null,
2580
- # "trade_price":"8565.0267019",
2581
- # "trade_amount":"0.0195",
2582
- # "order_id_oppo":34277498022
2583
- # }
2584
- # ]
2585
- # ]
2586
- #
2587
- positionsList = []
2588
- for i in range(0, len(response)):
2589
- positionsList.append({'result': response[i]})
2590
- return self.parse_positions(positionsList, symbols)
2591
-
2592
- def parse_position(self, position: dict, market: Market = None):
2593
- #
2594
- # [
2595
- # "tBTCUSD", # SYMBOL
2596
- # "ACTIVE", # STATUS
2597
- # 0.0195, # AMOUNT
2598
- # 8565.0267019, # BASE_PRICE
2599
- # 0, # MARGIN_FUNDING
2600
- # 0, # MARGIN_FUNDING_TYPE
2601
- # -0.33455568705000516, # PL
2602
- # -0.0003117550117425625, # PL_PERC
2603
- # 7045.876419249083, # PRICE_LIQ
2604
- # 3.0673001895895604, # LEVERAGE
2605
- # null, # _PLACEHOLDER
2606
- # 142355652, # POSITION_ID
2607
- # 1574002216000, # MTS_CREATE
2608
- # 1574002216000, # MTS_UPDATE
2609
- # null, # _PLACEHOLDER
2610
- # 0, # TYPE
2611
- # null, # _PLACEHOLDER
2612
- # 0, # COLLATERAL
2613
- # 0, # COLLATERAL_MIN
2614
- # # META
2615
- # {
2616
- # "reason": "TRADE",
2617
- # "order_id": 34271018124,
2618
- # "liq_stage": null,
2619
- # "trade_price": "8565.0267019",
2620
- # "trade_amount": "0.0195",
2621
- # "order_id_oppo": 34277498022
2622
- # }
2623
- # ]
2624
- #
2625
- positionList = self.safe_list(position, 'result')
2626
- marketId = self.safe_string(positionList, 0)
2627
- amount = self.safe_string(positionList, 2)
2628
- timestamp = self.safe_integer(positionList, 12)
2629
- meta = self.safe_string(positionList, 19)
2630
- tradePrice = self.safe_string(meta, 'trade_price')
2631
- tradeAmount = self.safe_string(meta, 'trade_amount')
2632
- return self.safe_position({
2633
- 'info': positionList,
2634
- 'id': self.safe_string(positionList, 11),
2635
- 'symbol': self.safe_symbol(marketId, market),
2636
- 'notional': self.parse_number(amount),
2637
- 'marginMode': 'isolated', # derivatives use isolated, margin uses cross, https://support.bitfinex.com/hc/en-us/articles/360035475374-Derivatives-Trading-on-Bitfinex
2638
- 'liquidationPrice': self.safe_number(positionList, 8),
2639
- 'entryPrice': self.safe_number(positionList, 3),
2640
- 'unrealizedPnl': self.safe_number(positionList, 6),
2641
- 'percentage': self.safe_number(positionList, 7),
2642
- 'contracts': None,
2643
- 'contractSize': None,
2644
- 'markPrice': None,
2645
- 'lastPrice': None,
2646
- 'side': 'long' if Precise.string_gt(amount, '0') else 'short',
2647
- 'hedged': None,
2648
- 'timestamp': timestamp,
2649
- 'datetime': self.iso8601(timestamp),
2650
- 'lastUpdateTimestamp': self.safe_integer(positionList, 13),
2651
- 'maintenanceMargin': self.safe_number(positionList, 18),
2652
- 'maintenanceMarginPercentage': None,
2653
- 'collateral': self.safe_number(positionList, 17),
2654
- 'initialMargin': self.parse_number(Precise.string_mul(tradeAmount, tradePrice)),
2655
- 'initialMarginPercentage': None,
2656
- 'leverage': self.safe_number(positionList, 9),
2657
- 'marginRatio': None,
2658
- 'stopLossPrice': None,
2659
- 'takeProfitPrice': None,
2660
- })
2661
-
2662
- def nonce(self):
2663
- return self.milliseconds()
2664
-
2665
- def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2666
- request = '/' + self.implode_params(path, params)
2667
- query = self.omit(params, self.extract_params(path))
2668
- if api == 'v1':
2669
- request = api + request
2670
- else:
2671
- request = self.version + request
2672
- url = self.urls['api'][api] + '/' + request
2673
- if api == 'public':
2674
- if query:
2675
- url += '?' + self.urlencode(query)
2676
- if api == 'private':
2677
- self.check_required_credentials()
2678
- nonce = str(self.nonce())
2679
- body = self.json(query)
2680
- auth = '/api/' + request + nonce + body
2681
- signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha384)
2682
- headers = {
2683
- 'bfx-nonce': nonce,
2684
- 'bfx-apikey': self.apiKey,
2685
- 'bfx-signature': signature,
2686
- 'Content-Type': 'application/json',
2687
- }
2688
- return {'url': url, 'method': method, 'body': body, 'headers': headers}
2689
-
2690
- def handle_errors(self, statusCode, statusText, url, method, headers, body, response, requestHeaders, requestBody):
2691
- # ["error", 11010, "ratelimit: error"]
2692
- if response is not None:
2693
- if not isinstance(response, list):
2694
- message = self.safe_string_2(response, 'message', 'error')
2695
- feedback = self.id + ' ' + body
2696
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2697
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2698
- raise ExchangeError(self.id + ' ' + body)
2699
- elif response == '':
2700
- raise ExchangeError(self.id + ' returned empty response')
2701
- if statusCode == 429:
2702
- raise RateLimitExceeded(self.id + ' ' + body)
2703
- if statusCode == 500:
2704
- # See https://docs.bitfinex.com/docs/abbreviations-glossary#section-errorinfo-codes
2705
- errorCode = self.safe_string(response, 1, '')
2706
- errorText = self.safe_string(response, 2, '')
2707
- feedback = self.id + ' ' + errorText
2708
- self.throw_broadly_matched_exception(self.exceptions['broad'], errorText, feedback)
2709
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
2710
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorText, feedback)
2711
- raise ExchangeError(self.id + ' ' + errorText + '(#' + errorCode + ')')
2712
- return response
2713
-
2714
- def parse_ledger_entry_type(self, type: Str):
2715
- if type is None:
2716
- return None
2717
- elif type.find('fee') >= 0 or type.find('charged') >= 0:
2718
- return 'fee'
2719
- elif type.find('rebate') >= 0:
2720
- return 'rebate'
2721
- elif type.find('deposit') >= 0 or type.find('withdrawal') >= 0:
2722
- return 'transaction'
2723
- elif type.find('transfer') >= 0:
2724
- return 'transfer'
2725
- elif type.find('payment') >= 0:
2726
- return 'payout'
2727
- elif type.find('exchange') >= 0 or type.find('position') >= 0:
2728
- return 'trade'
2729
- else:
2730
- return type
2731
-
2732
- def parse_ledger_entry(self, item: dict, currency: Currency = None):
2733
- #
2734
- # [
2735
- # [
2736
- # 2531822314, # ID: Ledger identifier
2737
- # "USD", # CURRENCY: The symbol of the currency(ex. "BTC")
2738
- # null, # PLACEHOLDER
2739
- # 1573521810000, # MTS: Timestamp in milliseconds
2740
- # null, # PLACEHOLDER
2741
- # 0.01644445, # AMOUNT: Amount of funds moved
2742
- # 0, # BALANCE: New balance
2743
- # null, # PLACEHOLDER
2744
- # "Settlement @ 185.79 on wallet margin" # DESCRIPTION: Description of ledger transaction
2745
- # ]
2746
- # ]
2747
- #
2748
- itemList = self.safe_list(item, 'result', [])
2749
- type = None
2750
- id = self.safe_string(itemList, 0)
2751
- currencyId = self.safe_string(itemList, 1)
2752
- code = self.safe_currency_code(currencyId, currency)
2753
- timestamp = self.safe_integer(itemList, 3)
2754
- amount = self.safe_number(itemList, 5)
2755
- after = self.safe_number(itemList, 6)
2756
- description = self.safe_string(itemList, 8)
2757
- if description is not None:
2758
- parts = description.split(' @ ')
2759
- first = self.safe_string_lower(parts, 0)
2760
- type = self.parse_ledger_entry_type(first)
2761
- return {
2762
- 'id': id,
2763
- 'direction': None,
2764
- 'account': None,
2765
- 'referenceId': id,
2766
- 'referenceAccount': None,
2767
- 'type': type,
2768
- 'currency': code,
2769
- 'amount': amount,
2770
- 'timestamp': timestamp,
2771
- 'datetime': self.iso8601(timestamp),
2772
- 'before': None,
2773
- 'after': after,
2774
- 'status': None,
2775
- 'fee': None,
2776
- 'info': item,
2777
- }
2778
-
2779
- def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
2780
- """
2781
- fetch the history of changes, actions done by the user or operations that altered balance of the user
2782
- :see: https://docs.bitfinex.com/reference/rest-auth-ledgers
2783
- :param str code: unified currency code, default is None
2784
- :param int [since]: timestamp in ms of the earliest ledger entry, default is None
2785
- :param int [limit]: max number of ledger entrys to return, default is None max is 2500
2786
- :param dict [params]: extra parameters specific to the exchange API endpoint
2787
- :param int [params.until]: timestamp in ms of the latest ledger entry
2788
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2789
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
2790
- """
2791
- self.load_markets()
2792
- paginate = False
2793
- paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
2794
- if paginate:
2795
- return self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params, 2500)
2796
- currency = None
2797
- request: dict = {}
2798
- if since is not None:
2799
- request['start'] = since
2800
- if limit is not None:
2801
- request['limit'] = limit
2802
- request, params = self.handle_until_option('end', request, params)
2803
- response = None
2804
- if code is not None:
2805
- currency = self.currency(code)
2806
- request['currency'] = currency['uppercaseId']
2807
- response = self.privatePostAuthRLedgersCurrencyHist(self.extend(request, params))
2808
- else:
2809
- response = self.privatePostAuthRLedgersHist(self.extend(request, params))
2810
- #
2811
- # [
2812
- # [
2813
- # 2531822314, # ID: Ledger identifier
2814
- # "USD", # CURRENCY: The symbol of the currency(ex. "BTC")
2815
- # null, # PLACEHOLDER
2816
- # 1573521810000, # MTS: Timestamp in milliseconds
2817
- # null, # PLACEHOLDER
2818
- # 0.01644445, # AMOUNT: Amount of funds moved
2819
- # 0, # BALANCE: New balance
2820
- # null, # PLACEHOLDER
2821
- # "Settlement @ 185.79 on wallet margin" # DESCRIPTION: Description of ledger transaction
2822
- # ]
2823
- # ]
2824
- #
2825
- ledgerObjects = []
2826
- for i in range(0, len(response)):
2827
- item = response[i]
2828
- ledgerObjects.append({'result': item})
2829
- return self.parse_ledger(ledgerObjects, currency, since, limit)
2830
-
2831
- def fetch_funding_rate(self, symbol: str, params={}):
2832
- """
2833
- fetch the current funding rate
2834
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
2835
- :param str symbol: unified market symbol
2836
- :param dict [params]: extra parameters specific to the exchange API endpoint
2837
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2838
- """
2839
- return self.fetch_funding_rates([symbol], params)
2840
-
2841
- def fetch_funding_rates(self, symbols: Strings = None, params={}):
2842
- """
2843
- fetch the current funding rate
2844
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
2845
- :param str[] symbols: list of unified market symbols
2846
- :param dict [params]: extra parameters specific to the exchange API endpoint
2847
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2848
- """
2849
- if symbols is None:
2850
- raise ArgumentsRequired(self.id + ' fetchFundingRates() requires a symbols argument')
2851
- self.load_markets()
2852
- marketIds = self.market_ids(symbols)
2853
- request: dict = {
2854
- 'keys': ','.join(marketIds),
2855
- }
2856
- response = self.publicGetStatusDeriv(self.extend(request, params))
2857
- #
2858
- # [
2859
- # [
2860
- # "tBTCF0:USTF0",
2861
- # 1691165059000,
2862
- # null,
2863
- # 29297.851276225,
2864
- # 29277.5,
2865
- # null,
2866
- # 36950860.76010306,
2867
- # null,
2868
- # 1691193600000,
2869
- # 0.00000527,
2870
- # 82,
2871
- # null,
2872
- # 0.00014548,
2873
- # null,
2874
- # null,
2875
- # 29278.8925,
2876
- # null,
2877
- # null,
2878
- # 9636.07644994,
2879
- # null,
2880
- # null,
2881
- # null,
2882
- # 0.0005,
2883
- # 0.0025
2884
- # ]
2885
- # ]
2886
- #
2887
- return self.parse_funding_rates(response)
2888
-
2889
- def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2890
- """
2891
- fetches historical funding rate prices
2892
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status-history
2893
- :param str symbol: unified market symbol
2894
- :param int [since]: timestamp in ms of the earliest funding rate entry
2895
- :param int [limit]: max number of funding rate entrys to return
2896
- :param dict [params]: extra parameters specific to the exchange API endpoint
2897
- :param int [params.until]: timestamp in ms of the latest funding rate
2898
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2899
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2900
- """
2901
- if symbol is None:
2902
- raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
2903
- self.load_markets()
2904
- paginate = False
2905
- paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2906
- if paginate:
2907
- return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 5000)
2908
- market = self.market(symbol)
2909
- request: dict = {
2910
- 'symbol': market['id'],
2911
- }
2912
- if since is not None:
2913
- request['start'] = since
2914
- request, params = self.handle_until_option('end', request, params)
2915
- response = self.publicGetStatusDerivSymbolHist(self.extend(request, params))
2916
- #
2917
- # [
2918
- # [
2919
- # "tBTCF0:USTF0",
2920
- # 1691165059000,
2921
- # null,
2922
- # 29297.851276225,
2923
- # 29277.5,
2924
- # null,
2925
- # 36950860.76010306,
2926
- # null,
2927
- # 1691193600000,
2928
- # 0.00000527,
2929
- # 82,
2930
- # null,
2931
- # 0.00014548,
2932
- # null,
2933
- # null,
2934
- # 29278.8925,
2935
- # null,
2936
- # null,
2937
- # 9636.07644994,
2938
- # null,
2939
- # null,
2940
- # null,
2941
- # 0.0005,
2942
- # 0.0025
2943
- # ]
2944
- # ]
2945
- #
2946
- rates = []
2947
- for i in range(0, len(response)):
2948
- fr = response[i]
2949
- rate = self.parse_funding_rate_history(fr, market)
2950
- rates.append(rate)
2951
- reversedArray = []
2952
- rawRates = self.filter_by_symbol_since_limit(rates, symbol, since, limit)
2953
- ratesLength = len(rawRates)
2954
- for i in range(0, ratesLength):
2955
- index = ratesLength - i - 1
2956
- valueAtIndex = rawRates[index]
2957
- reversedArray.append(valueAtIndex)
2958
- return reversedArray
2959
-
2960
- def parse_funding_rate(self, contract, market: Market = None):
2961
- #
2962
- # [
2963
- # "tBTCF0:USTF0",
2964
- # 1691165059000,
2965
- # null,
2966
- # 29297.851276225,
2967
- # 29277.5,
2968
- # null,
2969
- # 36950860.76010306,
2970
- # null,
2971
- # 1691193600000,
2972
- # 0.00000527,
2973
- # 82,
2974
- # null,
2975
- # 0.00014548,
2976
- # null,
2977
- # null,
2978
- # 29278.8925,
2979
- # null,
2980
- # null,
2981
- # 9636.07644994,
2982
- # null,
2983
- # null,
2984
- # null,
2985
- # 0.0005,
2986
- # 0.0025
2987
- # ]
2988
- #
2989
- marketId = self.safe_string(contract, 0)
2990
- timestamp = self.safe_integer(contract, 1)
2991
- nextFundingTimestamp = self.safe_integer(contract, 8)
2992
- return {
2993
- 'info': contract,
2994
- 'symbol': self.safe_symbol(marketId, market),
2995
- 'markPrice': self.safe_number(contract, 15),
2996
- 'indexPrice': self.safe_number(contract, 3),
2997
- 'interestRate': None,
2998
- 'estimatedSettlePrice': None,
2999
- 'timestamp': timestamp,
3000
- 'datetime': self.iso8601(timestamp),
3001
- 'fundingRate': self.safe_number(contract, 12),
3002
- 'fundingTimestamp': None,
3003
- 'fundingDatetime': None,
3004
- 'nextFundingRate': self.safe_number(contract, 9),
3005
- 'nextFundingTimestamp': nextFundingTimestamp,
3006
- 'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
3007
- 'previousFundingRate': None,
3008
- 'previousFundingTimestamp': None,
3009
- 'previousFundingDatetime': None,
3010
- }
3011
-
3012
- def parse_funding_rate_history(self, contract, market: Market = None):
3013
- #
3014
- # [
3015
- # 1691165494000,
3016
- # null,
3017
- # 29278.95838065,
3018
- # 29260.5,
3019
- # null,
3020
- # 36950860.76010305,
3021
- # null,
3022
- # 1691193600000,
3023
- # 0.00001449,
3024
- # 222,
3025
- # null,
3026
- # 0.00014548,
3027
- # null,
3028
- # null,
3029
- # 29260.005,
3030
- # null,
3031
- # null,
3032
- # 9635.86484562,
3033
- # null,
3034
- # null,
3035
- # null,
3036
- # 0.0005,
3037
- # 0.0025
3038
- # ]
3039
- #
3040
- timestamp = self.safe_integer(contract, 0)
3041
- nextFundingTimestamp = self.safe_integer(contract, 7)
3042
- return {
3043
- 'info': contract,
3044
- 'symbol': self.safe_symbol(None, market),
3045
- 'markPrice': self.safe_number(contract, 14),
3046
- 'indexPrice': self.safe_number(contract, 2),
3047
- 'interestRate': None,
3048
- 'estimatedSettlePrice': None,
3049
- 'timestamp': timestamp,
3050
- 'datetime': self.iso8601(timestamp),
3051
- 'fundingRate': self.safe_number(contract, 11),
3052
- 'fundingTimestamp': None,
3053
- 'fundingDatetime': None,
3054
- 'nextFundingRate': self.safe_number(contract, 8),
3055
- 'nextFundingTimestamp': nextFundingTimestamp,
3056
- 'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
3057
- 'previousFundingRate': None,
3058
- 'previousFundingTimestamp': None,
3059
- 'previousFundingDatetime': None,
3060
- }
3061
-
3062
- def fetch_open_interest(self, symbol: str, params={}):
3063
- """
3064
- retrieves the open interest of a contract trading pair
3065
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
3066
- :param str symbol: unified CCXT market symbol
3067
- :param dict [params]: exchange specific parameters
3068
- :returns dict: an `open interest structure <https://docs.ccxt.com/#/?id=open-interest-structure>`
3069
- """
3070
- self.load_markets()
3071
- market = self.market(symbol)
3072
- request: dict = {
3073
- 'keys': market['id'],
3074
- }
3075
- response = self.publicGetStatusDeriv(self.extend(request, params))
3076
- #
3077
- # [
3078
- # [
3079
- # "tXRPF0:USTF0", # market id
3080
- # 1706256986000, # millisecond timestamp
3081
- # null,
3082
- # 0.512705, # derivative mid price
3083
- # 0.512395, # underlying spot mid price
3084
- # null,
3085
- # 37671483.04, # insurance fund balance
3086
- # null,
3087
- # 1706284800000, # timestamp of next funding
3088
- # 0.00002353, # accrued funding for next period
3089
- # 317, # next funding step
3090
- # null,
3091
- # 0, # current funding
3092
- # null,
3093
- # null,
3094
- # 0.5123016, # mark price
3095
- # null,
3096
- # null,
3097
- # 2233562.03115, # open interest in contracts
3098
- # null,
3099
- # null,
3100
- # null,
3101
- # 0.0005, # average spread without funding payment
3102
- # 0.0025 # funding payment cap
3103
- # ]
3104
- # ]
3105
- #
3106
- oi = self.safe_list(response, 0)
3107
- return self.parse_open_interest(oi, market)
3108
-
3109
- def fetch_open_interest_history(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
3110
- """
3111
- retrieves the open interest history of a currency
3112
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status-history
3113
- :param str symbol: unified CCXT market symbol
3114
- :param str timeframe: the time period of each row of data, not used by bitfinex2
3115
- :param int [since]: the time in ms of the earliest record to retrieve unix timestamp
3116
- :param int [limit]: the number of records in the response
3117
- :param dict [params]: exchange specific parameters
3118
- :param int [params.until]: the time in ms of the latest record to retrieve unix timestamp
3119
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3120
- :returns: An array of `open interest structures <https://docs.ccxt.com/#/?id=open-interest-structure>`
3121
- """
3122
- self.load_markets()
3123
- paginate = False
3124
- paginate, params = self.handle_option_and_params(params, 'fetchOpenInterestHistory', 'paginate')
3125
- if paginate:
3126
- return self.fetch_paginated_call_deterministic('fetchOpenInterestHistory', symbol, since, limit, '8h', params, 5000)
3127
- market = self.market(symbol)
3128
- request: dict = {
3129
- 'symbol': market['id'],
3130
- }
3131
- if since is not None:
3132
- request['start'] = since
3133
- if limit is not None:
3134
- request['limit'] = limit
3135
- request, params = self.handle_until_option('end', request, params)
3136
- response = self.publicGetStatusDerivSymbolHist(self.extend(request, params))
3137
- #
3138
- # [
3139
- # [
3140
- # 1706295191000, # timestamp
3141
- # null,
3142
- # 42152.425382, # derivative mid price
3143
- # 42133, # spot mid price
3144
- # null,
3145
- # 37671589.7853521, # insurance fund balance
3146
- # null,
3147
- # 1706313600000, # timestamp of next funding
3148
- # 0.00018734, # accrued funding for next period
3149
- # 3343, # next funding step
3150
- # null,
3151
- # 0.00007587, # current funding
3152
- # null,
3153
- # null,
3154
- # 42134.1, # mark price
3155
- # null,
3156
- # null,
3157
- # 5775.20348804, # open interest number of contracts
3158
- # null,
3159
- # null,
3160
- # null,
3161
- # 0.0005, # average spread without funding payment
3162
- # 0.0025 # funding payment cap
3163
- # ],
3164
- # ]
3165
- #
3166
- return self.parse_open_interests(response, market, since, limit)
3167
-
3168
- def parse_open_interest(self, interest, market: Market = None):
3169
- #
3170
- # fetchOpenInterest:
3171
- #
3172
- # [
3173
- # "tXRPF0:USTF0", # market id
3174
- # 1706256986000, # millisecond timestamp
3175
- # null,
3176
- # 0.512705, # derivative mid price
3177
- # 0.512395, # underlying spot mid price
3178
- # null,
3179
- # 37671483.04, # insurance fund balance
3180
- # null,
3181
- # 1706284800000, # timestamp of next funding
3182
- # 0.00002353, # accrued funding for next period
3183
- # 317, # next funding step
3184
- # null,
3185
- # 0, # current funding
3186
- # null,
3187
- # null,
3188
- # 0.5123016, # mark price
3189
- # null,
3190
- # null,
3191
- # 2233562.03115, # open interest in contracts
3192
- # null,
3193
- # null,
3194
- # null,
3195
- # 0.0005, # average spread without funding payment
3196
- # 0.0025 # funding payment cap
3197
- # ]
3198
- #
3199
- # fetchOpenInterestHistory:
3200
- #
3201
- # [
3202
- # 1706295191000, # timestamp
3203
- # null,
3204
- # 42152.425382, # derivative mid price
3205
- # 42133, # spot mid price
3206
- # null,
3207
- # 37671589.7853521, # insurance fund balance
3208
- # null,
3209
- # 1706313600000, # timestamp of next funding
3210
- # 0.00018734, # accrued funding for next period
3211
- # 3343, # next funding step
3212
- # null,
3213
- # 0.00007587, # current funding
3214
- # null,
3215
- # null,
3216
- # 42134.1, # mark price
3217
- # null,
3218
- # null,
3219
- # 5775.20348804, # open interest number of contracts
3220
- # null,
3221
- # null,
3222
- # null,
3223
- # 0.0005, # average spread without funding payment
3224
- # 0.0025 # funding payment cap
3225
- # ]
3226
- #
3227
- interestLength = len(interest)
3228
- openInterestIndex = 17 if (interestLength == 23) else 18
3229
- timestamp = self.safe_integer(interest, 1)
3230
- marketId = self.safe_string(interest, 0)
3231
- return self.safe_open_interest({
3232
- 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
3233
- 'openInterestAmount': self.safe_number(interest, openInterestIndex),
3234
- 'openInterestValue': None,
3235
- 'timestamp': timestamp,
3236
- 'datetime': self.iso8601(timestamp),
3237
- 'info': interest,
3238
- }, market)
3239
-
3240
- def fetch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
3241
- """
3242
- retrieves the public liquidations of a trading pair
3243
- :see: https://docs.bitfinex.com/reference/rest-public-liquidations
3244
- :param str symbol: unified CCXT market symbol
3245
- :param int [since]: the earliest time in ms to fetch liquidations for
3246
- :param int [limit]: the maximum number of liquidation structures to retrieve
3247
- :param dict [params]: exchange specific parameters
3248
- :param int [params.until]: timestamp in ms of the latest liquidation
3249
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3250
- :returns dict: an array of `liquidation structures <https://docs.ccxt.com/#/?id=liquidation-structure>`
3251
- """
3252
- self.load_markets()
3253
- paginate = False
3254
- paginate, params = self.handle_option_and_params(params, 'fetchLiquidations', 'paginate')
3255
- if paginate:
3256
- return self.fetch_paginated_call_deterministic('fetchLiquidations', symbol, since, limit, '8h', params, 500)
3257
- market = self.market(symbol)
3258
- request: dict = {}
3259
- if since is not None:
3260
- request['start'] = since
3261
- if limit is not None:
3262
- request['limit'] = limit
3263
- request, params = self.handle_until_option('end', request, params)
3264
- response = self.publicGetLiquidationsHist(self.extend(request, params))
3265
- #
3266
- # [
3267
- # [
3268
- # [
3269
- # "pos",
3270
- # 171085137,
3271
- # 1706395919788,
3272
- # null,
3273
- # "tAVAXF0:USTF0",
3274
- # -8,
3275
- # 32.868,
3276
- # null,
3277
- # 1,
3278
- # 1,
3279
- # null,
3280
- # 33.255
3281
- # ]
3282
- # ],
3283
- # ]
3284
- #
3285
- return self.parse_liquidations(response, market, since, limit)
3286
-
3287
- def parse_liquidation(self, liquidation, market: Market = None):
3288
- #
3289
- # [
3290
- # [
3291
- # "pos",
3292
- # 171085137, # position id
3293
- # 1706395919788, # timestamp
3294
- # null,
3295
- # "tAVAXF0:USTF0", # market id
3296
- # -8, # amount in contracts
3297
- # 32.868, # base price
3298
- # null,
3299
- # 1,
3300
- # 1,
3301
- # null,
3302
- # 33.255 # acquired price
3303
- # ]
3304
- # ]
3305
- #
3306
- entry = liquidation[0]
3307
- timestamp = self.safe_integer(entry, 2)
3308
- marketId = self.safe_string(entry, 4)
3309
- contracts = Precise.string_abs(self.safe_string(entry, 5))
3310
- contractSize = self.safe_string(market, 'contractSize')
3311
- baseValue = Precise.string_mul(contracts, contractSize)
3312
- price = self.safe_string(entry, 11)
3313
- return self.safe_liquidation({
3314
- 'info': entry,
3315
- 'symbol': self.safe_symbol(marketId, market, None, 'contract'),
3316
- 'contracts': self.parse_number(contracts),
3317
- 'contractSize': self.parse_number(contractSize),
3318
- 'price': self.parse_number(price),
3319
- 'baseValue': self.parse_number(baseValue),
3320
- 'quoteValue': self.parse_number(Precise.string_mul(baseValue, price)),
3321
- 'timestamp': timestamp,
3322
- 'datetime': self.iso8601(timestamp),
3323
- })
3324
-
3325
- def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3326
- """
3327
- either adds or reduces margin in a swap position in order to set the margin to a specific value
3328
- :see: https://docs.bitfinex.com/reference/rest-auth-deriv-pos-collateral-set
3329
- :param str symbol: unified market symbol of the market to set margin in
3330
- :param float amount: the amount to set the margin to
3331
- :param dict [params]: parameters specific to the exchange API endpoint
3332
- :returns dict: A `margin structure <https://github.com/ccxt/ccxt/wiki/Manual#add-margin-structure>`
3333
- """
3334
- self.load_markets()
3335
- market = self.market(symbol)
3336
- if not market['swap']:
3337
- raise NotSupported(self.id + ' setMargin() only support swap markets')
3338
- request: dict = {
3339
- 'symbol': market['id'],
3340
- 'collateral': self.parse_to_numeric(amount),
3341
- }
3342
- response = self.privatePostAuthWDerivCollateralSet(self.extend(request, params))
3343
- #
3344
- # [
3345
- # [
3346
- # 1
3347
- # ]
3348
- # ]
3349
- #
3350
- data = self.safe_value(response, 0)
3351
- return self.parse_margin_modification(data, market)
3352
-
3353
- def parse_margin_modification(self, data, market=None) -> MarginModification:
3354
- #
3355
- # setMargin
3356
- #
3357
- # [
3358
- # [
3359
- # 1
3360
- # ]
3361
- # ]
3362
- #
3363
- marginStatusRaw = data[0]
3364
- marginStatus = 'ok' if (marginStatusRaw == 1) else 'failed'
3365
- return {
3366
- 'info': data,
3367
- 'symbol': market['symbol'],
3368
- 'type': None,
3369
- 'marginMode': 'isolated',
3370
- 'amount': None,
3371
- 'total': None,
3372
- 'code': None,
3373
- 'status': marginStatus,
3374
- 'timestamp': None,
3375
- 'datetime': None,
3376
- }
3377
-
3378
- def fetch_order(self, id: str, symbol: Str = None, params={}):
3379
- """
3380
- fetches information on an order made by the user
3381
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
3382
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
3383
- :param str id: the order id
3384
- :param str [symbol]: unified symbol of the market the order was made in
3385
- :param dict [params]: extra parameters specific to the exchange API endpoint
3386
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3387
- """
3388
- self.load_markets()
3389
- request: dict = {
3390
- 'id': [self.parse_to_numeric(id)],
3391
- }
3392
- market = None
3393
- response = None
3394
- if symbol is None:
3395
- response = self.privatePostAuthROrders(self.extend(request, params))
3396
- else:
3397
- market = self.market(symbol)
3398
- request['symbol'] = market['id']
3399
- response = self.privatePostAuthROrdersSymbol(self.extend(request, params))
3400
- #
3401
- # [
3402
- # [
3403
- # 139658969116,
3404
- # null,
3405
- # 1706843908637,
3406
- # "tBTCUST",
3407
- # 1706843908637,
3408
- # 1706843908638,
3409
- # 0.0001,
3410
- # 0.0001,
3411
- # "EXCHANGE LIMIT",
3412
- # null,
3413
- # null,
3414
- # null,
3415
- # 0,
3416
- # "ACTIVE",
3417
- # null,
3418
- # null,
3419
- # 35000,
3420
- # 0,
3421
- # 0,
3422
- # 0,
3423
- # null,
3424
- # null,
3425
- # null,
3426
- # 0,
3427
- # 0,
3428
- # null,
3429
- # null,
3430
- # null,
3431
- # "API>BFX",
3432
- # null,
3433
- # null,
3434
- # {}
3435
- # ]
3436
- # ]
3437
- #
3438
- order = self.safe_list(response, 0)
3439
- return self.parse_order(order, market)
3440
-
3441
- def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
3442
- """
3443
- edit a trade order
3444
- :see: https://docs.bitfinex.com/reference/rest-auth-update-order
3445
- :param str id: edit order id
3446
- :param str symbol: unified symbol of the market to edit an order in
3447
- :param str type: 'market' or 'limit'
3448
- :param str side: 'buy' or 'sell'
3449
- :param float amount: how much you want to trade in units of the base currency
3450
- :param float [price]: the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
3451
- :param dict [params]: extra parameters specific to the exchange API endpoint
3452
- :param float [params.stopPrice]: the price that triggers a trigger order
3453
- :param boolean [params.postOnly]: set to True if you want to make a post only order
3454
- :param boolean [params.reduceOnly]: indicates that the order is to reduce the size of a position
3455
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
3456
- :param int [params.leverage]: leverage for a derivative order, supported by derivative symbol orders only, the value should be between 1 and 100 inclusive
3457
- :param int [params.clientOrderId]: a unique client order id for the order
3458
- :param float [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
3459
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3460
- """
3461
- self.load_markets()
3462
- market = self.market(symbol)
3463
- request: dict = {
3464
- 'id': self.parse_to_numeric(id),
3465
- }
3466
- if amount is not None:
3467
- amountString = self.amount_to_precision(symbol, amount)
3468
- amountString = amountString if (side == 'buy') else Precise.string_neg(amountString)
3469
- request['amount'] = amountString
3470
- stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
3471
- trailingAmount = self.safe_string(params, 'trailingAmount')
3472
- timeInForce = self.safe_string(params, 'timeInForce')
3473
- postOnlyParam = self.safe_bool(params, 'postOnly', False)
3474
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
3475
- clientOrderId = self.safe_integer_2(params, 'cid', 'clientOrderId')
3476
- if trailingAmount is not None:
3477
- request['price_trailing'] = trailingAmount
3478
- elif stopPrice is not None:
3479
- # request['price'] is taken for stop orders
3480
- request['price'] = self.price_to_precision(symbol, stopPrice)
3481
- if type == 'limit':
3482
- request['price_aux_limit'] = self.price_to_precision(symbol, price)
3483
- postOnly = (postOnlyParam or (timeInForce == 'PO'))
3484
- if (type != 'market') and (stopPrice is None):
3485
- request['price'] = self.price_to_precision(symbol, price)
3486
- # flag values may be summed to combine flags
3487
- flags = 0
3488
- if postOnly:
3489
- flags = self.sum(flags, 4096)
3490
- if reduceOnly:
3491
- flags = self.sum(flags, 1024)
3492
- if flags != 0:
3493
- request['flags'] = flags
3494
- if clientOrderId is not None:
3495
- request['cid'] = clientOrderId
3496
- leverage = self.safe_integer_2(params, 'leverage', 'lev')
3497
- if leverage is not None:
3498
- request['lev'] = leverage
3499
- params = self.omit(params, ['triggerPrice', 'stopPrice', 'timeInForce', 'postOnly', 'reduceOnly', 'trailingAmount', 'clientOrderId', 'leverage'])
3500
- response = self.privatePostAuthWOrderUpdate(self.extend(request, params))
3501
- #
3502
- # [
3503
- # 1706845376402,
3504
- # "ou-req",
3505
- # null,
3506
- # null,
3507
- # [
3508
- # 139658969116,
3509
- # null,
3510
- # 1706843908637,
3511
- # "tBTCUST",
3512
- # 1706843908637,
3513
- # 1706843908638,
3514
- # 0.0002,
3515
- # 0.0002,
3516
- # "EXCHANGE LIMIT",
3517
- # null,
3518
- # null,
3519
- # null,
3520
- # 0,
3521
- # "ACTIVE",
3522
- # null,
3523
- # null,
3524
- # 35000,
3525
- # 0,
3526
- # 0,
3527
- # 0,
3528
- # null,
3529
- # null,
3530
- # null,
3531
- # 0,
3532
- # 0,
3533
- # null,
3534
- # null,
3535
- # null,
3536
- # "API>BFX",
3537
- # null,
3538
- # null,
3539
- # {}
3540
- # ],
3541
- # null,
3542
- # "SUCCESS",
3543
- # "Submitting update to exchange limit buy order for 0.0002 BTC."
3544
- # ]
3545
- #
3546
- status = self.safe_string(response, 6)
3547
- if status != 'SUCCESS':
3548
- errorCode = response[5]
3549
- errorText = response[7]
3550
- raise ExchangeError(self.id + ' ' + response[6] + ': ' + errorText + '(#' + errorCode + ')')
3551
- order = self.safe_list(response, 4, [])
3552
- return self.parse_order(order, market)