ccxt 4.2.77__py2.py3-none-any.whl → 4.4.48__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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3104 -880
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1513 -563
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +206 -89
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +557 -323
  126. ccxt/async_support/digifinex.py +340 -223
  127. ccxt/async_support/ellipx.py +1826 -0
  128. ccxt/async_support/exmo.py +259 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +334 -178
  133. ccxt/async_support/hollaex.py +134 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +105 -56
  136. ccxt/async_support/hyperliquid.py +1633 -268
  137. ccxt/async_support/idex.py +148 -95
  138. ccxt/async_support/independentreserve.py +236 -31
  139. ccxt/async_support/indodax.py +165 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +138 -106
  145. ccxt/async_support/latoken.py +135 -79
  146. ccxt/async_support/lbank.py +290 -113
  147. ccxt/async_support/luno.py +112 -62
  148. ccxt/async_support/lykke.py +104 -55
  149. ccxt/async_support/mercado.py +36 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +43 -0
  152. ccxt/async_support/ndax.py +163 -82
  153. ccxt/async_support/novadax.py +121 -75
  154. ccxt/async_support/oceanex.py +175 -59
  155. ccxt/async_support/okcoin.py +222 -163
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +132 -414
  158. ccxt/async_support/oxfun.py +2832 -0
  159. ccxt/async_support/p2b.py +79 -51
  160. ccxt/async_support/paradex.py +2017 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3104 -880
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1513 -563
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +206 -89
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +557 -323
  234. ccxt/digifinex.py +340 -223
  235. ccxt/ellipx.py +1826 -0
  236. ccxt/exmo.py +259 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +334 -178
  241. ccxt/hollaex.py +134 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +105 -56
  244. ccxt/hyperliquid.py +1632 -268
  245. ccxt/idex.py +148 -95
  246. ccxt/independentreserve.py +235 -31
  247. ccxt/indodax.py +165 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +138 -106
  253. ccxt/latoken.py +135 -79
  254. ccxt/lbank.py +290 -113
  255. ccxt/luno.py +112 -62
  256. ccxt/lykke.py +104 -55
  257. ccxt/mercado.py +36 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +43 -0
  260. ccxt/ndax.py +163 -82
  261. ccxt/novadax.py +121 -75
  262. ccxt/oceanex.py +175 -59
  263. ccxt/okcoin.py +222 -163
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +132 -414
  266. ccxt/oxfun.py +2831 -0
  267. ccxt/p2b.py +79 -51
  268. ccxt/paradex.py +2017 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +138 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.48.dist-info/METADATA +646 -0
  497. ccxt-4.4.48.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
@@ -1,3496 +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.async_support.base.exchange import Exchange
7
- from ccxt.abstract.bitfinex2 import ImplicitAPI
8
- import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
- from typing import List
11
- from ccxt.base.errors import ExchangeError
12
- from ccxt.base.errors import PermissionDenied
13
- from ccxt.base.errors import ArgumentsRequired
14
- from ccxt.base.errors import BadRequest
15
- from ccxt.base.errors import BadSymbol
16
- from ccxt.base.errors import InsufficientFunds
17
- from ccxt.base.errors import InvalidAddress
18
- from ccxt.base.errors import InvalidOrder
19
- from ccxt.base.errors import OrderNotFound
20
- from ccxt.base.errors import NotSupported
21
- from ccxt.base.errors import RateLimitExceeded
22
- from ccxt.base.errors import ExchangeNotAvailable
23
- from ccxt.base.errors import OnMaintenance
24
- from ccxt.base.errors import InvalidNonce
25
- from ccxt.base.errors import AuthenticationError
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
- async 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 = await 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
- async def fetch_markets(self, params={}):
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 = await self.publicGetConfPubInfoPair(params)
519
- futuresMarketsInfo = await 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 = await 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
- async def fetch_currencies(self, params={}):
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 = {
653
- 'config': config,
654
- }
655
- response = await 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 = {
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 = {}
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 = {}
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 = {
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
- async 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
- await 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 = await self.privatePostAuthRWallets(query)
856
- result = {'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
- async 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
- await 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 = {
905
- 'amount': requestedAmount,
906
- 'currency': fromCurrencyId,
907
- 'currency_to': toCurrencyId,
908
- 'from': fromId,
909
- 'to': toId,
910
- }
911
- response = await 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(response, currency)
940
-
941
- def parse_transfer(self, transfer, currency: Currency = None):
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
- timestamp = self.safe_integer(transfer, 0)
966
- info = self.safe_value(transfer, 4)
967
- fromAccount = self.safe_string(info, 1)
968
- toAccount = self.safe_string(info, 2)
969
- currencyId = self.safe_string(info, 5)
970
- status = self.safe_string(transfer, 6)
971
- return {
972
- 'id': None,
973
- 'timestamp': timestamp,
974
- 'datetime': self.iso8601(timestamp),
975
- 'status': self.parse_transfer_status(status),
976
- 'amount': self.safe_number(info, 7),
977
- 'currency': self.safe_currency_code(currencyId, currency),
978
- 'fromAccount': fromAccount,
979
- 'toAccount': toAccount,
980
- 'info': transfer,
981
- }
982
-
983
- def parse_transfer_status(self, status):
984
- statuses = {
985
- 'SUCCESS': 'ok',
986
- 'ERROR': 'failed',
987
- 'FAILURE': 'failed',
988
- }
989
- return self.safe_string(statuses, status, status)
990
-
991
- def convert_derivatives_id(self, currency, type):
992
- # there is a difference between self and the v1 api, namely trading wallet is called margin in v2
993
- # {
994
- # "id": "fUSTF0",
995
- # "code": "USTF0",
996
- # "info": ['USTF0', [], [], [], ["USTF0", "UST"]],
997
- info = self.safe_value(currency, 'info')
998
- transferId = self.safe_string(info, 0)
999
- underlying = self.safe_value(info, 4, [])
1000
- currencyId = None
1001
- if type == 'derivatives':
1002
- currencyId = self.safe_string(underlying, 0, transferId)
1003
- start = len(currencyId) - 2
1004
- isDerivativeCode = currencyId[start:] == 'F0'
1005
- if not isDerivativeCode:
1006
- currencyId = currencyId + 'F0'
1007
- elif type != 'margin':
1008
- currencyId = self.safe_string(underlying, 1, transferId)
1009
- else:
1010
- currencyId = transferId
1011
- return currencyId
1012
-
1013
- async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1014
- """
1015
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1016
- :see: https://docs.bitfinex.com/reference/rest-public-book
1017
- :param str symbol: unified symbol of the market to fetch the order book for
1018
- :param int [limit]: the maximum amount of order book entries to return, bitfinex only allows 1, 25, or 100
1019
- :param dict [params]: extra parameters specific to the exchange API endpoint
1020
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1021
- """
1022
- await self.load_markets()
1023
- precision = self.safe_value(self.options, 'precision', 'R0')
1024
- market = self.market(symbol)
1025
- request = {
1026
- 'symbol': market['id'],
1027
- 'precision': precision,
1028
- }
1029
- if limit is not None:
1030
- request['len'] = limit
1031
- fullRequest = self.extend(request, params)
1032
- orderbook = await self.publicGetBookSymbolPrecision(fullRequest)
1033
- timestamp = self.milliseconds()
1034
- result = {
1035
- 'symbol': market['symbol'],
1036
- 'bids': [],
1037
- 'asks': [],
1038
- 'timestamp': timestamp,
1039
- 'datetime': self.iso8601(timestamp),
1040
- 'nonce': None,
1041
- }
1042
- priceIndex = 1 if (fullRequest['precision'] == 'R0') else 0
1043
- for i in range(0, len(orderbook)):
1044
- order = orderbook[i]
1045
- price = self.safe_number(order, priceIndex)
1046
- signedAmount = self.safe_string(order, 2)
1047
- amount = Precise.string_abs(signedAmount)
1048
- side = 'bids' if Precise.string_gt(signedAmount, '0') else 'asks'
1049
- result[side].append([price, self.parse_number(amount)])
1050
- result['bids'] = self.sort_by(result['bids'], 0, True)
1051
- result['asks'] = self.sort_by(result['asks'], 0)
1052
- return result
1053
-
1054
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1055
- #
1056
- # on trading pairs(ex. tBTCUSD)
1057
- #
1058
- # [
1059
- # SYMBOL,
1060
- # BID,
1061
- # BID_SIZE,
1062
- # ASK,
1063
- # ASK_SIZE,
1064
- # DAILY_CHANGE,
1065
- # DAILY_CHANGE_RELATIVE,
1066
- # LAST_PRICE,
1067
- # VOLUME,
1068
- # HIGH,
1069
- # LOW
1070
- # ]
1071
- #
1072
- # on funding currencies(ex. fUSD)
1073
- #
1074
- # [
1075
- # SYMBOL,
1076
- # FRR,
1077
- # BID,
1078
- # BID_PERIOD,
1079
- # BID_SIZE,
1080
- # ASK,
1081
- # ASK_PERIOD,
1082
- # ASK_SIZE,
1083
- # DAILY_CHANGE,
1084
- # DAILY_CHANGE_RELATIVE,
1085
- # LAST_PRICE,
1086
- # VOLUME,
1087
- # HIGH,
1088
- # LOW,
1089
- # _PLACEHOLDER,
1090
- # _PLACEHOLDER,
1091
- # FRR_AMOUNT_AVAILABLE
1092
- # ]
1093
- #
1094
- symbol = self.safe_symbol(None, market)
1095
- length = len(ticker)
1096
- last = self.safe_string(ticker, length - 4)
1097
- percentage = self.safe_string(ticker, length - 5)
1098
- return self.safe_ticker({
1099
- 'symbol': symbol,
1100
- 'timestamp': None,
1101
- 'datetime': None,
1102
- 'high': self.safe_string(ticker, length - 2),
1103
- 'low': self.safe_string(ticker, length - 1),
1104
- 'bid': self.safe_string(ticker, length - 10),
1105
- 'bidVolume': self.safe_string(ticker, length - 9),
1106
- 'ask': self.safe_string(ticker, length - 8),
1107
- 'askVolume': self.safe_string(ticker, length - 7),
1108
- 'vwap': None,
1109
- 'open': None,
1110
- 'close': last,
1111
- 'last': last,
1112
- 'previousClose': None,
1113
- 'change': self.safe_string(ticker, length - 6),
1114
- 'percentage': Precise.string_mul(percentage, '100'),
1115
- 'average': None,
1116
- 'baseVolume': self.safe_string(ticker, length - 3),
1117
- 'quoteVolume': None,
1118
- 'info': ticker,
1119
- }, market)
1120
-
1121
- async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1122
- """
1123
- fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1124
- :see: https://docs.bitfinex.com/reference/rest-public-tickers
1125
- :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1126
- :param dict [params]: extra parameters specific to the exchange API endpoint
1127
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1128
- """
1129
- await self.load_markets()
1130
- symbols = self.market_symbols(symbols)
1131
- request = {}
1132
- if symbols is not None:
1133
- ids = self.market_ids(symbols)
1134
- request['symbols'] = ','.join(ids)
1135
- else:
1136
- request['symbols'] = 'ALL'
1137
- tickers = await self.publicGetTickers(self.extend(request, params))
1138
- #
1139
- # [
1140
- # # on trading pairs(ex. tBTCUSD)
1141
- # [
1142
- # SYMBOL,
1143
- # BID,
1144
- # BID_SIZE,
1145
- # ASK,
1146
- # ASK_SIZE,
1147
- # DAILY_CHANGE,
1148
- # DAILY_CHANGE_RELATIVE,
1149
- # LAST_PRICE,
1150
- # VOLUME,
1151
- # HIGH,
1152
- # LOW
1153
- # ],
1154
- # # on funding currencies(ex. fUSD)
1155
- # [
1156
- # SYMBOL,
1157
- # FRR,
1158
- # BID,
1159
- # BID_PERIOD,
1160
- # BID_SIZE,
1161
- # ASK,
1162
- # ASK_PERIOD,
1163
- # ASK_SIZE,
1164
- # DAILY_CHANGE,
1165
- # DAILY_CHANGE_RELATIVE,
1166
- # LAST_PRICE,
1167
- # VOLUME,
1168
- # HIGH,
1169
- # LOW,
1170
- # _PLACEHOLDER,
1171
- # _PLACEHOLDER,
1172
- # FRR_AMOUNT_AVAILABLE
1173
- # ],
1174
- # ...
1175
- # ]
1176
- #
1177
- result = {}
1178
- for i in range(0, len(tickers)):
1179
- ticker = tickers[i]
1180
- marketId = self.safe_string(ticker, 0)
1181
- market = self.safe_market(marketId)
1182
- symbol = market['symbol']
1183
- result[symbol] = self.parse_ticker(ticker, market)
1184
- return self.filter_by_array_tickers(result, 'symbol', symbols)
1185
-
1186
- async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1187
- """
1188
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1189
- :see: https://docs.bitfinex.com/reference/rest-public-ticker
1190
- :param str symbol: unified symbol of the market to fetch the ticker for
1191
- :param dict [params]: extra parameters specific to the exchange API endpoint
1192
- :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1193
- """
1194
- await self.load_markets()
1195
- market = self.market(symbol)
1196
- request = {
1197
- 'symbol': market['id'],
1198
- }
1199
- ticker = await self.publicGetTickerSymbol(self.extend(request, params))
1200
- return self.parse_ticker(ticker, market)
1201
-
1202
- def parse_trade(self, trade, market: Market = None) -> Trade:
1203
- #
1204
- # fetchTrades(public)
1205
- #
1206
- # [
1207
- # ID,
1208
- # MTS, # timestamp
1209
- # AMOUNT,
1210
- # PRICE
1211
- # ]
1212
- #
1213
- # fetchMyTrades(private)
1214
- #
1215
- # [
1216
- # ID,
1217
- # PAIR,
1218
- # MTS_CREATE,
1219
- # ORDER_ID,
1220
- # EXEC_AMOUNT,
1221
- # EXEC_PRICE,
1222
- # ORDER_TYPE,
1223
- # ORDER_PRICE,
1224
- # MAKER,
1225
- # FEE,
1226
- # FEE_CURRENCY,
1227
- # ...
1228
- # ]
1229
- #
1230
- tradeLength = len(trade)
1231
- isPrivate = (tradeLength > 5)
1232
- id = self.safe_string(trade, 0)
1233
- amountIndex = 4 if isPrivate else 2
1234
- side = None
1235
- amountString = self.safe_string(trade, amountIndex)
1236
- priceIndex = 5 if isPrivate else 3
1237
- priceString = self.safe_string(trade, priceIndex)
1238
- if amountString[0] == '-':
1239
- side = 'sell'
1240
- amountString = Precise.string_abs(amountString)
1241
- else:
1242
- side = 'buy'
1243
- orderId = None
1244
- takerOrMaker = None
1245
- type = None
1246
- fee = None
1247
- symbol = self.safe_symbol(None, market)
1248
- timestampIndex = 2 if isPrivate else 1
1249
- timestamp = self.safe_integer(trade, timestampIndex)
1250
- if isPrivate:
1251
- marketId = trade[1]
1252
- symbol = self.safe_symbol(marketId)
1253
- orderId = self.safe_string(trade, 3)
1254
- maker = self.safe_integer(trade, 8)
1255
- takerOrMaker = 'maker' if (maker == 1) else 'taker'
1256
- feeCostString = self.safe_string(trade, 9)
1257
- feeCostString = Precise.string_neg(feeCostString)
1258
- feeCurrencyId = self.safe_string(trade, 10)
1259
- feeCurrency = self.safe_currency_code(feeCurrencyId)
1260
- fee = {
1261
- 'cost': feeCostString,
1262
- 'currency': feeCurrency,
1263
- }
1264
- orderType = trade[6]
1265
- type = self.safe_string(self.options['exchangeTypes'], orderType)
1266
- return self.safe_trade({
1267
- 'id': id,
1268
- 'timestamp': timestamp,
1269
- 'datetime': self.iso8601(timestamp),
1270
- 'symbol': symbol,
1271
- 'order': orderId,
1272
- 'side': side,
1273
- 'type': type,
1274
- 'takerOrMaker': takerOrMaker,
1275
- 'price': priceString,
1276
- 'amount': amountString,
1277
- 'cost': None,
1278
- 'fee': fee,
1279
- 'info': trade,
1280
- }, market)
1281
-
1282
- async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1283
- """
1284
- get the list of most recent trades for a particular symbol
1285
- :see: https://docs.bitfinex.com/reference/rest-public-trades
1286
- :param str symbol: unified symbol of the market to fetch trades for
1287
- :param int [since]: timestamp in ms of the earliest trade to fetch
1288
- :param int [limit]: the maximum amount of trades to fetch, default 120, max 10000
1289
- :param dict [params]: extra parameters specific to the exchange API endpoint
1290
- :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)
1291
- :param int [params.until]: the latest time in ms to fetch entries for
1292
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1293
- """
1294
- await self.load_markets()
1295
- paginate = False
1296
- paginate, params = self.handle_option_and_params(params, 'fetchTrades', 'paginate')
1297
- if paginate:
1298
- return await self.fetch_paginated_call_dynamic('fetchTrades', symbol, since, limit, params, 10000)
1299
- market = self.market(symbol)
1300
- sort = '-1'
1301
- request = {
1302
- 'symbol': market['id'],
1303
- }
1304
- if since is not None:
1305
- request['start'] = since
1306
- sort = '1'
1307
- if limit is not None:
1308
- request['limit'] = min(limit, 10000) # default 120, max 10000
1309
- request['sort'] = sort
1310
- request, params = self.handle_until_option('end', request, params)
1311
- response = await self.publicGetTradesSymbolHist(self.extend(request, params))
1312
- #
1313
- # [
1314
- # [
1315
- # ID,
1316
- # MTS, # timestamp
1317
- # AMOUNT,
1318
- # PRICE
1319
- # ]
1320
- # ]
1321
- #
1322
- trades = self.sort_by(response, 1)
1323
- return self.parse_trades(trades, market, None, limit)
1324
-
1325
- async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = 100, params={}) -> List[list]:
1326
- """
1327
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1328
- :see: https://docs.bitfinex.com/reference/rest-public-candles
1329
- :param str symbol: unified symbol of the market to fetch OHLCV data for
1330
- :param str timeframe: the length of time each candle represents
1331
- :param int [since]: timestamp in ms of the earliest candle to fetch
1332
- :param int [limit]: the maximum amount of candles to fetch, default 100 max 10000
1333
- :param dict [params]: extra parameters specific to the exchange API endpoint
1334
- :returns int[][]: A list of candles ordered, open, high, low, close, volume
1335
- :param int [params.until]: timestamp in ms of the latest candle to fetch
1336
- :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)
1337
- """
1338
- await self.load_markets()
1339
- paginate = False
1340
- paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
1341
- if paginate:
1342
- return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 10000)
1343
- market = self.market(symbol)
1344
- if limit is None:
1345
- limit = 10000
1346
- request = {
1347
- 'symbol': market['id'],
1348
- 'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
1349
- 'sort': 1,
1350
- 'limit': limit,
1351
- }
1352
- if since is not None:
1353
- request['start'] = since
1354
- request, params = self.handle_until_option('end', request, params)
1355
- response = await self.publicGetCandlesTradeTimeframeSymbolHist(self.extend(request, params))
1356
- #
1357
- # [
1358
- # [1591503840000,0.025069,0.025068,0.025069,0.025068,1.97828998],
1359
- # [1591504500000,0.025065,0.025065,0.025065,0.025065,1.0164],
1360
- # [1591504620000,0.025062,0.025062,0.025062,0.025062,0.5],
1361
- # ]
1362
- #
1363
- return self.parse_ohlcvs(response, market, timeframe, since, limit)
1364
-
1365
- def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1366
- #
1367
- # [
1368
- # 1457539800000,
1369
- # 0.02594,
1370
- # 0.02594,
1371
- # 0.02594,
1372
- # 0.02594,
1373
- # 0.1
1374
- # ]
1375
- #
1376
- return [
1377
- self.safe_integer(ohlcv, 0),
1378
- self.safe_number(ohlcv, 1),
1379
- self.safe_number(ohlcv, 3),
1380
- self.safe_number(ohlcv, 4),
1381
- self.safe_number(ohlcv, 2),
1382
- self.safe_number(ohlcv, 5),
1383
- ]
1384
-
1385
- def parse_order_status(self, status):
1386
- if status is None:
1387
- return status
1388
- parts = status.split(' ')
1389
- state = self.safe_string(parts, 0)
1390
- statuses = {
1391
- 'ACTIVE': 'open',
1392
- 'PARTIALLY': 'open',
1393
- 'EXECUTED': 'closed',
1394
- 'CANCELED': 'canceled',
1395
- 'INSUFFICIENT': 'canceled',
1396
- 'POSTONLY CANCELED': 'canceled',
1397
- 'RSN_DUST': 'rejected',
1398
- 'RSN_PAUSE': 'rejected',
1399
- 'IOC CANCELED': 'canceled',
1400
- 'FILLORKILL CANCELED': 'canceled',
1401
- }
1402
- return self.safe_string(statuses, state, status)
1403
-
1404
- def parse_order_flags(self, flags):
1405
- # flags can be added to each other...
1406
- flagValues = {
1407
- '1024': ['reduceOnly'],
1408
- '4096': ['postOnly'],
1409
- '5120': ['reduceOnly', 'postOnly'],
1410
- # '64': 'hidden', # The hidden order option ensures an order does not appear in the order book
1411
- # '512': 'close', # Close position if position present.
1412
- # '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.
1413
- # '524288': 'No Var Rates' # Excludes variable rate funding offers from matching against self order, if on margin
1414
- }
1415
- return self.safe_value(flagValues, flags, None)
1416
-
1417
- def parse_time_in_force(self, orderType):
1418
- orderTypes = {
1419
- 'EXCHANGE IOC': 'IOC',
1420
- 'EXCHANGE FOK': 'FOK',
1421
- 'IOC': 'IOC', # Margin
1422
- 'FOK': 'FOK', # Margin
1423
- }
1424
- return self.safe_string(orderTypes, orderType, 'GTC')
1425
-
1426
- def parse_order(self, order, market: Market = None) -> Order:
1427
- id = self.safe_string(order, 0)
1428
- marketId = self.safe_string(order, 3)
1429
- symbol = self.safe_symbol(marketId)
1430
- # https://github.com/ccxt/ccxt/issues/6686
1431
- # timestamp = self.safe_timestamp(order, 5)
1432
- timestamp = self.safe_integer(order, 5)
1433
- remaining = Precise.string_abs(self.safe_string(order, 6))
1434
- signedAmount = self.safe_string(order, 7)
1435
- amount = Precise.string_abs(signedAmount)
1436
- side = 'sell' if Precise.string_lt(signedAmount, '0') else 'buy'
1437
- orderType = self.safe_string(order, 8)
1438
- type = self.safe_string(self.safe_value(self.options, 'exchangeTypes'), orderType)
1439
- timeInForce = self.parse_time_in_force(orderType)
1440
- rawFlags = self.safe_string(order, 12)
1441
- flags = self.parse_order_flags(rawFlags)
1442
- postOnly = False
1443
- if flags is not None:
1444
- for i in range(0, len(flags)):
1445
- if flags[i] == 'postOnly':
1446
- postOnly = True
1447
- price = self.safe_string(order, 16)
1448
- stopPrice = None
1449
- if (orderType == 'EXCHANGE STOP') or (orderType == 'EXCHANGE STOP LIMIT'):
1450
- price = None
1451
- stopPrice = self.safe_string(order, 16)
1452
- if orderType == 'EXCHANGE STOP LIMIT':
1453
- price = self.safe_string(order, 19)
1454
- status = None
1455
- statusString = self.safe_string(order, 13)
1456
- if statusString is not None:
1457
- parts = statusString.split(' @ ')
1458
- status = self.parse_order_status(self.safe_string(parts, 0))
1459
- average = self.safe_string(order, 17)
1460
- clientOrderId = self.safe_string(order, 2)
1461
- return self.safe_order({
1462
- 'info': order,
1463
- 'id': id,
1464
- 'clientOrderId': clientOrderId,
1465
- 'timestamp': timestamp,
1466
- 'datetime': self.iso8601(timestamp),
1467
- 'lastTradeTimestamp': None,
1468
- 'symbol': symbol,
1469
- 'type': type,
1470
- 'timeInForce': timeInForce,
1471
- 'postOnly': postOnly,
1472
- 'side': side,
1473
- 'price': price,
1474
- 'stopPrice': stopPrice,
1475
- 'triggerPrice': stopPrice,
1476
- 'amount': amount,
1477
- 'cost': None,
1478
- 'average': average,
1479
- 'filled': None,
1480
- 'remaining': remaining,
1481
- 'status': status,
1482
- 'fee': None,
1483
- 'trades': None,
1484
- }, market)
1485
-
1486
- def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1487
- """
1488
- * @ignore
1489
- helper function to build an order request
1490
- :param str symbol: unified symbol of the market to create an order in
1491
- :param str type: 'market' or 'limit'
1492
- :param str side: 'buy' or 'sell'
1493
- :param float amount: how much you want to trade in units of the base currency
1494
- :param float [price]: the price of the order, in units of the quote currency, ignored in market orders
1495
- :param dict [params]: extra parameters specific to the exchange API endpoint
1496
- :param float [params.stopPrice]: The price at which a trigger order is triggered at
1497
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1498
- :param bool [params.postOnly]:
1499
- :param bool [params.reduceOnly]: Ensures that the executed order does not flip the opened position.
1500
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
1501
- :param int [params.lev]: leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1502
- :param str [params.price_traling]: The trailing price for a trailing stop order
1503
- :param str [params.price_aux_limit]: Order price for stop limit orders
1504
- :param str [params.price_oco_stop]: OCO stop price
1505
- :returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
1506
- """
1507
- market = self.market(symbol)
1508
- amountString = self.amount_to_precision(symbol, amount)
1509
- amountString = amountString if (side == 'buy') else Precise.string_neg(amountString)
1510
- request = {
1511
- 'symbol': market['id'],
1512
- 'amount': amountString,
1513
- }
1514
- stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1515
- trailingAmount = self.safe_string(params, 'trailingAmount')
1516
- timeInForce = self.safe_string(params, 'timeInForce')
1517
- postOnlyParam = self.safe_bool(params, 'postOnly', False)
1518
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1519
- clientOrderId = self.safe_value_2(params, 'cid', 'clientOrderId')
1520
- orderType = type.upper()
1521
- if trailingAmount is not None:
1522
- orderType = 'TRAILING STOP'
1523
- request['price_trailing'] = trailingAmount
1524
- elif stopPrice is not None:
1525
- # request['price'] is taken for stop orders
1526
- request['price'] = self.price_to_precision(symbol, stopPrice)
1527
- if type == 'limit':
1528
- orderType = 'STOP LIMIT'
1529
- request['price_aux_limit'] = self.price_to_precision(symbol, price)
1530
- else:
1531
- orderType = 'STOP'
1532
- ioc = (timeInForce == 'IOC')
1533
- fok = (timeInForce == 'FOK')
1534
- postOnly = (postOnlyParam or (timeInForce == 'PO'))
1535
- if (ioc or fok) and (price is None):
1536
- raise InvalidOrder(self.id + ' createOrder() requires a price argument with IOC and FOK orders')
1537
- if (ioc or fok) and (type == 'market'):
1538
- raise InvalidOrder(self.id + ' createOrder() does not allow market IOC and FOK orders')
1539
- if (type != 'market') and (stopPrice is None):
1540
- request['price'] = self.price_to_precision(symbol, price)
1541
- if ioc:
1542
- orderType = 'IOC'
1543
- elif fok:
1544
- orderType = 'FOK'
1545
- marginMode = None
1546
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
1547
- if market['spot'] and (marginMode is None):
1548
- # The EXCHANGE prefix is only required for non margin spot markets
1549
- orderType = 'EXCHANGE ' + orderType
1550
- request['type'] = orderType
1551
- # flag values may be summed to combine flags
1552
- flags = 0
1553
- if postOnly:
1554
- flags = self.sum(flags, 4096)
1555
- if reduceOnly:
1556
- flags = self.sum(flags, 1024)
1557
- if flags != 0:
1558
- request['flags'] = flags
1559
- if clientOrderId is not None:
1560
- request['cid'] = clientOrderId
1561
- params = self.omit(params, ['triggerPrice', 'stopPrice', 'timeInForce', 'postOnly', 'reduceOnly', 'trailingAmount', 'clientOrderId'])
1562
- return self.extend(request, params)
1563
-
1564
- async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1565
- """
1566
- create an order on the exchange
1567
- :see: https://docs.bitfinex.com/reference/rest-auth-submit-order
1568
- :param str symbol: unified CCXT market symbol
1569
- :param str type: 'limit' or 'market'
1570
- :param str side: 'buy' or 'sell'
1571
- :param float amount: the amount of currency to trade
1572
- :param float [price]: price of the order
1573
- :param dict [params]: extra parameters specific to the exchange API endpoint
1574
- :param float [params.stopPrice]: the price that triggers a trigger order
1575
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1576
- :param boolean [params.postOnly]: set to True if you want to make a post only order
1577
- :param boolean [params.reduceOnly]: indicates that the order is to reduce the size of a position
1578
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
1579
- :param int [params.lev]: leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1580
- :param str [params.price_aux_limit]: order price for stop limit orders
1581
- :param str [params.price_oco_stop]: OCO stop price
1582
- :param str [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
1583
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1584
- """
1585
- await self.load_markets()
1586
- market = self.market(symbol)
1587
- request = self.create_order_request(symbol, type, side, amount, price, params)
1588
- response = await self.privatePostAuthWOrderSubmit(request)
1589
- #
1590
- # [
1591
- # 1653325121, # Timestamp in milliseconds
1592
- # "on-req", # Purpose of notification('on-req', 'oc-req', "uca", 'fon-req', "foc-req")
1593
- # null, # unique ID of the message
1594
- # null,
1595
- # [
1596
- # [
1597
- # 95412102131, # Order ID
1598
- # null, # Group ID
1599
- # 1653325121798, # Client Order ID
1600
- # "tDOGE:UST", # Market ID
1601
- # 1653325121798, # Millisecond timestamp of creation
1602
- # 1653325121798, # Millisecond timestamp of update
1603
- # -10, # Amount(Positive means buy, negative means sell)
1604
- # -10, # Original amount
1605
- # "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.
1606
- # null, # Previous order type(stop-limit orders are converted to limit orders so for them previous type is always STOP)
1607
- # null, # Millisecond timestamp of Time-In-Force: automatic order cancellation
1608
- # null, # _PLACEHOLDER
1609
- # 4096, # Flags, see parseOrderFlags()
1610
- # "ACTIVE", # Order Status, see parseOrderStatus()
1611
- # null, # _PLACEHOLDER
1612
- # null, # _PLACEHOLDER
1613
- # 0.071, # Price(Stop Price for stop-limit orders, Limit Price for limit orders)
1614
- # 0, # Average Price
1615
- # 0, # Trailing Price
1616
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1617
- # null, # _PLACEHOLDER
1618
- # null, # _PLACEHOLDER
1619
- # null, # _PLACEHOLDER
1620
- # 0, # Hidden(0 if False, 1 if True)
1621
- # 0, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
1622
- # null, # _PLACEHOLDER
1623
- # null, # _PLACEHOLDER
1624
- # null, # _PLACEHOLDER
1625
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
1626
- # null, # _PLACEHOLDER
1627
- # null, # _PLACEHOLDER
1628
- # {"$F7":1} # additional meta information about the order( $F7 = IS_POST_ONLY(0 if False, 1 if True), $F33 = Leverage(int))
1629
- # ]
1630
- # ],
1631
- # null, # CODE(work in progress)
1632
- # "SUCCESS", # Status of the request
1633
- # "Submitting 1 orders." # Message
1634
- # ]
1635
- #
1636
- status = self.safe_string(response, 6)
1637
- if status != 'SUCCESS':
1638
- errorCode = response[5]
1639
- errorText = response[7]
1640
- raise ExchangeError(self.id + ' ' + response[6] + ': ' + errorText + '(#' + errorCode + ')')
1641
- orders = self.safe_list(response, 4, [])
1642
- order = self.safe_list(orders, 0)
1643
- return self.parse_order(order, market)
1644
-
1645
- async def create_orders(self, orders: List[OrderRequest], params={}):
1646
- """
1647
- create a list of trade orders
1648
- :see: https://docs.bitfinex.com/reference/rest-auth-order-multi
1649
- :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
1650
- :param dict [params]: extra parameters specific to the exchange API endpoint
1651
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1652
- """
1653
- await self.load_markets()
1654
- ordersRequests = []
1655
- for i in range(0, len(orders)):
1656
- rawOrder = orders[i]
1657
- symbol = self.safe_string(rawOrder, 'symbol')
1658
- type = self.safe_string(rawOrder, 'type')
1659
- side = self.safe_string(rawOrder, 'side')
1660
- amount = self.safe_number(rawOrder, 'amount')
1661
- price = self.safe_number(rawOrder, 'price')
1662
- orderParams = self.safe_dict(rawOrder, 'params', {})
1663
- orderRequest = self.create_order_request(symbol, type, side, amount, price, orderParams)
1664
- ordersRequests.append(['on', orderRequest])
1665
- request = {
1666
- 'ops': ordersRequests,
1667
- }
1668
- response = await self.privatePostAuthWOrderMulti(request)
1669
- #
1670
- # [
1671
- # 1706762515553,
1672
- # "ox_multi-req",
1673
- # null,
1674
- # null,
1675
- # [
1676
- # [
1677
- # 1706762515,
1678
- # "on-req",
1679
- # null,
1680
- # null,
1681
- # [
1682
- # [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,{}]
1683
- # ],
1684
- # null,
1685
- # "SUCCESS",
1686
- # "Submitting 1 orders."
1687
- # ],
1688
- # ],
1689
- # null,
1690
- # "SUCCESS",
1691
- # "Submitting 2 order operations."
1692
- # ]
1693
- #
1694
- results = []
1695
- data = self.safe_list(response, 4, [])
1696
- for i in range(0, len(data)):
1697
- entry = data[i]
1698
- individualOrder = entry[4]
1699
- results.append(individualOrder[0])
1700
- return self.parse_orders(results)
1701
-
1702
- async def cancel_all_orders(self, symbol: Str = None, params={}):
1703
- """
1704
- cancel all open orders
1705
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-orders-multiple
1706
- :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1707
- :param dict [params]: extra parameters specific to the exchange API endpoint
1708
- :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1709
- """
1710
- await self.load_markets()
1711
- request = {
1712
- 'all': 1,
1713
- }
1714
- response = await self.privatePostAuthWOrderCancelMulti(self.extend(request, params))
1715
- orders = self.safe_value(response, 4, [])
1716
- return self.parse_orders(orders)
1717
-
1718
- async def cancel_order(self, id: str, symbol: Str = None, params={}):
1719
- """
1720
- cancels an open order
1721
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-order
1722
- :param str id: order id
1723
- :param str symbol: Not used by bitfinex2 cancelOrder()
1724
- :param dict [params]: extra parameters specific to the exchange API endpoint
1725
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1726
- """
1727
- await self.load_markets()
1728
- cid = self.safe_value_2(params, 'cid', 'clientOrderId') # client order id
1729
- request = None
1730
- if cid is not None:
1731
- cidDate = self.safe_value(params, 'cidDate') # client order id date
1732
- if cidDate is None:
1733
- raise InvalidOrder(self.id + " canceling an order by clientOrderId('cid') requires both 'cid' and 'cid_date'('YYYY-MM-DD')")
1734
- request = {
1735
- 'cid': cid,
1736
- 'cid_date': cidDate,
1737
- }
1738
- params = self.omit(params, ['cid', 'clientOrderId'])
1739
- else:
1740
- request = {
1741
- 'id': int(id),
1742
- }
1743
- response = await self.privatePostAuthWOrderCancel(self.extend(request, params))
1744
- order = self.safe_value(response, 4)
1745
- return self.parse_order(order)
1746
-
1747
- async def cancel_orders(self, ids, symbol: Str = None, params={}):
1748
- """
1749
- cancel multiple orders at the same time
1750
- :see: https://docs.bitfinex.com/reference/rest-auth-cancel-orders-multiple
1751
- :param str[] ids: order ids
1752
- :param str symbol: unified market symbol, default is None
1753
- :param dict [params]: extra parameters specific to the exchange API endpoint
1754
- :returns dict: an array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1755
- """
1756
- await self.load_markets()
1757
- for i in range(0, len(ids)):
1758
- ids[i] = self.parse_to_numeric(ids[i])
1759
- request = {
1760
- 'id': ids,
1761
- }
1762
- market = None
1763
- if symbol is not None:
1764
- market = self.market(symbol)
1765
- response = await self.privatePostAuthWOrderCancelMulti(self.extend(request, params))
1766
- #
1767
- # [
1768
- # 1706740198811,
1769
- # "oc_multi-req",
1770
- # null,
1771
- # null,
1772
- # [
1773
- # [
1774
- # 139530205057,
1775
- # null,
1776
- # 1706740132275,
1777
- # "tBTCF0:USTF0",
1778
- # 1706740132276,
1779
- # 1706740132276,
1780
- # 0.0001,
1781
- # 0.0001,
1782
- # "LIMIT",
1783
- # null,
1784
- # null,
1785
- # null,
1786
- # 0,
1787
- # "ACTIVE",
1788
- # null,
1789
- # null,
1790
- # 39000,
1791
- # 0,
1792
- # 0,
1793
- # 0,
1794
- # null,
1795
- # null,
1796
- # null,
1797
- # 0,
1798
- # 0,
1799
- # null,
1800
- # null,
1801
- # null,
1802
- # "API>BFX",
1803
- # null,
1804
- # null,
1805
- # {
1806
- # "lev": 10,
1807
- # "$F33": 10
1808
- # }
1809
- # ],
1810
- # ],
1811
- # null,
1812
- # "SUCCESS",
1813
- # "Submitting 2 order cancellations."
1814
- # ]
1815
- #
1816
- orders = self.safe_list(response, 4, [])
1817
- return self.parse_orders(orders, market)
1818
-
1819
- async def fetch_open_order(self, id: str, symbol: Str = None, params={}):
1820
- """
1821
- fetch an open order by it's id
1822
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1823
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1824
- :param str id: order id
1825
- :param str symbol: unified market symbol, default is None
1826
- :param dict [params]: extra parameters specific to the exchange API endpoint
1827
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1828
- """
1829
- request = {
1830
- 'id': [int(id)],
1831
- }
1832
- orders = await self.fetch_open_orders(symbol, None, None, self.extend(request, params))
1833
- order = self.safe_value(orders, 0)
1834
- if order is None:
1835
- raise OrderNotFound(self.id + ' order ' + id + ' not found')
1836
- return order
1837
-
1838
- async def fetch_closed_order(self, id: str, symbol: Str = None, params={}):
1839
- """
1840
- fetch an open order by it's id
1841
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1842
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1843
- :param str id: order id
1844
- :param str symbol: unified market symbol, default is None
1845
- :param dict [params]: extra parameters specific to the exchange API endpoint
1846
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1847
- """
1848
- request = {
1849
- 'id': [int(id)],
1850
- }
1851
- orders = await self.fetch_closed_orders(symbol, None, None, self.extend(request, params))
1852
- order = self.safe_value(orders, 0)
1853
- if order is None:
1854
- raise OrderNotFound(self.id + ' order ' + id + ' not found')
1855
- return order
1856
-
1857
- async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1858
- """
1859
- fetch all unfilled currently open orders
1860
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1861
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1862
- :param str symbol: unified market symbol
1863
- :param int [since]: the earliest time in ms to fetch open orders for
1864
- :param int [limit]: the maximum number of open orders structures to retrieve
1865
- :param dict [params]: extra parameters specific to the exchange API endpoint
1866
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1867
- """
1868
- await self.load_markets()
1869
- request = {}
1870
- market = None
1871
- response = None
1872
- if symbol is None:
1873
- response = await self.privatePostAuthROrders(self.extend(request, params))
1874
- else:
1875
- market = self.market(symbol)
1876
- request['symbol'] = market['id']
1877
- response = await self.privatePostAuthROrdersSymbol(self.extend(request, params))
1878
- #
1879
- # [
1880
- # [
1881
- # 95408916206, # Order ID
1882
- # null, # Group Order ID
1883
- # 1653322349926, # Client Order ID
1884
- # "tDOGE:UST", # Market ID
1885
- # 1653322349926, # Created Timestamp in milliseconds
1886
- # 1653322349927, # Updated Timestamp in milliseconds
1887
- # -10, # Amount remaining(Positive means buy, negative means sell)
1888
- # -10, # Original amount
1889
- # "EXCHANGE LIMIT", # Order type
1890
- # null, # Previous Order Type
1891
- # null, # _PLACEHOLDER
1892
- # null, # _PLACEHOLDER
1893
- # 0, # Flags, see parseOrderFlags()
1894
- # "ACTIVE", # Order Status, see parseOrderStatus()
1895
- # null, # _PLACEHOLDER
1896
- # null, # _PLACEHOLDER
1897
- # 0.11, # Price
1898
- # 0, # Average Price
1899
- # 0, # Trailing Price
1900
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1901
- # null, # _PLACEHOLDER
1902
- # null, # _PLACEHOLDER
1903
- # null, # _PLACEHOLDER
1904
- # 0, # Hidden(0 if False, 1 if True)
1905
- # 0, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
1906
- # null, # _PLACEHOLDER
1907
- # null, # _PLACEHOLDER
1908
- # null, # _PLACEHOLDER
1909
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
1910
- # null, # _PLACEHOLDER
1911
- # null, # _PLACEHOLDER
1912
- # {"$F7":1} # additional meta information about the order( $F7 = IS_POST_ONLY(0 if False, 1 if True), $F33 = Leverage(int))
1913
- # ],
1914
- # ]
1915
- #
1916
- return self.parse_orders(response, market, since, limit)
1917
-
1918
- async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1919
- """
1920
- fetches information on multiple closed orders made by the user
1921
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
1922
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
1923
- :param str symbol: unified market symbol of the market orders were made in
1924
- :param int [since]: the earliest time in ms to fetch orders for
1925
- :param int [limit]: the maximum number of order structures to retrieve
1926
- :param dict [params]: extra parameters specific to the exchange API endpoint
1927
- :param int [params.until]: the latest time in ms to fetch entries for
1928
- :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)
1929
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1930
- """
1931
- # returns the most recent closed or canceled orders up to circa two weeks ago
1932
- await self.load_markets()
1933
- paginate = False
1934
- paginate, params = self.handle_option_and_params(params, 'fetchClosedOrders', 'paginate')
1935
- if paginate:
1936
- return await self.fetch_paginated_call_dynamic('fetchClosedOrders', symbol, since, limit, params)
1937
- request = {}
1938
- if since is not None:
1939
- request['start'] = since
1940
- if limit is not None:
1941
- request['limit'] = limit # default 25, max 2500
1942
- request, params = self.handle_until_option('end', request, params)
1943
- market = None
1944
- response = None
1945
- if symbol is None:
1946
- response = await self.privatePostAuthROrdersHist(self.extend(request, params))
1947
- else:
1948
- market = self.market(symbol)
1949
- request['symbol'] = market['id']
1950
- response = await self.privatePostAuthROrdersSymbolHist(self.extend(request, params))
1951
- #
1952
- # [
1953
- # [
1954
- # 95412102131, # Order ID
1955
- # null, # Group Order ID
1956
- # 1653325121798, # Client Order ID
1957
- # "tDOGE:UST", # Market ID
1958
- # 1653325122000, # Created Timestamp in milliseconds
1959
- # 1653325122000, # Updated Timestamp in milliseconds
1960
- # -10, # Amount remaining(Positive means buy, negative means sell)
1961
- # -10, # Original amount
1962
- # "EXCHANGE LIMIT", # Order type
1963
- # null, # Previous Order Type
1964
- # null, # Millisecond timestamp of Time-In-Force: automatic order cancellation
1965
- # null, # _PLACEHOLDER
1966
- # "4096", # Flags, see parseOrderFlags()
1967
- # "POSTONLY CANCELED", # Order Status, see parseOrderStatus()
1968
- # null, # _PLACEHOLDER
1969
- # null, # _PLACEHOLDER
1970
- # 0.071, # Price
1971
- # 0, # Average Price
1972
- # 0, # Trailing Price
1973
- # 0, # Auxiliary Limit price(for STOP LIMIT)
1974
- # null, # _PLACEHOLDER
1975
- # null, # _PLACEHOLDER
1976
- # null, # _PLACEHOLDER
1977
- # 0, # Notify(0 if False, 1 if True)
1978
- # 0, # Hidden(0 if False, 1 if True)
1979
- # null, # Placed ID(If another order caused self order to be placed(OCO) self will be that other order's ID)
1980
- # null, # _PLACEHOLDER
1981
- # null, # _PLACEHOLDER
1982
- # "API>BFX", # Routing, indicates origin of action: BFX, ETHFX, API>BFX, API>ETHFX
1983
- # null, # _PLACEHOLDER
1984
- # null, # _PLACEHOLDER
1985
- # {"_$F7":1} # additional meta information about the order( _$F7 = IS_POST_ONLY(0 if False, 1 if True), _$F33 = Leverage(int))
1986
- # ]
1987
- # ]
1988
- #
1989
- return self.parse_orders(response, market, since, limit)
1990
-
1991
- async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1992
- """
1993
- fetch all the trades made from a single order
1994
- :see: https://docs.bitfinex.com/reference/rest-auth-order-trades
1995
- :param str id: order id
1996
- :param str symbol: unified market symbol
1997
- :param int [since]: the earliest time in ms to fetch trades for
1998
- :param int [limit]: the maximum number of trades to retrieve
1999
- :param dict [params]: extra parameters specific to the exchange API endpoint
2000
- :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2001
- """
2002
- if symbol is None:
2003
- raise ArgumentsRequired(self.id + ' fetchOrderTrades() requires a symbol argument')
2004
- await self.load_markets()
2005
- market = self.market(symbol)
2006
- orderId = int(id)
2007
- request = {
2008
- 'id': orderId,
2009
- 'symbol': market['id'],
2010
- }
2011
- # valid for trades upto 10 days old
2012
- response = await self.privatePostAuthROrderSymbolIdTrades(self.extend(request, params))
2013
- return self.parse_trades(response, market, since, limit)
2014
-
2015
- async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2016
- """
2017
- fetch all trades made by the user
2018
- :see: https://docs.bitfinex.com/reference/rest-auth-trades
2019
- :see: https://docs.bitfinex.com/reference/rest-auth-trades-by-symbol
2020
- :param str symbol: unified market symbol
2021
- :param int [since]: the earliest time in ms to fetch trades for
2022
- :param int [limit]: the maximum number of trades structures to retrieve
2023
- :param dict [params]: extra parameters specific to the exchange API endpoint
2024
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2025
- """
2026
- await self.load_markets()
2027
- market = None
2028
- request = {
2029
- 'end': self.milliseconds(),
2030
- }
2031
- if since is not None:
2032
- request['start'] = since
2033
- if limit is not None:
2034
- request['limit'] = limit # default 25, max 1000
2035
- response = None
2036
- if symbol is not None:
2037
- market = self.market(symbol)
2038
- request['symbol'] = market['id']
2039
- response = await self.privatePostAuthRTradesSymbolHist(self.extend(request, params))
2040
- else:
2041
- response = await self.privatePostAuthRTradesHist(self.extend(request, params))
2042
- return self.parse_trades(response, market, since, limit)
2043
-
2044
- async def create_deposit_address(self, code: str, params={}):
2045
- """
2046
- create a currency deposit address
2047
- :see: https://docs.bitfinex.com/reference/rest-auth-deposit-address
2048
- :param str code: unified currency code of the currency for the deposit address
2049
- :param dict [params]: extra parameters specific to the exchange API endpoint
2050
- :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2051
- """
2052
- await self.load_markets()
2053
- request = {
2054
- 'op_renew': 1,
2055
- }
2056
- return await self.fetch_deposit_address(code, self.extend(request, params))
2057
-
2058
- async def fetch_deposit_address(self, code: str, params={}):
2059
- """
2060
- fetch the deposit address for a currency associated with self account
2061
- :see: https://docs.bitfinex.com/reference/rest-auth-deposit-address
2062
- :param str code: unified currency code
2063
- :param dict [params]: extra parameters specific to the exchange API endpoint
2064
- :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
2065
- """
2066
- await self.load_markets()
2067
- currency = self.currency(code)
2068
- # if not provided explicitly we will try to match using the currency name
2069
- network = self.safe_string(params, 'network', code)
2070
- currencyNetworks = self.safe_value(currency, 'networks', {})
2071
- currencyNetwork = self.safe_value(currencyNetworks, network)
2072
- networkId = self.safe_string(currencyNetwork, 'id')
2073
- if networkId is None:
2074
- raise ArgumentsRequired(self.id + " fetchDepositAddress() could not find a network for '" + code + "'. You can specify it by providing the 'network' value inside params")
2075
- wallet = self.safe_string(params, 'wallet', 'exchange') # 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
2076
- params = self.omit(params, 'network', 'wallet')
2077
- request = {
2078
- 'method': networkId,
2079
- 'wallet': wallet,
2080
- 'op_renew': 0, # a value of 1 will generate a new address
2081
- }
2082
- response = await self.privatePostAuthWDepositAddress(self.extend(request, params))
2083
- #
2084
- # [
2085
- # 1582269616687, # MTS Millisecond Time Stamp of the update
2086
- # "acc_dep", # TYPE Purpose of notification "acc_dep" for account deposit
2087
- # null, # MESSAGE_ID unique ID of the message
2088
- # null, # not documented
2089
- # [
2090
- # null, # PLACEHOLDER
2091
- # "BITCOIN", # METHOD Method of deposit
2092
- # "BTC", # CURRENCY_CODE Currency code of new address
2093
- # null, # PLACEHOLDER
2094
- # "1BC9PZqpUmjyEB54uggn8TFKj49zSDYzqG", # ADDRESS
2095
- # null, # POOL_ADDRESS
2096
- # ],
2097
- # null, # CODE null or integer work in progress
2098
- # "SUCCESS", # STATUS Status of the notification, SUCCESS, ERROR, FAILURE
2099
- # "success", # TEXT Text of the notification
2100
- # ]
2101
- #
2102
- result = self.safe_value(response, 4, [])
2103
- poolAddress = self.safe_string(result, 5)
2104
- address = self.safe_string(result, 4) if (poolAddress is None) else poolAddress
2105
- tag = None if (poolAddress is None) else self.safe_string(result, 4)
2106
- self.check_address(address)
2107
- return {
2108
- 'currency': code,
2109
- 'address': address,
2110
- 'tag': tag,
2111
- 'network': None,
2112
- 'info': response,
2113
- }
2114
-
2115
- def parse_transaction_status(self, status):
2116
- statuses = {
2117
- 'SUCCESS': 'ok',
2118
- 'COMPLETED': 'ok',
2119
- 'ERROR': 'failed',
2120
- 'FAILURE': 'failed',
2121
- 'CANCELED': 'canceled',
2122
- 'PENDING APPROVAL': 'pending',
2123
- 'PENDING': 'pending',
2124
- 'PENDING REVIEW': 'pending',
2125
- 'PENDING CANCELLATION': 'pending',
2126
- 'SENDING': 'pending',
2127
- 'USER APPROVED': 'pending',
2128
- }
2129
- return self.safe_string(statuses, status, status)
2130
-
2131
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
2132
- #
2133
- # withdraw
2134
- #
2135
- # [
2136
- # 1582271520931, # MTS Millisecond Time Stamp of the update
2137
- # "acc_wd-req", # TYPE Purpose of notification "acc_wd-req" account withdrawal request
2138
- # null, # MESSAGE_ID unique ID of the message
2139
- # null, # not documented
2140
- # [
2141
- # 0, # WITHDRAWAL_ID Unique Withdrawal ID
2142
- # null, # PLACEHOLDER
2143
- # "bitcoin", # METHOD Method of withdrawal
2144
- # null, # PAYMENT_ID Payment ID if relevant
2145
- # "exchange", # WALLET Sending wallet
2146
- # 1, # AMOUNT Amount of Withdrawal less fee
2147
- # null, # PLACEHOLDER
2148
- # null, # PLACEHOLDER
2149
- # 0.0004, # WITHDRAWAL_FEE Fee on withdrawal
2150
- # ],
2151
- # null, # CODE null or integer Work in progress
2152
- # "SUCCESS", # STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
2153
- # "Invalid bitcoin address(abcdef)", # TEXT Text of the notification
2154
- # ]
2155
- #
2156
- # fetchDepositsWithdrawals
2157
- #
2158
- # [
2159
- # 13293039, # ID
2160
- # "ETH", # CURRENCY
2161
- # "ETHEREUM", # CURRENCY_NAME
2162
- # null,
2163
- # null,
2164
- # 1574175052000, # MTS_STARTED
2165
- # 1574181326000, # MTS_UPDATED
2166
- # null,
2167
- # null,
2168
- # "CANCELED", # STATUS
2169
- # null,
2170
- # null,
2171
- # -0.24, # AMOUNT, negative for withdrawals
2172
- # -0.00135, # FEES
2173
- # null,
2174
- # null,
2175
- # "0x38110e0Fc932CB2BE...........", # DESTINATION_ADDRESS
2176
- # null,
2177
- # null,
2178
- # null,
2179
- # "0x523ec8945500.....................................", # TRANSACTION_ID
2180
- # "Purchase of 100 pizzas", # WITHDRAW_TRANSACTION_NOTE, might also be: null
2181
- # ]
2182
- #
2183
- transactionLength = len(transaction)
2184
- timestamp = None
2185
- updated = None
2186
- code = None
2187
- amount = None
2188
- id = None
2189
- status = None
2190
- tag = None
2191
- type = None
2192
- feeCost = None
2193
- txid = None
2194
- addressTo = None
2195
- network = None
2196
- comment = None
2197
- if transactionLength == 8:
2198
- data = self.safe_value(transaction, 4, [])
2199
- timestamp = self.safe_integer(transaction, 0)
2200
- if currency is not None:
2201
- code = currency['code']
2202
- feeCost = self.safe_string(data, 8)
2203
- if feeCost is not None:
2204
- feeCost = Precise.string_abs(feeCost)
2205
- amount = self.safe_number(data, 5)
2206
- id = self.safe_string(data, 0)
2207
- status = 'ok'
2208
- if id == 0:
2209
- id = None
2210
- status = 'failed'
2211
- tag = self.safe_string(data, 3)
2212
- type = 'withdrawal'
2213
- elif transactionLength == 22:
2214
- id = self.safe_string(transaction, 0)
2215
- currencyId = self.safe_string(transaction, 1)
2216
- code = self.safe_currency_code(currencyId, currency)
2217
- networkId = self.safe_string(transaction, 2)
2218
- network = self.safe_network(networkId)
2219
- timestamp = self.safe_integer(transaction, 5)
2220
- updated = self.safe_integer(transaction, 6)
2221
- status = self.parse_transaction_status(self.safe_string(transaction, 9))
2222
- signedAmount = self.safe_string(transaction, 12)
2223
- amount = Precise.string_abs(signedAmount)
2224
- if signedAmount is not None:
2225
- if Precise.string_lt(signedAmount, '0'):
2226
- type = 'withdrawal'
2227
- else:
2228
- type = 'deposit'
2229
- feeCost = self.safe_string(transaction, 13)
2230
- if feeCost is not None:
2231
- feeCost = Precise.string_abs(feeCost)
2232
- addressTo = self.safe_string(transaction, 16)
2233
- txid = self.safe_string(transaction, 20)
2234
- comment = self.safe_string(transaction, 21)
2235
- return {
2236
- 'info': transaction,
2237
- 'id': id,
2238
- 'txid': txid,
2239
- 'type': type,
2240
- 'currency': code,
2241
- 'network': network,
2242
- 'amount': self.parse_number(amount),
2243
- 'status': status,
2244
- 'timestamp': timestamp,
2245
- 'datetime': self.iso8601(timestamp),
2246
- 'address': addressTo, # self is actually the tag for XRP transfers(the address is missing)
2247
- 'addressFrom': None,
2248
- 'addressTo': addressTo,
2249
- 'tag': tag, # refix it properly for the tag from description
2250
- 'tagFrom': None,
2251
- 'tagTo': tag,
2252
- 'updated': updated,
2253
- 'comment': comment,
2254
- 'internal': None,
2255
- 'fee': {
2256
- 'currency': code,
2257
- 'cost': self.parse_number(feeCost),
2258
- 'rate': None,
2259
- },
2260
- }
2261
-
2262
- async def fetch_trading_fees(self, params={}):
2263
- """
2264
- fetch the trading fees for multiple markets
2265
- :see: https://docs.bitfinex.com/reference/rest-auth-summary
2266
- :param dict [params]: extra parameters specific to the exchange API endpoint
2267
- :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
2268
- """
2269
- await self.load_markets()
2270
- response = await self.privatePostAuthRSummary(params)
2271
- #
2272
- # Response Spec:
2273
- # [
2274
- # PLACEHOLDER,
2275
- # PLACEHOLDER,
2276
- # PLACEHOLDER,
2277
- # PLACEHOLDER,
2278
- # [
2279
- # [
2280
- # MAKER_FEE,
2281
- # MAKER_FEE,
2282
- # MAKER_FEE,
2283
- # PLACEHOLDER,
2284
- # PLACEHOLDER,
2285
- # DERIV_REBATE
2286
- # ],
2287
- # [
2288
- # TAKER_FEE_TO_CRYPTO,
2289
- # TAKER_FEE_TO_STABLE,
2290
- # TAKER_FEE_TO_FIAT,
2291
- # PLACEHOLDER,
2292
- # PLACEHOLDER,
2293
- # DERIV_TAKER_FEE
2294
- # ]
2295
- # ],
2296
- # PLACEHOLDER,
2297
- # PLACEHOLDER,
2298
- # PLACEHOLDER,
2299
- # PLACEHOLDER,
2300
- # {
2301
- # LEO_LEV,
2302
- # LEO_AMOUNT_AVG
2303
- # }
2304
- # ]
2305
- #
2306
- # Example response:
2307
- #
2308
- # [
2309
- # null,
2310
- # null,
2311
- # null,
2312
- # null,
2313
- # [
2314
- # [0.001, 0.001, 0.001, null, null, 0.0002],
2315
- # [0.002, 0.002, 0.002, null, null, 0.00065]
2316
- # ],
2317
- # [
2318
- # [
2319
- # {
2320
- # "curr": "Total(USD)",
2321
- # "vol": "0",
2322
- # "vol_safe": "0",
2323
- # "vol_maker": "0",
2324
- # "vol_BFX": "0",
2325
- # "vol_BFX_safe": "0",
2326
- # "vol_BFX_maker": "0"
2327
- # }
2328
- # ],
2329
- # {},
2330
- # 0
2331
- # ],
2332
- # [null, {}, 0],
2333
- # null,
2334
- # null,
2335
- # {leo_lev: "0", leo_amount_avg: "0"}
2336
- # ]
2337
- #
2338
- result = {}
2339
- fiat = self.safe_value(self.options, 'fiat', {})
2340
- feeData = self.safe_value(response, 4, [])
2341
- makerData = self.safe_value(feeData, 0, [])
2342
- takerData = self.safe_value(feeData, 1, [])
2343
- makerFee = self.safe_number(makerData, 0)
2344
- makerFeeFiat = self.safe_number(makerData, 2)
2345
- makerFeeDeriv = self.safe_number(makerData, 5)
2346
- takerFee = self.safe_number(takerData, 0)
2347
- takerFeeFiat = self.safe_number(takerData, 2)
2348
- takerFeeDeriv = self.safe_number(takerData, 5)
2349
- for i in range(0, len(self.symbols)):
2350
- symbol = self.symbols[i]
2351
- market = self.market(symbol)
2352
- fee = {
2353
- 'info': response,
2354
- 'symbol': symbol,
2355
- 'percentage': True,
2356
- 'tierBased': True,
2357
- }
2358
- if market['quote'] in fiat:
2359
- fee['maker'] = makerFeeFiat
2360
- fee['taker'] = takerFeeFiat
2361
- elif market['contract']:
2362
- fee['maker'] = makerFeeDeriv
2363
- fee['taker'] = takerFeeDeriv
2364
- else: # TODO check if stable coin
2365
- fee['maker'] = makerFee
2366
- fee['taker'] = takerFee
2367
- result[symbol] = fee
2368
- return result
2369
-
2370
- async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2371
- """
2372
- fetch history of deposits and withdrawals
2373
- :see: https://docs.bitfinex.com/reference/movement-info
2374
- :see: https://docs.bitfinex.com/reference/rest-auth-movements
2375
- :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2376
- :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2377
- :param int [limit]: max number of deposit/withdrawals to return, default is None
2378
- :param dict [params]: extra parameters specific to the exchange API endpoint
2379
- :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2380
- """
2381
- await self.load_markets()
2382
- currency = None
2383
- request = {}
2384
- if since is not None:
2385
- request['start'] = since
2386
- if limit is not None:
2387
- request['limit'] = limit # max 1000
2388
- response = None
2389
- if code is not None:
2390
- currency = self.currency(code)
2391
- request['currency'] = currency['uppercaseId']
2392
- response = await self.privatePostAuthRMovementsCurrencyHist(self.extend(request, params))
2393
- else:
2394
- response = await self.privatePostAuthRMovementsHist(self.extend(request, params))
2395
- #
2396
- # [
2397
- # [
2398
- # 13293039, # ID
2399
- # "ETH", # CURRENCY
2400
- # "ETHEREUM", # CURRENCY_NAME
2401
- # null,
2402
- # null,
2403
- # 1574175052000, # MTS_STARTED
2404
- # 1574181326000, # MTS_UPDATED
2405
- # null,
2406
- # null,
2407
- # "CANCELED", # STATUS
2408
- # null,
2409
- # null,
2410
- # -0.24, # AMOUNT, negative for withdrawals
2411
- # -0.00135, # FEES
2412
- # null,
2413
- # null,
2414
- # "0x38110e0Fc932CB2BE...........", # DESTINATION_ADDRESS
2415
- # null,
2416
- # null,
2417
- # null,
2418
- # "0x523ec8945500.....................................", # TRANSACTION_ID
2419
- # "Purchase of 100 pizzas", # WITHDRAW_TRANSACTION_NOTE, might also be: null
2420
- # ]
2421
- # ]
2422
- #
2423
- return self.parse_transactions(response, currency, since, limit)
2424
-
2425
- async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
2426
- """
2427
- make a withdrawal
2428
- :see: https://docs.bitfinex.com/reference/rest-auth-withdraw
2429
- :param str code: unified currency code
2430
- :param float amount: the amount to withdraw
2431
- :param str address: the address to withdraw to
2432
- :param str tag:
2433
- :param dict [params]: extra parameters specific to the exchange API endpoint
2434
- :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2435
- """
2436
- self.check_address(address)
2437
- await self.load_markets()
2438
- currency = self.currency(code)
2439
- # if not provided explicitly we will try to match using the currency name
2440
- network = self.safe_string(params, 'network', code)
2441
- params = self.omit(params, 'network')
2442
- currencyNetworks = self.safe_value(currency, 'networks', {})
2443
- currencyNetwork = self.safe_value(currencyNetworks, network)
2444
- networkId = self.safe_string(currencyNetwork, 'id')
2445
- if networkId is None:
2446
- raise ArgumentsRequired(self.id + " withdraw() could not find a network for '" + code + "'. You can specify it by providing the 'network' value inside params")
2447
- wallet = self.safe_string(params, 'wallet', 'exchange') # 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
2448
- params = self.omit(params, 'network', 'wallet')
2449
- request = {
2450
- 'method': networkId,
2451
- 'wallet': wallet,
2452
- 'amount': self.number_to_string(amount),
2453
- 'address': address,
2454
- }
2455
- if tag is not None:
2456
- request['payment_id'] = tag
2457
- withdrawOptions = self.safe_value(self.options, 'withdraw', {})
2458
- includeFee = self.safe_bool(withdrawOptions, 'includeFee', False)
2459
- if includeFee:
2460
- request['fee_deduct'] = 1
2461
- response = await self.privatePostAuthWWithdraw(self.extend(request, params))
2462
- #
2463
- # [
2464
- # 1582271520931, # MTS Millisecond Time Stamp of the update
2465
- # "acc_wd-req", # TYPE Purpose of notification "acc_wd-req" account withdrawal request
2466
- # null, # MESSAGE_ID unique ID of the message
2467
- # null, # not documented
2468
- # [
2469
- # 0, # WITHDRAWAL_ID Unique Withdrawal ID
2470
- # null, # PLACEHOLDER
2471
- # "bitcoin", # METHOD Method of withdrawal
2472
- # null, # PAYMENT_ID Payment ID if relevant
2473
- # "exchange", # WALLET Sending wallet
2474
- # 1, # AMOUNT Amount of Withdrawal less fee
2475
- # null, # PLACEHOLDER
2476
- # null, # PLACEHOLDER
2477
- # 0.0004, # WITHDRAWAL_FEE Fee on withdrawal
2478
- # ],
2479
- # null, # CODE null or integer Work in progress
2480
- # "SUCCESS", # STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
2481
- # "Invalid bitcoin address(abcdef)", # TEXT Text of the notification
2482
- # ]
2483
- #
2484
- # in case of failure:
2485
- #
2486
- # [
2487
- # "error",
2488
- # 10001,
2489
- # "Momentary balance check. Please wait few seconds and try the transfer again."
2490
- # ]
2491
- #
2492
- statusMessage = self.safe_string(response, 0)
2493
- if statusMessage == 'error':
2494
- feedback = self.id + ' ' + response
2495
- message = self.safe_string(response, 2, '')
2496
- # same message v1
2497
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2498
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2499
- raise ExchangeError(feedback) # unknown message
2500
- text = self.safe_string(response, 7)
2501
- if text != 'success':
2502
- self.throw_broadly_matched_exception(self.exceptions['broad'], text, text)
2503
- transaction = self.parse_transaction(response, currency)
2504
- return self.extend(transaction, {
2505
- 'address': address,
2506
- })
2507
-
2508
- async def fetch_positions(self, symbols: Strings = None, params={}):
2509
- """
2510
- fetch all open positions
2511
- :see: https://docs.bitfinex.com/reference/rest-auth-positions
2512
- :param str[]|None symbols: list of unified market symbols
2513
- :param dict [params]: extra parameters specific to the exchange API endpoint
2514
- :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2515
- """
2516
- await self.load_markets()
2517
- symbols = self.market_symbols(symbols)
2518
- response = await self.privatePostAuthRPositions(params)
2519
- #
2520
- # [
2521
- # [
2522
- # "tBTCUSD", # SYMBOL
2523
- # "ACTIVE", # STATUS
2524
- # 0.0195, # AMOUNT
2525
- # 8565.0267019, # BASE_PRICE
2526
- # 0, # MARGIN_FUNDING
2527
- # 0, # MARGIN_FUNDING_TYPE
2528
- # -0.33455568705000516, # PL
2529
- # -0.0003117550117425625, # PL_PERC
2530
- # 7045.876419249083, # PRICE_LIQ
2531
- # 3.0673001895895604, # LEVERAGE
2532
- # null, # _PLACEHOLDER
2533
- # 142355652, # POSITION_ID
2534
- # 1574002216000, # MTS_CREATE
2535
- # 1574002216000, # MTS_UPDATE
2536
- # null, # _PLACEHOLDER
2537
- # 0, # TYPE
2538
- # null, # _PLACEHOLDER
2539
- # 0, # COLLATERAL
2540
- # 0, # COLLATERAL_MIN
2541
- # # META
2542
- # {
2543
- # "reason":"TRADE",
2544
- # "order_id":34271018124,
2545
- # "liq_stage":null,
2546
- # "trade_price":"8565.0267019",
2547
- # "trade_amount":"0.0195",
2548
- # "order_id_oppo":34277498022
2549
- # }
2550
- # ]
2551
- # ]
2552
- #
2553
- return self.parse_positions(response, symbols)
2554
-
2555
- def parse_position(self, position, market: Market = None):
2556
- #
2557
- # [
2558
- # "tBTCUSD", # SYMBOL
2559
- # "ACTIVE", # STATUS
2560
- # 0.0195, # AMOUNT
2561
- # 8565.0267019, # BASE_PRICE
2562
- # 0, # MARGIN_FUNDING
2563
- # 0, # MARGIN_FUNDING_TYPE
2564
- # -0.33455568705000516, # PL
2565
- # -0.0003117550117425625, # PL_PERC
2566
- # 7045.876419249083, # PRICE_LIQ
2567
- # 3.0673001895895604, # LEVERAGE
2568
- # null, # _PLACEHOLDER
2569
- # 142355652, # POSITION_ID
2570
- # 1574002216000, # MTS_CREATE
2571
- # 1574002216000, # MTS_UPDATE
2572
- # null, # _PLACEHOLDER
2573
- # 0, # TYPE
2574
- # null, # _PLACEHOLDER
2575
- # 0, # COLLATERAL
2576
- # 0, # COLLATERAL_MIN
2577
- # # META
2578
- # {
2579
- # "reason": "TRADE",
2580
- # "order_id": 34271018124,
2581
- # "liq_stage": null,
2582
- # "trade_price": "8565.0267019",
2583
- # "trade_amount": "0.0195",
2584
- # "order_id_oppo": 34277498022
2585
- # }
2586
- # ]
2587
- #
2588
- marketId = self.safe_string(position, 0)
2589
- amount = self.safe_string(position, 2)
2590
- timestamp = self.safe_integer(position, 12)
2591
- meta = self.safe_string(position, 19)
2592
- tradePrice = self.safe_string(meta, 'trade_price')
2593
- tradeAmount = self.safe_string(meta, 'trade_amount')
2594
- return self.safe_position({
2595
- 'info': position,
2596
- 'id': self.safe_string(position, 11),
2597
- 'symbol': self.safe_symbol(marketId, market),
2598
- 'notional': self.parse_number(amount),
2599
- 'marginMode': 'isolated', # derivatives use isolated, margin uses cross, https://support.bitfinex.com/hc/en-us/articles/360035475374-Derivatives-Trading-on-Bitfinex
2600
- 'liquidationPrice': self.safe_number(position, 8),
2601
- 'entryPrice': self.safe_number(position, 3),
2602
- 'unrealizedPnl': self.safe_number(position, 6),
2603
- 'percentage': self.safe_number(position, 7),
2604
- 'contracts': None,
2605
- 'contractSize': None,
2606
- 'markPrice': None,
2607
- 'lastPrice': None,
2608
- 'side': 'long' if Precise.string_gt(amount, '0') else 'short',
2609
- 'hedged': None,
2610
- 'timestamp': timestamp,
2611
- 'datetime': self.iso8601(timestamp),
2612
- 'lastUpdateTimestamp': self.safe_integer(position, 13),
2613
- 'maintenanceMargin': self.safe_number(position, 18),
2614
- 'maintenanceMarginPercentage': None,
2615
- 'collateral': self.safe_number(position, 17),
2616
- 'initialMargin': self.parse_number(Precise.string_mul(tradeAmount, tradePrice)),
2617
- 'initialMarginPercentage': None,
2618
- 'leverage': self.safe_number(position, 9),
2619
- 'marginRatio': None,
2620
- 'stopLossPrice': None,
2621
- 'takeProfitPrice': None,
2622
- })
2623
-
2624
- def nonce(self):
2625
- return self.milliseconds()
2626
-
2627
- def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2628
- request = '/' + self.implode_params(path, params)
2629
- query = self.omit(params, self.extract_params(path))
2630
- if api == 'v1':
2631
- request = api + request
2632
- else:
2633
- request = self.version + request
2634
- url = self.urls['api'][api] + '/' + request
2635
- if api == 'public':
2636
- if query:
2637
- url += '?' + self.urlencode(query)
2638
- if api == 'private':
2639
- self.check_required_credentials()
2640
- nonce = str(self.nonce())
2641
- body = self.json(query)
2642
- auth = '/api/' + request + nonce + body
2643
- signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha384)
2644
- headers = {
2645
- 'bfx-nonce': nonce,
2646
- 'bfx-apikey': self.apiKey,
2647
- 'bfx-signature': signature,
2648
- 'Content-Type': 'application/json',
2649
- }
2650
- return {'url': url, 'method': method, 'body': body, 'headers': headers}
2651
-
2652
- def handle_errors(self, statusCode, statusText, url, method, headers, body, response, requestHeaders, requestBody):
2653
- # ["error", 11010, "ratelimit: error"]
2654
- if response is not None:
2655
- if not isinstance(response, list):
2656
- message = self.safe_string_2(response, 'message', 'error')
2657
- feedback = self.id + ' ' + body
2658
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2659
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
2660
- raise ExchangeError(self.id + ' ' + body)
2661
- elif response == '':
2662
- raise ExchangeError(self.id + ' returned empty response')
2663
- if statusCode == 429:
2664
- raise RateLimitExceeded(self.id + ' ' + body)
2665
- if statusCode == 500:
2666
- # See https://docs.bitfinex.com/docs/abbreviations-glossary#section-errorinfo-codes
2667
- errorCode = self.safe_string(response, 1, '')
2668
- errorText = self.safe_string(response, 2, '')
2669
- feedback = self.id + ' ' + errorText
2670
- self.throw_broadly_matched_exception(self.exceptions['broad'], errorText, feedback)
2671
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
2672
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorText, feedback)
2673
- raise ExchangeError(self.id + ' ' + errorText + '(#' + errorCode + ')')
2674
- return response
2675
-
2676
- def parse_ledger_entry_type(self, type):
2677
- if type is None:
2678
- return None
2679
- elif type.find('fee') >= 0 or type.find('charged') >= 0:
2680
- return 'fee'
2681
- elif type.find('rebate') >= 0:
2682
- return 'rebate'
2683
- elif type.find('deposit') >= 0 or type.find('withdrawal') >= 0:
2684
- return 'transaction'
2685
- elif type.find('transfer') >= 0:
2686
- return 'transfer'
2687
- elif type.find('payment') >= 0:
2688
- return 'payout'
2689
- elif type.find('exchange') >= 0 or type.find('position') >= 0:
2690
- return 'trade'
2691
- else:
2692
- return type
2693
-
2694
- def parse_ledger_entry(self, item, currency: Currency = None):
2695
- #
2696
- # [
2697
- # [
2698
- # 2531822314, # ID: Ledger identifier
2699
- # "USD", # CURRENCY: The symbol of the currency(ex. "BTC")
2700
- # null, # PLACEHOLDER
2701
- # 1573521810000, # MTS: Timestamp in milliseconds
2702
- # null, # PLACEHOLDER
2703
- # 0.01644445, # AMOUNT: Amount of funds moved
2704
- # 0, # BALANCE: New balance
2705
- # null, # PLACEHOLDER
2706
- # "Settlement @ 185.79 on wallet margin" # DESCRIPTION: Description of ledger transaction
2707
- # ]
2708
- # ]
2709
- #
2710
- type = None
2711
- id = self.safe_string(item, 0)
2712
- currencyId = self.safe_string(item, 1)
2713
- code = self.safe_currency_code(currencyId, currency)
2714
- timestamp = self.safe_integer(item, 3)
2715
- amount = self.safe_number(item, 5)
2716
- after = self.safe_number(item, 6)
2717
- description = self.safe_string(item, 8)
2718
- if description is not None:
2719
- parts = description.split(' @ ')
2720
- first = self.safe_string_lower(parts, 0)
2721
- type = self.parse_ledger_entry_type(first)
2722
- return {
2723
- 'id': id,
2724
- 'direction': None,
2725
- 'account': None,
2726
- 'referenceId': id,
2727
- 'referenceAccount': None,
2728
- 'type': type,
2729
- 'currency': code,
2730
- 'amount': amount,
2731
- 'timestamp': timestamp,
2732
- 'datetime': self.iso8601(timestamp),
2733
- 'before': None,
2734
- 'after': after,
2735
- 'status': None,
2736
- 'fee': None,
2737
- 'info': item,
2738
- }
2739
-
2740
- async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
2741
- """
2742
- fetch the history of changes, actions done by the user or operations that altered balance of the user
2743
- :see: https://docs.bitfinex.com/reference/rest-auth-ledgers
2744
- :param str code: unified currency code, default is None
2745
- :param int [since]: timestamp in ms of the earliest ledger entry, default is None
2746
- :param int [limit]: max number of ledger entrys to return, default is None max is 2500
2747
- :param dict [params]: extra parameters specific to the exchange API endpoint
2748
- :param int [params.until]: timestamp in ms of the latest ledger entry
2749
- :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)
2750
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
2751
- """
2752
- await self.load_markets()
2753
- paginate = False
2754
- paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
2755
- if paginate:
2756
- return await self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params, 2500)
2757
- currency = None
2758
- request = {}
2759
- if since is not None:
2760
- request['start'] = since
2761
- if limit is not None:
2762
- request['limit'] = limit
2763
- request, params = self.handle_until_option('end', request, params)
2764
- response = None
2765
- if code is not None:
2766
- currency = self.currency(code)
2767
- request['currency'] = currency['uppercaseId']
2768
- response = await self.privatePostAuthRLedgersCurrencyHist(self.extend(request, params))
2769
- else:
2770
- response = await self.privatePostAuthRLedgersHist(self.extend(request, params))
2771
- #
2772
- # [
2773
- # [
2774
- # 2531822314, # ID: Ledger identifier
2775
- # "USD", # CURRENCY: The symbol of the currency(ex. "BTC")
2776
- # null, # PLACEHOLDER
2777
- # 1573521810000, # MTS: Timestamp in milliseconds
2778
- # null, # PLACEHOLDER
2779
- # 0.01644445, # AMOUNT: Amount of funds moved
2780
- # 0, # BALANCE: New balance
2781
- # null, # PLACEHOLDER
2782
- # "Settlement @ 185.79 on wallet margin" # DESCRIPTION: Description of ledger transaction
2783
- # ]
2784
- # ]
2785
- #
2786
- return self.parse_ledger(response, currency, since, limit)
2787
-
2788
- async def fetch_funding_rate(self, symbol: str, params={}):
2789
- """
2790
- fetch the current funding rate
2791
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
2792
- :param str symbol: unified market symbol
2793
- :param dict [params]: extra parameters specific to the exchange API endpoint
2794
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2795
- """
2796
- return await self.fetch_funding_rates([symbol], params)
2797
-
2798
- async def fetch_funding_rates(self, symbols: Strings = None, params={}):
2799
- """
2800
- fetch the current funding rate
2801
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
2802
- :param str[] symbols: list of unified market symbols
2803
- :param dict [params]: extra parameters specific to the exchange API endpoint
2804
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2805
- """
2806
- if symbols is None:
2807
- raise ArgumentsRequired(self.id + ' fetchFundingRates() requires a symbols argument')
2808
- await self.load_markets()
2809
- marketIds = self.market_ids(symbols)
2810
- request = {
2811
- 'keys': ','.join(marketIds),
2812
- }
2813
- response = await self.publicGetStatusDeriv(self.extend(request, params))
2814
- #
2815
- # [
2816
- # [
2817
- # "tBTCF0:USTF0",
2818
- # 1691165059000,
2819
- # null,
2820
- # 29297.851276225,
2821
- # 29277.5,
2822
- # null,
2823
- # 36950860.76010306,
2824
- # null,
2825
- # 1691193600000,
2826
- # 0.00000527,
2827
- # 82,
2828
- # null,
2829
- # 0.00014548,
2830
- # null,
2831
- # null,
2832
- # 29278.8925,
2833
- # null,
2834
- # null,
2835
- # 9636.07644994,
2836
- # null,
2837
- # null,
2838
- # null,
2839
- # 0.0005,
2840
- # 0.0025
2841
- # ]
2842
- # ]
2843
- #
2844
- return self.parse_funding_rates(response)
2845
-
2846
- async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2847
- """
2848
- fetches historical funding rate prices
2849
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status-history
2850
- :param str symbol: unified market symbol
2851
- :param int [since]: timestamp in ms of the earliest funding rate entry
2852
- :param int [limit]: max number of funding rate entrys to return
2853
- :param dict [params]: extra parameters specific to the exchange API endpoint
2854
- :param int [params.until]: timestamp in ms of the latest funding rate
2855
- :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)
2856
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
2857
- """
2858
- if symbol is None:
2859
- raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
2860
- await self.load_markets()
2861
- paginate = False
2862
- paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
2863
- if paginate:
2864
- return await self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 5000)
2865
- market = self.market(symbol)
2866
- request = {
2867
- 'symbol': market['id'],
2868
- }
2869
- if since is not None:
2870
- request['start'] = since
2871
- request, params = self.handle_until_option('end', request, params)
2872
- response = await self.publicGetStatusDerivSymbolHist(self.extend(request, params))
2873
- #
2874
- # [
2875
- # [
2876
- # "tBTCF0:USTF0",
2877
- # 1691165059000,
2878
- # null,
2879
- # 29297.851276225,
2880
- # 29277.5,
2881
- # null,
2882
- # 36950860.76010306,
2883
- # null,
2884
- # 1691193600000,
2885
- # 0.00000527,
2886
- # 82,
2887
- # null,
2888
- # 0.00014548,
2889
- # null,
2890
- # null,
2891
- # 29278.8925,
2892
- # null,
2893
- # null,
2894
- # 9636.07644994,
2895
- # null,
2896
- # null,
2897
- # null,
2898
- # 0.0005,
2899
- # 0.0025
2900
- # ]
2901
- # ]
2902
- #
2903
- rates = []
2904
- for i in range(0, len(response)):
2905
- fr = response[i]
2906
- rate = self.parse_funding_rate_history(fr, market)
2907
- rates.append(rate)
2908
- reversedArray = []
2909
- rawRates = self.filter_by_symbol_since_limit(rates, symbol, since, limit)
2910
- ratesLength = len(rawRates)
2911
- for i in range(0, ratesLength):
2912
- index = ratesLength - i - 1
2913
- valueAtIndex = rawRates[index]
2914
- reversedArray.append(valueAtIndex)
2915
- return reversedArray
2916
-
2917
- def parse_funding_rate(self, contract, market: Market = None):
2918
- #
2919
- # [
2920
- # "tBTCF0:USTF0",
2921
- # 1691165059000,
2922
- # null,
2923
- # 29297.851276225,
2924
- # 29277.5,
2925
- # null,
2926
- # 36950860.76010306,
2927
- # null,
2928
- # 1691193600000,
2929
- # 0.00000527,
2930
- # 82,
2931
- # null,
2932
- # 0.00014548,
2933
- # null,
2934
- # null,
2935
- # 29278.8925,
2936
- # null,
2937
- # null,
2938
- # 9636.07644994,
2939
- # null,
2940
- # null,
2941
- # null,
2942
- # 0.0005,
2943
- # 0.0025
2944
- # ]
2945
- #
2946
- marketId = self.safe_string(contract, 0)
2947
- timestamp = self.safe_integer(contract, 1)
2948
- nextFundingTimestamp = self.safe_integer(contract, 8)
2949
- return {
2950
- 'info': contract,
2951
- 'symbol': self.safe_symbol(marketId, market),
2952
- 'markPrice': self.safe_number(contract, 15),
2953
- 'indexPrice': self.safe_number(contract, 3),
2954
- 'interestRate': None,
2955
- 'estimatedSettlePrice': None,
2956
- 'timestamp': timestamp,
2957
- 'datetime': self.iso8601(timestamp),
2958
- 'fundingRate': self.safe_number(contract, 12),
2959
- 'fundingTimestamp': None,
2960
- 'fundingDatetime': None,
2961
- 'nextFundingRate': self.safe_number(contract, 9),
2962
- 'nextFundingTimestamp': nextFundingTimestamp,
2963
- 'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
2964
- 'previousFundingRate': None,
2965
- 'previousFundingTimestamp': None,
2966
- 'previousFundingDatetime': None,
2967
- }
2968
-
2969
- def parse_funding_rate_history(self, contract, market: Market = None):
2970
- #
2971
- # [
2972
- # 1691165494000,
2973
- # null,
2974
- # 29278.95838065,
2975
- # 29260.5,
2976
- # null,
2977
- # 36950860.76010305,
2978
- # null,
2979
- # 1691193600000,
2980
- # 0.00001449,
2981
- # 222,
2982
- # null,
2983
- # 0.00014548,
2984
- # null,
2985
- # null,
2986
- # 29260.005,
2987
- # null,
2988
- # null,
2989
- # 9635.86484562,
2990
- # null,
2991
- # null,
2992
- # null,
2993
- # 0.0005,
2994
- # 0.0025
2995
- # ]
2996
- #
2997
- timestamp = self.safe_integer(contract, 0)
2998
- nextFundingTimestamp = self.safe_integer(contract, 7)
2999
- return {
3000
- 'info': contract,
3001
- 'symbol': self.safe_symbol(None, market),
3002
- 'markPrice': self.safe_number(contract, 14),
3003
- 'indexPrice': self.safe_number(contract, 2),
3004
- 'interestRate': None,
3005
- 'estimatedSettlePrice': None,
3006
- 'timestamp': timestamp,
3007
- 'datetime': self.iso8601(timestamp),
3008
- 'fundingRate': self.safe_number(contract, 11),
3009
- 'fundingTimestamp': None,
3010
- 'fundingDatetime': None,
3011
- 'nextFundingRate': self.safe_number(contract, 8),
3012
- 'nextFundingTimestamp': nextFundingTimestamp,
3013
- 'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
3014
- 'previousFundingRate': None,
3015
- 'previousFundingTimestamp': None,
3016
- 'previousFundingDatetime': None,
3017
- }
3018
-
3019
- async def fetch_open_interest(self, symbol: str, params={}):
3020
- """
3021
- retrieves the open interest of a contract trading pair
3022
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status
3023
- :param str symbol: unified CCXT market symbol
3024
- :param dict [params]: exchange specific parameters
3025
- :returns dict: an `open interest structure <https://docs.ccxt.com/#/?id=open-interest-structure>`
3026
- """
3027
- await self.load_markets()
3028
- market = self.market(symbol)
3029
- request = {
3030
- 'keys': market['id'],
3031
- }
3032
- response = await self.publicGetStatusDeriv(self.extend(request, params))
3033
- #
3034
- # [
3035
- # [
3036
- # "tXRPF0:USTF0", # market id
3037
- # 1706256986000, # millisecond timestamp
3038
- # null,
3039
- # 0.512705, # derivative mid price
3040
- # 0.512395, # underlying spot mid price
3041
- # null,
3042
- # 37671483.04, # insurance fund balance
3043
- # null,
3044
- # 1706284800000, # timestamp of next funding
3045
- # 0.00002353, # accrued funding for next period
3046
- # 317, # next funding step
3047
- # null,
3048
- # 0, # current funding
3049
- # null,
3050
- # null,
3051
- # 0.5123016, # mark price
3052
- # null,
3053
- # null,
3054
- # 2233562.03115, # open interest in contracts
3055
- # null,
3056
- # null,
3057
- # null,
3058
- # 0.0005, # average spread without funding payment
3059
- # 0.0025 # funding payment cap
3060
- # ]
3061
- # ]
3062
- #
3063
- oi = self.safe_list(response, 0)
3064
- return self.parse_open_interest(oi, market)
3065
-
3066
- async def fetch_open_interest_history(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
3067
- """
3068
- retrieves the open interest history of a currency
3069
- :see: https://docs.bitfinex.com/reference/rest-public-derivatives-status-history
3070
- :param str symbol: unified CCXT market symbol
3071
- :param str timeframe: the time period of each row of data, not used by bitfinex2
3072
- :param int [since]: the time in ms of the earliest record to retrieve unix timestamp
3073
- :param int [limit]: the number of records in the response
3074
- :param dict [params]: exchange specific parameters
3075
- :param int [params.until]: the time in ms of the latest record to retrieve unix timestamp
3076
- :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)
3077
- :returns: An array of `open interest structures <https://docs.ccxt.com/#/?id=open-interest-structure>`
3078
- """
3079
- await self.load_markets()
3080
- paginate = False
3081
- paginate, params = self.handle_option_and_params(params, 'fetchOpenInterestHistory', 'paginate')
3082
- if paginate:
3083
- return await self.fetch_paginated_call_deterministic('fetchOpenInterestHistory', symbol, since, limit, '8h', params, 5000)
3084
- market = self.market(symbol)
3085
- request = {
3086
- 'symbol': market['id'],
3087
- }
3088
- if since is not None:
3089
- request['start'] = since
3090
- if limit is not None:
3091
- request['limit'] = limit
3092
- request, params = self.handle_until_option('end', request, params)
3093
- response = await self.publicGetStatusDerivSymbolHist(self.extend(request, params))
3094
- #
3095
- # [
3096
- # [
3097
- # 1706295191000, # timestamp
3098
- # null,
3099
- # 42152.425382, # derivative mid price
3100
- # 42133, # spot mid price
3101
- # null,
3102
- # 37671589.7853521, # insurance fund balance
3103
- # null,
3104
- # 1706313600000, # timestamp of next funding
3105
- # 0.00018734, # accrued funding for next period
3106
- # 3343, # next funding step
3107
- # null,
3108
- # 0.00007587, # current funding
3109
- # null,
3110
- # null,
3111
- # 42134.1, # mark price
3112
- # null,
3113
- # null,
3114
- # 5775.20348804, # open interest number of contracts
3115
- # null,
3116
- # null,
3117
- # null,
3118
- # 0.0005, # average spread without funding payment
3119
- # 0.0025 # funding payment cap
3120
- # ],
3121
- # ]
3122
- #
3123
- return self.parse_open_interests(response, market, since, limit)
3124
-
3125
- def parse_open_interest(self, interest, market: Market = None):
3126
- #
3127
- # fetchOpenInterest:
3128
- #
3129
- # [
3130
- # "tXRPF0:USTF0", # market id
3131
- # 1706256986000, # millisecond timestamp
3132
- # null,
3133
- # 0.512705, # derivative mid price
3134
- # 0.512395, # underlying spot mid price
3135
- # null,
3136
- # 37671483.04, # insurance fund balance
3137
- # null,
3138
- # 1706284800000, # timestamp of next funding
3139
- # 0.00002353, # accrued funding for next period
3140
- # 317, # next funding step
3141
- # null,
3142
- # 0, # current funding
3143
- # null,
3144
- # null,
3145
- # 0.5123016, # mark price
3146
- # null,
3147
- # null,
3148
- # 2233562.03115, # open interest in contracts
3149
- # null,
3150
- # null,
3151
- # null,
3152
- # 0.0005, # average spread without funding payment
3153
- # 0.0025 # funding payment cap
3154
- # ]
3155
- #
3156
- # fetchOpenInterestHistory:
3157
- #
3158
- # [
3159
- # 1706295191000, # timestamp
3160
- # null,
3161
- # 42152.425382, # derivative mid price
3162
- # 42133, # spot mid price
3163
- # null,
3164
- # 37671589.7853521, # insurance fund balance
3165
- # null,
3166
- # 1706313600000, # timestamp of next funding
3167
- # 0.00018734, # accrued funding for next period
3168
- # 3343, # next funding step
3169
- # null,
3170
- # 0.00007587, # current funding
3171
- # null,
3172
- # null,
3173
- # 42134.1, # mark price
3174
- # null,
3175
- # null,
3176
- # 5775.20348804, # open interest number of contracts
3177
- # null,
3178
- # null,
3179
- # null,
3180
- # 0.0005, # average spread without funding payment
3181
- # 0.0025 # funding payment cap
3182
- # ]
3183
- #
3184
- interestLength = len(interest)
3185
- openInterestIndex = 17 if (interestLength == 23) else 18
3186
- timestamp = self.safe_integer(interest, 1)
3187
- marketId = self.safe_string(interest, 0)
3188
- return self.safe_open_interest({
3189
- 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
3190
- 'openInterestAmount': self.safe_number(interest, openInterestIndex),
3191
- 'openInterestValue': None,
3192
- 'timestamp': timestamp,
3193
- 'datetime': self.iso8601(timestamp),
3194
- 'info': interest,
3195
- }, market)
3196
-
3197
- async def fetch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
3198
- """
3199
- retrieves the public liquidations of a trading pair
3200
- :see: https://docs.bitfinex.com/reference/rest-public-liquidations
3201
- :param str symbol: unified CCXT market symbol
3202
- :param int [since]: the earliest time in ms to fetch liquidations for
3203
- :param int [limit]: the maximum number of liquidation structures to retrieve
3204
- :param dict [params]: exchange specific parameters
3205
- :param int [params.until]: timestamp in ms of the latest liquidation
3206
- :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)
3207
- :returns dict: an array of `liquidation structures <https://docs.ccxt.com/#/?id=liquidation-structure>`
3208
- """
3209
- await self.load_markets()
3210
- paginate = False
3211
- paginate, params = self.handle_option_and_params(params, 'fetchLiquidations', 'paginate')
3212
- if paginate:
3213
- return await self.fetch_paginated_call_deterministic('fetchLiquidations', symbol, since, limit, '8h', params, 500)
3214
- market = self.market(symbol)
3215
- request = {}
3216
- if since is not None:
3217
- request['start'] = since
3218
- if limit is not None:
3219
- request['limit'] = limit
3220
- request, params = self.handle_until_option('end', request, params)
3221
- response = await self.publicGetLiquidationsHist(self.extend(request, params))
3222
- #
3223
- # [
3224
- # [
3225
- # [
3226
- # "pos",
3227
- # 171085137,
3228
- # 1706395919788,
3229
- # null,
3230
- # "tAVAXF0:USTF0",
3231
- # -8,
3232
- # 32.868,
3233
- # null,
3234
- # 1,
3235
- # 1,
3236
- # null,
3237
- # 33.255
3238
- # ]
3239
- # ],
3240
- # ]
3241
- #
3242
- return self.parse_liquidations(response, market, since, limit)
3243
-
3244
- def parse_liquidation(self, liquidation, market: Market = None):
3245
- #
3246
- # [
3247
- # [
3248
- # "pos",
3249
- # 171085137, # position id
3250
- # 1706395919788, # timestamp
3251
- # null,
3252
- # "tAVAXF0:USTF0", # market id
3253
- # -8, # amount in contracts
3254
- # 32.868, # base price
3255
- # null,
3256
- # 1,
3257
- # 1,
3258
- # null,
3259
- # 33.255 # acquired price
3260
- # ]
3261
- # ]
3262
- #
3263
- entry = liquidation[0]
3264
- timestamp = self.safe_integer(entry, 2)
3265
- marketId = self.safe_string(entry, 4)
3266
- contracts = Precise.string_abs(self.safe_string(entry, 5))
3267
- contractSize = self.safe_string(market, 'contractSize')
3268
- baseValue = Precise.string_mul(contracts, contractSize)
3269
- price = self.safe_string(entry, 11)
3270
- return self.safe_liquidation({
3271
- 'info': entry,
3272
- 'symbol': self.safe_symbol(marketId, market, None, 'contract'),
3273
- 'contracts': self.parse_number(contracts),
3274
- 'contractSize': self.parse_number(contractSize),
3275
- 'price': self.parse_number(price),
3276
- 'baseValue': self.parse_number(baseValue),
3277
- 'quoteValue': self.parse_number(Precise.string_mul(baseValue, price)),
3278
- 'timestamp': timestamp,
3279
- 'datetime': self.iso8601(timestamp),
3280
- })
3281
-
3282
- async def set_margin(self, symbol: str, amount: float, params={}):
3283
- """
3284
- either adds or reduces margin in a swap position in order to set the margin to a specific value
3285
- :see: https://docs.bitfinex.com/reference/rest-auth-deriv-pos-collateral-set
3286
- :param str symbol: unified market symbol of the market to set margin in
3287
- :param float amount: the amount to set the margin to
3288
- :param dict [params]: parameters specific to the exchange API endpoint
3289
- :returns dict: A `margin structure <https://github.com/ccxt/ccxt/wiki/Manual#add-margin-structure>`
3290
- """
3291
- await self.load_markets()
3292
- market = self.market(symbol)
3293
- if not market['swap']:
3294
- raise NotSupported(self.id + ' setMargin() only support swap markets')
3295
- request = {
3296
- 'symbol': market['id'],
3297
- 'collateral': self.parse_to_numeric(amount),
3298
- }
3299
- response = await self.privatePostAuthWDerivCollateralSet(self.extend(request, params))
3300
- #
3301
- # [
3302
- # [
3303
- # 1
3304
- # ]
3305
- # ]
3306
- #
3307
- data = self.safe_value(response, 0)
3308
- return self.parse_margin_modification(data, market)
3309
-
3310
- def parse_margin_modification(self, data, market=None):
3311
- marginStatusRaw = data[0]
3312
- marginStatus = 'ok' if (marginStatusRaw == 1) else 'failed'
3313
- return {
3314
- 'info': data,
3315
- 'type': None,
3316
- 'amount': None,
3317
- 'code': None,
3318
- 'symbol': market['symbol'],
3319
- 'status': marginStatus,
3320
- }
3321
-
3322
- async def fetch_order(self, id: str, symbol: Str = None, params={}):
3323
- """
3324
- fetches information on an order made by the user
3325
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders
3326
- :see: https://docs.bitfinex.com/reference/rest-auth-retrieve-orders-by-symbol
3327
- :param str id: the order id
3328
- :param str [symbol]: unified symbol of the market the order was made in
3329
- :param dict [params]: extra parameters specific to the exchange API endpoint
3330
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3331
- """
3332
- await self.load_markets()
3333
- request = {
3334
- 'id': [self.parse_to_numeric(id)],
3335
- }
3336
- market = None
3337
- response = None
3338
- if symbol is None:
3339
- response = await self.privatePostAuthROrders(self.extend(request, params))
3340
- else:
3341
- market = self.market(symbol)
3342
- request['symbol'] = market['id']
3343
- response = await self.privatePostAuthROrdersSymbol(self.extend(request, params))
3344
- #
3345
- # [
3346
- # [
3347
- # 139658969116,
3348
- # null,
3349
- # 1706843908637,
3350
- # "tBTCUST",
3351
- # 1706843908637,
3352
- # 1706843908638,
3353
- # 0.0001,
3354
- # 0.0001,
3355
- # "EXCHANGE LIMIT",
3356
- # null,
3357
- # null,
3358
- # null,
3359
- # 0,
3360
- # "ACTIVE",
3361
- # null,
3362
- # null,
3363
- # 35000,
3364
- # 0,
3365
- # 0,
3366
- # 0,
3367
- # null,
3368
- # null,
3369
- # null,
3370
- # 0,
3371
- # 0,
3372
- # null,
3373
- # null,
3374
- # null,
3375
- # "API>BFX",
3376
- # null,
3377
- # null,
3378
- # {}
3379
- # ]
3380
- # ]
3381
- #
3382
- order = self.safe_list(response, 0)
3383
- return self.parse_order(order, market)
3384
-
3385
- async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
3386
- """
3387
- edit a trade order
3388
- :see: https://docs.bitfinex.com/reference/rest-auth-update-order
3389
- :param str id: edit order id
3390
- :param str symbol: unified symbol of the market to edit an order in
3391
- :param str type: 'market' or 'limit'
3392
- :param str side: 'buy' or 'sell'
3393
- :param float amount: how much you want to trade in units of the base currency
3394
- :param float [price]: the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
3395
- :param dict [params]: extra parameters specific to the exchange API endpoint
3396
- :param float [params.stopPrice]: the price that triggers a trigger order
3397
- :param boolean [params.postOnly]: set to True if you want to make a post only order
3398
- :param boolean [params.reduceOnly]: indicates that the order is to reduce the size of a position
3399
- :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
3400
- :param int [params.leverage]: leverage for a derivative order, supported by derivative symbol orders only, the value should be between 1 and 100 inclusive
3401
- :param int [params.clientOrderId]: a unique client order id for the order
3402
- :param float [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
3403
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3404
- """
3405
- await self.load_markets()
3406
- market = self.market(symbol)
3407
- request = {
3408
- 'id': self.parse_to_numeric(id),
3409
- }
3410
- if amount is not None:
3411
- amountString = self.amount_to_precision(symbol, amount)
3412
- amountString = amountString if (side == 'buy') else Precise.string_neg(amountString)
3413
- request['amount'] = amountString
3414
- stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
3415
- trailingAmount = self.safe_string(params, 'trailingAmount')
3416
- timeInForce = self.safe_string(params, 'timeInForce')
3417
- postOnlyParam = self.safe_bool(params, 'postOnly', False)
3418
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
3419
- clientOrderId = self.safe_integer_2(params, 'cid', 'clientOrderId')
3420
- if trailingAmount is not None:
3421
- request['price_trailing'] = trailingAmount
3422
- elif stopPrice is not None:
3423
- # request['price'] is taken for stop orders
3424
- request['price'] = self.price_to_precision(symbol, stopPrice)
3425
- if type == 'limit':
3426
- request['price_aux_limit'] = self.price_to_precision(symbol, price)
3427
- postOnly = (postOnlyParam or (timeInForce == 'PO'))
3428
- if (type != 'market') and (stopPrice is None):
3429
- request['price'] = self.price_to_precision(symbol, price)
3430
- # flag values may be summed to combine flags
3431
- flags = 0
3432
- if postOnly:
3433
- flags = self.sum(flags, 4096)
3434
- if reduceOnly:
3435
- flags = self.sum(flags, 1024)
3436
- if flags != 0:
3437
- request['flags'] = flags
3438
- if clientOrderId is not None:
3439
- request['cid'] = clientOrderId
3440
- leverage = self.safe_integer_2(params, 'leverage', 'lev')
3441
- if leverage is not None:
3442
- request['lev'] = leverage
3443
- params = self.omit(params, ['triggerPrice', 'stopPrice', 'timeInForce', 'postOnly', 'reduceOnly', 'trailingAmount', 'clientOrderId', 'leverage'])
3444
- response = await self.privatePostAuthWOrderUpdate(self.extend(request, params))
3445
- #
3446
- # [
3447
- # 1706845376402,
3448
- # "ou-req",
3449
- # null,
3450
- # null,
3451
- # [
3452
- # 139658969116,
3453
- # null,
3454
- # 1706843908637,
3455
- # "tBTCUST",
3456
- # 1706843908637,
3457
- # 1706843908638,
3458
- # 0.0002,
3459
- # 0.0002,
3460
- # "EXCHANGE LIMIT",
3461
- # null,
3462
- # null,
3463
- # null,
3464
- # 0,
3465
- # "ACTIVE",
3466
- # null,
3467
- # null,
3468
- # 35000,
3469
- # 0,
3470
- # 0,
3471
- # 0,
3472
- # null,
3473
- # null,
3474
- # null,
3475
- # 0,
3476
- # 0,
3477
- # null,
3478
- # null,
3479
- # null,
3480
- # "API>BFX",
3481
- # null,
3482
- # null,
3483
- # {}
3484
- # ],
3485
- # null,
3486
- # "SUCCESS",
3487
- # "Submitting update to exchange limit buy order for 0.0002 BTC."
3488
- # ]
3489
- #
3490
- status = self.safe_string(response, 6)
3491
- if status != 'SUCCESS':
3492
- errorCode = response[5]
3493
- errorText = response[7]
3494
- raise ExchangeError(self.id + ' ' + response[6] + ': ' + errorText + '(#' + errorCode + ')')
3495
- order = self.safe_list(response, 4, [])
3496
- return self.parse_order(order, market)