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
ccxt/phemex.py CHANGED
@@ -7,9 +7,10 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
13
14
  from ccxt.base.errors import PermissionDenied
14
15
  from ccxt.base.errors import AccountSuspended
15
16
  from ccxt.base.errors import ArgumentsRequired
@@ -18,12 +19,10 @@ from ccxt.base.errors import BadSymbol
18
19
  from ccxt.base.errors import InsufficientFunds
19
20
  from ccxt.base.errors import InvalidOrder
20
21
  from ccxt.base.errors import OrderNotFound
21
- from ccxt.base.errors import CancelPending
22
22
  from ccxt.base.errors import DuplicateOrderId
23
- from ccxt.base.errors import NotSupported
24
23
  from ccxt.base.errors import DDoSProtection
25
24
  from ccxt.base.errors import RateLimitExceeded
26
- from ccxt.base.errors import AuthenticationError
25
+ from ccxt.base.errors import CancelPending
27
26
  from ccxt.base.decimal_to_precision import TICK_SIZE
28
27
  from ccxt.base.precise import Precise
29
28
 
@@ -65,6 +64,8 @@ class phemex(Exchange, ImplicitAPI):
65
64
  'fetchCrossBorrowRates': False,
66
65
  'fetchCurrencies': True,
67
66
  'fetchDepositAddress': True,
67
+ 'fetchDepositAddresses': False,
68
+ 'fetchDepositAddressesByNetwork': False,
68
69
  'fetchDeposits': True,
69
70
  'fetchFundingHistory': True,
70
71
  'fetchFundingRate': True,
@@ -81,6 +82,7 @@ class phemex(Exchange, ImplicitAPI):
81
82
  'fetchMarkOHLCV': False,
82
83
  'fetchMyTrades': True,
83
84
  'fetchOHLCV': True,
85
+ 'fetchOpenInterest': True,
84
86
  'fetchOpenOrders': True,
85
87
  'fetchOrder': True,
86
88
  'fetchOrderBook': True,
@@ -96,6 +98,7 @@ class phemex(Exchange, ImplicitAPI):
96
98
  'fetchTransfers': True,
97
99
  'fetchWithdrawals': True,
98
100
  'reduceMargin': False,
101
+ 'sandbox': True,
99
102
  'setLeverage': True,
100
103
  'setMargin': True,
101
104
  'setMarginMode': True,
@@ -118,7 +121,7 @@ class phemex(Exchange, ImplicitAPI):
118
121
  'private': 'https://{hostname}',
119
122
  },
120
123
  'www': 'https://phemex.com',
121
- 'doc': 'https://github.com/phemex/phemex-api-docs',
124
+ 'doc': 'https://phemex-docs.github.io/#overview',
122
125
  'fees': 'https://phemex.com/fees-conditions',
123
126
  'referral': {
124
127
  'url': 'https://phemex.com/register?referralCode=EDNVJ',
@@ -176,6 +179,7 @@ class phemex(Exchange, ImplicitAPI):
176
179
  'v2': {
177
180
  'get': {
178
181
  'public/products': 5,
182
+ 'public/products-plus': 5,
179
183
  'md/v2/orderbook': 5, # ?symbol=<symbol>&id=<id>
180
184
  'md/v2/trade': 5, # ?symbol=<symbol>&id=<id>
181
185
  'md/v2/ticker/24hr': 5, # ?symbol=<symbol>&id=<id>
@@ -302,6 +306,109 @@ class phemex(Exchange, ImplicitAPI):
302
306
  'maker': self.parse_number('0.001'),
303
307
  },
304
308
  },
309
+ 'features': {
310
+ 'default': {
311
+ 'sandbox': True,
312
+ 'createOrder': {
313
+ 'marginMode': False,
314
+ 'triggerPrice': True,
315
+ # todo
316
+ 'triggerPriceType': {
317
+ 'mark': True,
318
+ 'last': True,
319
+ 'index': True,
320
+ },
321
+ 'triggerDirection': False,
322
+ 'stopLossPrice': False, # todo
323
+ 'takeProfitPrice': False, # todo
324
+ 'attachedStopLossTakeProfit': None,
325
+ 'timeInForce': {
326
+ 'IOC': True,
327
+ 'FOK': True,
328
+ 'PO': True,
329
+ 'GTD': False,
330
+ },
331
+ 'hedged': False,
332
+ 'leverage': False,
333
+ 'marketBuyByCost': True,
334
+ 'marketBuyRequiresPrice': False,
335
+ 'selfTradePrevention': False,
336
+ 'trailing': False,
337
+ 'iceberg': False,
338
+ },
339
+ 'createOrders': None,
340
+ 'fetchMyTrades': {
341
+ 'marginMode': False,
342
+ 'limit': 200,
343
+ 'daysBack': 100000,
344
+ 'untilDays': 2, # todo implement
345
+ },
346
+ 'fetchOrder': {
347
+ 'marginMode': False,
348
+ 'trigger': False,
349
+ 'trailing': False,
350
+ },
351
+ 'fetchOpenOrders': {
352
+ 'marginMode': False,
353
+ 'limit': None,
354
+ 'trigger': False,
355
+ 'trailing': False,
356
+ },
357
+ 'fetchOrders': {
358
+ 'marginMode': False,
359
+ 'limit': None,
360
+ 'daysBack': None,
361
+ 'untilDays': None,
362
+ 'trigger': False,
363
+ 'trailing': False,
364
+ },
365
+ 'fetchClosedOrders': {
366
+ 'marginMode': False,
367
+ 'limit': 200,
368
+ 'daysBack': 100000,
369
+ 'daysBackCanceled': 100000,
370
+ 'untilDays': 2,
371
+ 'trigger': False,
372
+ 'trailing': False,
373
+ },
374
+ 'fetchOHLCV': {
375
+ 'limit': 1000,
376
+ },
377
+ },
378
+ 'spot': {
379
+ 'extends': 'default',
380
+ },
381
+ 'forDerivatives': {
382
+ 'extends': 'default',
383
+ 'createOrder': {
384
+ 'triggerDirection': True,
385
+ 'attachedStopLossTakeProfit': {
386
+ 'triggerPriceType': {
387
+ 'mark': True,
388
+ 'last': True,
389
+ 'index': True,
390
+ },
391
+ 'price': True,
392
+ },
393
+ 'hedged': True,
394
+ },
395
+ 'fetchOHLCV': {
396
+ 'limit': 2000,
397
+ },
398
+ },
399
+ 'swap': {
400
+ 'linear': {
401
+ 'extends': 'forDerivatives',
402
+ },
403
+ 'inverse': {
404
+ 'extends': 'forDerivatives',
405
+ },
406
+ },
407
+ 'future': {
408
+ 'linear': None,
409
+ 'inverse': None,
410
+ },
411
+ },
305
412
  'requiredCredentials': {
306
413
  'apiKey': True,
307
414
  'secret': True,
@@ -500,6 +607,13 @@ class phemex(Exchange, ImplicitAPI):
500
607
  'transfer': {
501
608
  'fillResponseFromRequest': True,
502
609
  },
610
+ 'triggerPriceTypesMap': {
611
+ 'last': 'ByLastPrice',
612
+ 'mark': 'ByMarkPrice',
613
+ 'index': 'ByIndexPrice',
614
+ 'ask': 'ByAskPrice',
615
+ 'bid': 'ByBidPrice',
616
+ },
503
617
  },
504
618
  })
505
619
 
@@ -511,10 +625,10 @@ class phemex(Exchange, ImplicitAPI):
511
625
  parts = value.split(' ')
512
626
  return self.safe_number(parts, 0)
513
627
 
514
- def parse_swap_market(self, market):
628
+ def parse_swap_market(self, market: dict):
515
629
  #
516
630
  # {
517
- # "symbol":"BTCUSD",
631
+ # "symbol":"BTCUSD", #
518
632
  # "code":"1",
519
633
  # "type":"Perpetual",
520
634
  # "displaySymbol":"BTC / USD",
@@ -522,7 +636,7 @@ class phemex(Exchange, ImplicitAPI):
522
636
  # "markSymbol":".MBTC",
523
637
  # "fundingRateSymbol":".BTCFR",
524
638
  # "fundingRate8hSymbol":".BTCFR8H",
525
- # "contractUnderlyingAssets":"USD",
639
+ # "contractUnderlyingAssets":"USD", # or eg. `1000 SHIB`
526
640
  # "settleCurrency":"BTC",
527
641
  # "quoteCurrency":"USD",
528
642
  # "contractSize":"1 USD",
@@ -566,6 +680,7 @@ class phemex(Exchange, ImplicitAPI):
566
680
  quoteId = self.safe_string(market, 'quoteCurrency')
567
681
  settleId = self.safe_string(market, 'settleCurrency')
568
682
  base = self.safe_currency_code(baseId)
683
+ base = base.replace(' ', '') # replace space for junction codes, eg. `1000 SHIB`
569
684
  quote = self.safe_currency_code(quoteId)
570
685
  settle = self.safe_currency_code(settleId)
571
686
  inverse = False
@@ -646,7 +761,7 @@ class phemex(Exchange, ImplicitAPI):
646
761
  'info': market,
647
762
  })
648
763
 
649
- def parse_spot_market(self, market):
764
+ def parse_spot_market(self, market: dict):
650
765
  #
651
766
  # {
652
767
  # "symbol":"sBTCUSDT",
@@ -743,13 +858,16 @@ class phemex(Exchange, ImplicitAPI):
743
858
  'max': self.parse_safe_number(self.safe_string(market, 'maxOrderValue')),
744
859
  },
745
860
  },
746
- 'created': None,
861
+ 'created': self.safe_integer(market, 'listTime'),
747
862
  'info': market,
748
863
  })
749
864
 
750
- def fetch_markets(self, params={}):
865
+ def fetch_markets(self, params={}) -> List[Market]:
751
866
  """
752
867
  retrieves data on all markets for phemex
868
+
869
+ https://phemex-docs.github.io/#query-product-information-3
870
+
753
871
  :param dict [params]: extra parameters specific to the exchange API endpoint
754
872
  :returns dict[]: an array of objects representing market data
755
873
  """
@@ -971,7 +1089,7 @@ class phemex(Exchange, ImplicitAPI):
971
1089
  result.append(market)
972
1090
  return result
973
1091
 
974
- def fetch_currencies(self, params={}):
1092
+ def fetch_currencies(self, params={}) -> Currencies:
975
1093
  """
976
1094
  fetches all available currencies on an exchange
977
1095
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -994,7 +1112,7 @@ class phemex(Exchange, ImplicitAPI):
994
1112
  # }
995
1113
  data = self.safe_value(response, 'data', {})
996
1114
  currencies = self.safe_value(data, 'currencies', [])
997
- result = {}
1115
+ result: dict = {}
998
1116
  for i in range(0, len(currencies)):
999
1117
  currency = currencies[i]
1000
1118
  id = self.safe_string(currency, 'currency')
@@ -1050,7 +1168,7 @@ class phemex(Exchange, ImplicitAPI):
1050
1168
  ]
1051
1169
 
1052
1170
  def custom_parse_order_book(self, orderbook, symbol, timestamp=None, bidsKey='bids', asksKey='asks', priceKey=0, amountKey=1, market: Market = None):
1053
- result = {
1171
+ result: dict = {
1054
1172
  'symbol': symbol,
1055
1173
  'timestamp': timestamp,
1056
1174
  'datetime': self.iso8601(timestamp),
@@ -1071,7 +1189,9 @@ class phemex(Exchange, ImplicitAPI):
1071
1189
  def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1072
1190
  """
1073
1191
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1074
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorderbook
1192
+
1193
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorderbook
1194
+
1075
1195
  :param str symbol: unified symbol of the market to fetch the order book for
1076
1196
  :param int [limit]: the maximum amount of order book entries to return
1077
1197
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1079,7 +1199,7 @@ class phemex(Exchange, ImplicitAPI):
1079
1199
  """
1080
1200
  self.load_markets()
1081
1201
  market = self.market(symbol)
1082
- request = {
1202
+ request: dict = {
1083
1203
  'symbol': market['id'],
1084
1204
  # 'id': 123456789, # optional request id
1085
1205
  }
@@ -1195,8 +1315,10 @@ class phemex(Exchange, ImplicitAPI):
1195
1315
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1196
1316
  """
1197
1317
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1198
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querykline
1199
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-kline
1318
+
1319
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querykline
1320
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-kline
1321
+
1200
1322
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1201
1323
  :param str timeframe: the length of time each candle represents
1202
1324
  :param int [since]: *only used for USDT settled contracts, otherwise is emulated and not supported by the exchange* timestamp in ms of the earliest candle to fetch
@@ -1208,7 +1330,7 @@ class phemex(Exchange, ImplicitAPI):
1208
1330
  self.load_markets()
1209
1331
  market = self.market(symbol)
1210
1332
  userLimit = limit
1211
- request = {
1333
+ request: dict = {
1212
1334
  'symbol': market['id'],
1213
1335
  'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
1214
1336
  }
@@ -1266,10 +1388,10 @@ class phemex(Exchange, ImplicitAPI):
1266
1388
  # }
1267
1389
  #
1268
1390
  data = self.safe_value(response, 'data', {})
1269
- rows = self.safe_value(data, 'rows', [])
1391
+ rows = self.safe_list(data, 'rows', [])
1270
1392
  return self.parse_ohlcvs(rows, market, timeframe, since, userLimit)
1271
1393
 
1272
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1394
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1273
1395
  #
1274
1396
  # spot
1275
1397
  #
@@ -1359,14 +1481,16 @@ class phemex(Exchange, ImplicitAPI):
1359
1481
  def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1360
1482
  """
1361
1483
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1362
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query24hrsticker
1484
+
1485
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query24hrsticker
1486
+
1363
1487
  :param str symbol: unified symbol of the market to fetch the ticker for
1364
1488
  :param dict [params]: extra parameters specific to the exchange API endpoint
1365
1489
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1366
1490
  """
1367
1491
  self.load_markets()
1368
1492
  market = self.market(symbol)
1369
- request = {
1493
+ request: dict = {
1370
1494
  'symbol': market['id'],
1371
1495
  # 'id': 123456789, # optional request id
1372
1496
  }
@@ -1422,15 +1546,17 @@ class phemex(Exchange, ImplicitAPI):
1422
1546
  # }
1423
1547
  # }
1424
1548
  #
1425
- result = self.safe_value(response, 'result', {})
1549
+ result = self.safe_dict(response, 'result', {})
1426
1550
  return self.parse_ticker(result, market)
1427
1551
 
1428
1552
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1429
1553
  """
1430
1554
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1431
- :see: https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols-2 # spot
1432
- :see: https://phemex-docs.github.io/#query-24-ticker-for-all-symbols # linear
1433
- :see: https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols # inverse
1555
+
1556
+ https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols-2 # spot
1557
+ https://phemex-docs.github.io/#query-24-ticker-for-all-symbols # linear
1558
+ https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols # inverse
1559
+
1434
1560
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1435
1561
  :param dict [params]: extra parameters specific to the exchange API endpoint
1436
1562
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1452,13 +1578,15 @@ class phemex(Exchange, ImplicitAPI):
1452
1578
  response = self.v1GetMdTicker24hrAll(query)
1453
1579
  else:
1454
1580
  response = self.v2GetMdV2Ticker24hrAll(query)
1455
- result = self.safe_value(response, 'result', [])
1581
+ result = self.safe_list(response, 'result', [])
1456
1582
  return self.parse_tickers(result, symbols)
1457
1583
 
1458
1584
  def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1459
1585
  """
1460
1586
  get the list of most recent trades for a particular symbol
1461
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querytrades
1587
+
1588
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querytrades
1589
+
1462
1590
  :param str symbol: unified symbol of the market to fetch trades for
1463
1591
  :param int [since]: timestamp in ms of the earliest trade to fetch
1464
1592
  :param int [limit]: the maximum amount of trades to fetch
@@ -1467,7 +1595,7 @@ class phemex(Exchange, ImplicitAPI):
1467
1595
  """
1468
1596
  self.load_markets()
1469
1597
  market = self.market(symbol)
1470
- request = {
1598
+ request: dict = {
1471
1599
  'symbol': market['id'],
1472
1600
  # 'id': 123456789, # optional request id
1473
1601
  }
@@ -1496,7 +1624,7 @@ class phemex(Exchange, ImplicitAPI):
1496
1624
  trades = self.safe_value_2(result, 'trades', 'trades_p', [])
1497
1625
  return self.parse_trades(trades, market, since, limit)
1498
1626
 
1499
- def parse_trade(self, trade, market: Market = None) -> Trade:
1627
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1500
1628
  #
1501
1629
  # fetchTrades(public) spot & contract
1502
1630
  #
@@ -1657,6 +1785,26 @@ class phemex(Exchange, ImplicitAPI):
1657
1785
  # "execId": "8718cae",
1658
1786
  # "execStatus": 6
1659
1787
  # }
1788
+ # spot with fees paid using PT token
1789
+ # "createdAt": "1714990724076",
1790
+ # "symbol": "BTCUSDT",
1791
+ # "currency": "USDT",
1792
+ # "action": "1",
1793
+ # "tradeType": "1",
1794
+ # "execQtyRq": "0.003",
1795
+ # "execPriceRp": "64935",
1796
+ # "side": "2",
1797
+ # "orderQtyRq": "0.003",
1798
+ # "priceRp": "51600",
1799
+ # "execValueRv": "194.805",
1800
+ # "feeRateRr": "0.000495",
1801
+ # "execFeeRv": "0",
1802
+ # "ordType": "3",
1803
+ # "execId": "XXXXXX",
1804
+ # "execStatus": "7",
1805
+ # "posSide": "1",
1806
+ # "ptFeeRv": "0.110012249248",
1807
+ # "ptPriceRp": "0.876524893"
1660
1808
  #
1661
1809
  priceString: Str
1662
1810
  amountString: Str
@@ -1705,10 +1853,16 @@ class phemex(Exchange, ImplicitAPI):
1705
1853
  priceString = self.safe_string(trade, 'execPriceRp')
1706
1854
  amountString = self.safe_string(trade, 'execQtyRq')
1707
1855
  costString = self.safe_string(trade, 'execValueRv')
1708
- feeCostString = self.safe_string(trade, 'execFeeRv')
1856
+ feeCostString = self.omit_zero(self.safe_string(trade, 'execFeeRv'))
1709
1857
  feeRateString = self.safe_string(trade, 'feeRateRr')
1710
- currencyId = self.safe_string(trade, 'currency')
1711
- feeCurrencyCode = self.safe_currency_code(currencyId)
1858
+ if feeCostString is not None:
1859
+ currencyId = self.safe_string(trade, 'currency')
1860
+ feeCurrencyCode = self.safe_currency_code(currencyId)
1861
+ else:
1862
+ ptFeeRv = self.omit_zero(self.safe_string(trade, 'ptFeeRv'))
1863
+ if ptFeeRv is not None:
1864
+ feeCostString = ptFeeRv
1865
+ feeCurrencyCode = 'PT'
1712
1866
  else:
1713
1867
  side = self.safe_string_lower(trade, 'side')
1714
1868
  type = self.parse_order_type(self.safe_string(trade, 'ordType'))
@@ -1719,7 +1873,7 @@ class phemex(Exchange, ImplicitAPI):
1719
1873
  amountString = self.from_ev(self.safe_string(trade, 'execBaseQtyEv'), market)
1720
1874
  amountString = self.safe_string(trade, 'execQty', amountString)
1721
1875
  costString = self.from_er(self.safe_string_2(trade, 'execQuoteQtyEv', 'execValueEv'), market)
1722
- feeCostString = self.from_er(self.safe_string(trade, 'execFeeEv'), market)
1876
+ feeCostString = self.from_er(self.omit_zero(self.safe_string(trade, 'execFeeEv')), market)
1723
1877
  if feeCostString is not None:
1724
1878
  feeRateString = self.from_er(self.safe_string(trade, 'feeRateEr'), market)
1725
1879
  if market['spot']:
@@ -1729,6 +1883,10 @@ class phemex(Exchange, ImplicitAPI):
1729
1883
  if info is not None:
1730
1884
  settlementCurrencyId = self.safe_string(info, 'settlementCurrency')
1731
1885
  feeCurrencyCode = self.safe_currency_code(settlementCurrencyId)
1886
+ else:
1887
+ feeCostString = self.safe_string(trade, 'ptFeeRv')
1888
+ if feeCostString is not None:
1889
+ feeCurrencyCode = 'PT'
1732
1890
  fee = {
1733
1891
  'cost': feeCostString,
1734
1892
  'rate': feeRateString,
@@ -1776,7 +1934,7 @@ class phemex(Exchange, ImplicitAPI):
1776
1934
  # }
1777
1935
  #
1778
1936
  timestamp = None
1779
- result = {'info': response}
1937
+ result: dict = {'info': response}
1780
1938
  data = self.safe_value(response, 'data', [])
1781
1939
  for i in range(0, len(data)):
1782
1940
  balance = data[i]
@@ -1832,7 +1990,7 @@ class phemex(Exchange, ImplicitAPI):
1832
1990
  # }
1833
1991
  # }
1834
1992
  #
1835
- result = {'info': response}
1993
+ result: dict = {'info': response}
1836
1994
  data = self.safe_value(response, 'data', {})
1837
1995
  balance = self.safe_value(data, 'account', {})
1838
1996
  currencyId = self.safe_string(balance, 'currency')
@@ -1851,9 +2009,11 @@ class phemex(Exchange, ImplicitAPI):
1851
2009
  def fetch_balance(self, params={}) -> Balances:
1852
2010
  """
1853
2011
  query for balance and get the amount of funds available for trading or funds locked in orders
1854
- :see: https://phemex-docs.github.io/#query-wallets
1855
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
1856
- :see: https://phemex-docs.github.io/#query-trading-account-and-positions
2012
+
2013
+ https://phemex-docs.github.io/#query-wallets
2014
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
2015
+ https://phemex-docs.github.io/#query-trading-account-and-positions
2016
+
1857
2017
  :param dict [params]: extra parameters specific to the exchange API endpoint
1858
2018
  :param str [params.type]: spot or swap
1859
2019
  :param str [params.code]: *swap only* currency code of the balance to query(USD, USDT, etc), default is USDT
@@ -1865,7 +2025,7 @@ class phemex(Exchange, ImplicitAPI):
1865
2025
  code = self.safe_string(params, 'code')
1866
2026
  params = self.omit(params, ['code'])
1867
2027
  response = None
1868
- request = {}
2028
+ request: dict = {}
1869
2029
  if (type != 'spot') and (type != 'swap'):
1870
2030
  raise BadRequest(self.id + ' does not support ' + type + ' markets, only spot and swap')
1871
2031
  if type == 'swap':
@@ -2010,8 +2170,8 @@ class phemex(Exchange, ImplicitAPI):
2010
2170
  result = self.parse_swap_balance(response) if (type == 'swap') else self.parse_spot_balance(response)
2011
2171
  return result
2012
2172
 
2013
- def parse_order_status(self, status):
2014
- statuses = {
2173
+ def parse_order_status(self, status: Str):
2174
+ statuses: dict = {
2015
2175
  'Created': 'open',
2016
2176
  'Untriggered': 'open',
2017
2177
  'Deactivated': 'closed',
@@ -2021,6 +2181,7 @@ class phemex(Exchange, ImplicitAPI):
2021
2181
  'PartiallyFilled': 'open',
2022
2182
  'Filled': 'closed',
2023
2183
  'Canceled': 'canceled',
2184
+ 'Suspended': 'canceled',
2024
2185
  '1': 'open',
2025
2186
  '2': 'canceled',
2026
2187
  '3': 'closed',
@@ -2032,8 +2193,8 @@ class phemex(Exchange, ImplicitAPI):
2032
2193
  }
2033
2194
  return self.safe_string(statuses, status, status)
2034
2195
 
2035
- def parse_order_type(self, type):
2036
- types = {
2196
+ def parse_order_type(self, type: Str):
2197
+ types: dict = {
2037
2198
  '1': 'market',
2038
2199
  '2': 'limit',
2039
2200
  '3': 'stop',
@@ -2049,8 +2210,8 @@ class phemex(Exchange, ImplicitAPI):
2049
2210
  }
2050
2211
  return self.safe_string(types, type, type)
2051
2212
 
2052
- def parse_time_in_force(self, timeInForce):
2053
- timeInForces = {
2213
+ def parse_time_in_force(self, timeInForce: Str):
2214
+ timeInForces: dict = {
2054
2215
  'GoodTillCancel': 'GTC',
2055
2216
  'PostOnly': 'PO',
2056
2217
  'ImmediateOrCancel': 'IOC',
@@ -2058,7 +2219,7 @@ class phemex(Exchange, ImplicitAPI):
2058
2219
  }
2059
2220
  return self.safe_string(timeInForces, timeInForce, timeInForce)
2060
2221
 
2061
- def parse_spot_order(self, order, market: Market = None):
2222
+ def parse_spot_order(self, order: dict, market: Market = None):
2062
2223
  #
2063
2224
  # spot
2064
2225
  #
@@ -2137,10 +2298,10 @@ class phemex(Exchange, ImplicitAPI):
2137
2298
  if feeCost is not None:
2138
2299
  fee = {
2139
2300
  'cost': feeCost,
2140
- 'currency': None,
2301
+ 'currency': self.safe_currency_code(self.safe_string(order, 'feeCurrency')),
2141
2302
  }
2142
2303
  timeInForce = self.parse_time_in_force(self.safe_string(order, 'timeInForce'))
2143
- stopPrice = self.parse_number(self.omit_zero(self.from_ep(self.safe_string(order, 'stopPxEp'))))
2304
+ triggerPrice = self.parse_number(self.omit_zero(self.from_ep(self.safe_string(order, 'stopPxEp'))))
2144
2305
  postOnly = (timeInForce == 'PO')
2145
2306
  return self.safe_order({
2146
2307
  'info': order,
@@ -2155,8 +2316,7 @@ class phemex(Exchange, ImplicitAPI):
2155
2316
  'postOnly': postOnly,
2156
2317
  'side': side,
2157
2318
  'price': price,
2158
- 'stopPrice': stopPrice,
2159
- 'triggerPrice': stopPrice,
2319
+ 'triggerPrice': triggerPrice,
2160
2320
  'amount': amount,
2161
2321
  'cost': cost,
2162
2322
  'average': average,
@@ -2168,7 +2328,7 @@ class phemex(Exchange, ImplicitAPI):
2168
2328
  }, market)
2169
2329
 
2170
2330
  def parse_order_side(self, side):
2171
- sides = {
2331
+ sides: dict = {
2172
2332
  '1': 'buy',
2173
2333
  '2': 'sell',
2174
2334
  }
@@ -2282,6 +2442,7 @@ class phemex(Exchange, ImplicitAPI):
2282
2442
  clientOrderId = None
2283
2443
  marketId = self.safe_string(order, 'symbol')
2284
2444
  symbol = self.safe_symbol(marketId, market)
2445
+ market = self.safe_market(marketId, market)
2285
2446
  status = self.parse_order_status(self.safe_string(order, 'ordStatus'))
2286
2447
  side = self.parse_order_side(self.safe_string_lower(order, 'side'))
2287
2448
  type = self.parse_order_type(self.safe_string(order, 'orderType'))
@@ -2299,7 +2460,7 @@ class phemex(Exchange, ImplicitAPI):
2299
2460
  if lastTradeTimestamp == 0:
2300
2461
  lastTradeTimestamp = None
2301
2462
  timeInForce = self.parse_time_in_force(self.safe_string(order, 'timeInForce'))
2302
- stopPrice = self.omit_zero(self.safe_number_2(order, 'stopPx', 'stopPxRp'))
2463
+ triggerPrice = self.omit_zero(self.safe_string_2(order, 'stopPx', 'stopPxRp'))
2303
2464
  postOnly = (timeInForce == 'PO')
2304
2465
  reduceOnly = self.safe_value(order, 'reduceOnly')
2305
2466
  execInst = self.safe_string(order, 'execInst')
@@ -2307,6 +2468,19 @@ class phemex(Exchange, ImplicitAPI):
2307
2468
  reduceOnly = True
2308
2469
  takeProfit = self.safe_string(order, 'takeProfitRp')
2309
2470
  stopLoss = self.safe_string(order, 'stopLossRp')
2471
+ feeValue = self.omit_zero(self.safe_string(order, 'execFeeRv'))
2472
+ ptFeeRv = self.omit_zero(self.safe_string(order, 'ptFeeRv'))
2473
+ fee = None
2474
+ if feeValue is not None:
2475
+ fee = {
2476
+ 'cost': feeValue,
2477
+ 'currency': market['quote'],
2478
+ }
2479
+ elif ptFeeRv is not None:
2480
+ fee = {
2481
+ 'cost': ptFeeRv,
2482
+ 'currency': 'PT',
2483
+ }
2310
2484
  return self.safe_order({
2311
2485
  'info': order,
2312
2486
  'id': id,
@@ -2321,8 +2495,7 @@ class phemex(Exchange, ImplicitAPI):
2321
2495
  'reduceOnly': reduceOnly,
2322
2496
  'side': side,
2323
2497
  'price': price,
2324
- 'stopPrice': stopPrice,
2325
- 'triggerPrice': stopPrice,
2498
+ 'triggerPrice': triggerPrice,
2326
2499
  'takeProfitPrice': takeProfit,
2327
2500
  'stopLossPrice': stopLoss,
2328
2501
  'amount': amount,
@@ -2331,11 +2504,11 @@ class phemex(Exchange, ImplicitAPI):
2331
2504
  'cost': cost,
2332
2505
  'average': None,
2333
2506
  'status': status,
2334
- 'fee': None,
2507
+ 'fee': fee,
2335
2508
  'trades': None,
2336
2509
  })
2337
2510
 
2338
- def parse_order(self, order, market: Market = None) -> Order:
2511
+ def parse_order(self, order: dict, market: Market = None) -> Order:
2339
2512
  isSwap = self.safe_bool(market, 'swap', False)
2340
2513
  hasPnl = ('closedPnl' in order) or ('closedPnlRv' in order) or ('totalPnlRv' in order)
2341
2514
  if isSwap or hasPnl:
@@ -2345,25 +2518,31 @@ class phemex(Exchange, ImplicitAPI):
2345
2518
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2346
2519
  """
2347
2520
  create a trade order
2348
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2521
+
2522
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2523
+ https://phemex-docs.github.io/#place-order-http-put-prefered-3
2524
+
2349
2525
  :param str symbol: unified symbol of the market to create an order in
2350
2526
  :param str type: 'market' or 'limit'
2351
2527
  :param str side: 'buy' or 'sell'
2352
2528
  :param float amount: how much of currency you want to trade in units of base currency
2353
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2529
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2354
2530
  :param dict [params]: extra parameters specific to the exchange API endpoint
2531
+ :param float [params.trigger]: trigger price for conditional orders
2355
2532
  :param dict [params.takeProfit]: *swap only* *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered(perpetual swap markets only)
2356
2533
  :param float [params.takeProfit.triggerPrice]: take profit trigger price
2357
2534
  :param dict [params.stopLoss]: *swap only* *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered(perpetual swap markets only)
2358
2535
  :param float [params.stopLoss.triggerPrice]: stop loss trigger price
2536
+ :param str [params.posSide]: *swap only* "Merged" for one way mode, "Long" for buy side of hedged mode, "Short" for sell side of hedged mode
2537
+ :param bool [params.hedged]: *swap only* True for hedged mode, False for one way mode, default is False
2359
2538
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2360
2539
  """
2361
2540
  self.load_markets()
2362
2541
  market = self.market(symbol)
2363
2542
  requestSide = self.capitalize(side)
2364
2543
  type = self.capitalize(type)
2365
- reduceOnly = self.safe_value(params, 'reduceOnly')
2366
- request = {
2544
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2545
+ request: dict = {
2367
2546
  # common
2368
2547
  'symbol': market['id'],
2369
2548
  'side': requestSide, # Sell, Buy
@@ -2403,18 +2582,24 @@ class phemex(Exchange, ImplicitAPI):
2403
2582
  else:
2404
2583
  request['clOrdID'] = clientOrderId
2405
2584
  params = self.omit(params, ['clOrdID', 'clientOrderId'])
2406
- stopPrice = self.safe_string_n(params, ['stopPx', 'stopPrice', 'triggerPrice'])
2407
- if stopPrice is not None:
2585
+ triggerPrice = self.safe_string_n(params, ['stopPx', 'stopPrice', 'triggerPrice'])
2586
+ if triggerPrice is not None:
2408
2587
  if market['settle'] == 'USDT':
2409
- request['stopPxRp'] = self.price_to_precision(symbol, stopPrice)
2588
+ request['stopPxRp'] = self.price_to_precision(symbol, triggerPrice)
2410
2589
  else:
2411
- request['stopPxEp'] = self.to_ep(stopPrice, market)
2590
+ request['stopPxEp'] = self.to_ep(triggerPrice, market)
2412
2591
  params = self.omit(params, ['stopPx', 'stopPrice', 'stopLoss', 'takeProfit', 'triggerPrice'])
2413
2592
  if market['spot']:
2414
2593
  qtyType = self.safe_value(params, 'qtyType', 'ByBase')
2415
2594
  if (type == 'Market') or (type == 'Stop') or (type == 'MarketIfTouched'):
2416
2595
  if price is not None:
2417
2596
  qtyType = 'ByQuote'
2597
+ if triggerPrice is not None:
2598
+ if type == 'Limit':
2599
+ request['ordType'] = 'StopLimit'
2600
+ elif type == 'Market':
2601
+ request['ordType'] = 'Stop'
2602
+ request['trigger'] = 'ByLastPrice'
2418
2603
  request['qtyType'] = qtyType
2419
2604
  if qtyType == 'ByQuote':
2420
2605
  cost = self.safe_number(params, 'cost')
@@ -2434,55 +2619,70 @@ class phemex(Exchange, ImplicitAPI):
2434
2619
  amountString = self.number_to_string(amount)
2435
2620
  request['baseQtyEv'] = self.to_ev(amountString, market)
2436
2621
  elif market['swap']:
2622
+ hedged = self.safe_bool(params, 'hedged', False)
2623
+ params = self.omit(params, 'hedged')
2437
2624
  posSide = self.safe_string_lower(params, 'posSide')
2438
2625
  if posSide is None:
2439
- posSide = 'Merged'
2626
+ if hedged:
2627
+ if reduceOnly:
2628
+ side = 'sell' if (side == 'buy') else 'buy'
2629
+ posSide = 'Long' if (side == 'buy') else 'Short'
2630
+ else:
2631
+ posSide = 'Merged'
2440
2632
  posSide = self.capitalize(posSide)
2441
2633
  request['posSide'] = posSide
2442
- if reduceOnly is not None:
2443
- request['reduceOnly'] = reduceOnly
2444
2634
  if market['settle'] == 'USDT':
2445
2635
  request['orderQtyRq'] = amount
2446
2636
  else:
2447
2637
  request['orderQty'] = self.parse_to_int(amount)
2448
- if stopPrice is not None:
2638
+ if triggerPrice is not None:
2449
2639
  triggerType = self.safe_string(params, 'triggerType', 'ByMarkPrice')
2450
2640
  request['triggerType'] = triggerType
2641
+ # set direction & exchange specific order type
2642
+ triggerDirection = None
2643
+ triggerDirection, params = self.handle_param_string(params, 'triggerDirection')
2644
+ if triggerDirection is None:
2645
+ raise ArgumentsRequired(self.id + " createOrder() also requires a 'triggerDirection' parameter with either 'up' or 'down' value")
2646
+ # the flow defined per https://phemex-docs.github.io/#more-order-type-examples
2647
+ if triggerDirection == 'up':
2648
+ if side == 'sell':
2649
+ request['ordType'] = 'MarketIfTouched' if (type == 'Market') else 'LimitIfTouched'
2650
+ elif side == 'buy':
2651
+ request['ordType'] = 'Stop' if (type == 'Market') else 'StopLimit'
2652
+ elif triggerDirection == 'down':
2653
+ if side == 'sell':
2654
+ request['ordType'] = 'Stop' if (type == 'Market') else 'StopLimit'
2655
+ elif side == 'buy':
2656
+ request['ordType'] = 'MarketIfTouched' if (type == 'Market') else 'LimitIfTouched'
2451
2657
  if stopLossDefined or takeProfitDefined:
2452
2658
  if stopLossDefined:
2453
2659
  stopLossTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice')
2454
2660
  if stopLossTriggerPrice is None:
2455
- raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"], or params["stopLoss"]["stopPrice"] for a stop loss order')
2661
+ raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"] for a stop loss order')
2456
2662
  if market['settle'] == 'USDT':
2457
2663
  request['stopLossRp'] = self.price_to_precision(symbol, stopLossTriggerPrice)
2458
2664
  else:
2459
2665
  request['stopLossEp'] = self.to_ep(stopLossTriggerPrice, market)
2460
2666
  stopLossTriggerPriceType = self.safe_string_2(stopLoss, 'triggerPriceType', 'slTrigger')
2461
2667
  if stopLossTriggerPriceType is not None:
2462
- if market['settle'] == 'USDT':
2463
- if (stopLossTriggerPriceType != 'ByMarkPrice') and (stopLossTriggerPriceType != 'ByLastPrice') and (stopLossTriggerPriceType != 'ByIndexPrice') and (stopLossTriggerPriceType != 'ByAskPrice') and (stopLossTriggerPriceType != 'ByBidPrice') and (stopLossTriggerPriceType != 'ByMarkPriceLimit') and (stopLossTriggerPriceType != 'ByLastPriceLimit'):
2464
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"')
2465
- else:
2466
- if (stopLossTriggerPriceType != 'ByMarkPrice') and (stopLossTriggerPriceType != 'ByLastPrice'):
2467
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"')
2468
- request['slTrigger'] = stopLossTriggerPriceType
2668
+ request['slTrigger'] = self.safe_string(self.options['triggerPriceTypesMap'], stopLossTriggerPriceType, stopLossTriggerPriceType)
2669
+ slLimitPrice = self.safe_string(stopLoss, 'price')
2670
+ if slLimitPrice is not None:
2671
+ request['slPxRp'] = self.price_to_precision(symbol, slLimitPrice)
2469
2672
  if takeProfitDefined:
2470
2673
  takeProfitTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice')
2471
2674
  if takeProfitTriggerPrice is None:
2472
- raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"], or params["takeProfit"]["stopPrice"] for a take profit order')
2675
+ raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"] for a take profit order')
2473
2676
  if market['settle'] == 'USDT':
2474
2677
  request['takeProfitRp'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
2475
2678
  else:
2476
2679
  request['takeProfitEp'] = self.to_ep(takeProfitTriggerPrice, market)
2477
- takeProfitTriggerPriceType = self.safe_string_2(stopLoss, 'triggerPriceType', 'tpTrigger')
2680
+ takeProfitTriggerPriceType = self.safe_string_2(takeProfit, 'triggerPriceType', 'tpTrigger')
2478
2681
  if takeProfitTriggerPriceType is not None:
2479
- if market['settle'] == 'USDT':
2480
- if (takeProfitTriggerPriceType != 'ByMarkPrice') and (takeProfitTriggerPriceType != 'ByLastPrice') and (takeProfitTriggerPriceType != 'ByIndexPrice') and (takeProfitTriggerPriceType != 'ByAskPrice') and (takeProfitTriggerPriceType != 'ByBidPrice') and (takeProfitTriggerPriceType != 'ByMarkPriceLimit') and (takeProfitTriggerPriceType != 'ByLastPriceLimit'):
2481
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"')
2482
- else:
2483
- if (takeProfitTriggerPriceType != 'ByMarkPrice') and (takeProfitTriggerPriceType != 'ByLastPrice'):
2484
- raise InvalidOrder(self.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"')
2485
- request['tpTrigger'] = takeProfitTriggerPriceType
2682
+ request['tpTrigger'] = self.safe_string(self.options['triggerPriceTypesMap'], takeProfitTriggerPriceType, takeProfitTriggerPriceType)
2683
+ tpLimitPrice = self.safe_string(takeProfit, 'price')
2684
+ if tpLimitPrice is not None:
2685
+ request['tpPxRp'] = self.price_to_precision(symbol, tpLimitPrice)
2486
2686
  if (type == 'Limit') or (type == 'StopLimit') or (type == 'LimitIfTouched'):
2487
2687
  if market['settle'] == 'USDT':
2488
2688
  request['priceRp'] = self.price_to_precision(symbol, price)
@@ -2587,26 +2787,28 @@ class phemex(Exchange, ImplicitAPI):
2587
2787
  # }
2588
2788
  # }
2589
2789
  #
2590
- data = self.safe_value(response, 'data', {})
2790
+ data = self.safe_dict(response, 'data', {})
2591
2791
  return self.parse_order(data, market)
2592
2792
 
2593
2793
  def edit_order(self, id: str, symbol: str, type: OrderType = None, side: OrderSide = None, amount: Num = None, price: Num = None, params={}):
2594
2794
  """
2595
2795
  edit a trade order
2596
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
2796
+
2797
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
2798
+
2597
2799
  :param str id: cancel order id
2598
2800
  :param str symbol: unified symbol of the market to create an order in
2599
2801
  :param str type: 'market' or 'limit'
2600
2802
  :param str side: 'buy' or 'sell'
2601
2803
  :param float amount: how much of currency you want to trade in units of base currency
2602
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2804
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2603
2805
  :param dict [params]: extra parameters specific to the exchange API endpoint
2604
2806
  :param str [params.posSide]: either 'Merged' or 'Long' or 'Short'
2605
2807
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2606
2808
  """
2607
2809
  self.load_markets()
2608
2810
  market = self.market(symbol)
2609
- request = {
2811
+ request: dict = {
2610
2812
  'symbol': market['id'],
2611
2813
  }
2612
2814
  clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clOrdID')
@@ -2631,13 +2833,13 @@ class phemex(Exchange, ImplicitAPI):
2631
2833
  request['orderQtyRq'] = self.amount_to_precision(market['symbol'], amount)
2632
2834
  else:
2633
2835
  request['baseQtyEV'] = self.to_ev(amount, market)
2634
- stopPrice = self.safe_string_2(params, 'stopPx', 'stopPrice')
2635
- if stopPrice is not None:
2836
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPx', 'stopPrice'])
2837
+ if triggerPrice is not None:
2636
2838
  if isUSDTSettled:
2637
- request['stopPxRp'] = self.price_to_precision(symbol, stopPrice)
2839
+ request['stopPxRp'] = self.price_to_precision(symbol, triggerPrice)
2638
2840
  else:
2639
- request['stopPxEp'] = self.to_ep(stopPrice, market)
2640
- params = self.omit(params, ['stopPx', 'stopPrice'])
2841
+ request['stopPxEp'] = self.to_ep(triggerPrice, market)
2842
+ params = self.omit(params, ['triggerPrice', 'stopPx', 'stopPrice'])
2641
2843
  response = None
2642
2844
  if isUSDTSettled:
2643
2845
  posSide = self.safe_string(params, 'posSide')
@@ -2648,13 +2850,15 @@ class phemex(Exchange, ImplicitAPI):
2648
2850
  response = self.privatePutOrdersReplace(self.extend(request, params))
2649
2851
  else:
2650
2852
  response = self.privatePutSpotOrders(self.extend(request, params))
2651
- data = self.safe_value(response, 'data', {})
2853
+ data = self.safe_dict(response, 'data', {})
2652
2854
  return self.parse_order(data, market)
2653
2855
 
2654
2856
  def cancel_order(self, id: str, symbol: Str = None, params={}):
2655
2857
  """
2656
2858
  cancels an open order
2657
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancel-single-order-by-orderid
2859
+
2860
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancel-single-order-by-orderid
2861
+
2658
2862
  :param str id: order id
2659
2863
  :param str symbol: unified symbol of the market the order was made in
2660
2864
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2665,7 +2869,7 @@ class phemex(Exchange, ImplicitAPI):
2665
2869
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
2666
2870
  self.load_markets()
2667
2871
  market = self.market(symbol)
2668
- request = {
2872
+ request: dict = {
2669
2873
  'symbol': market['id'],
2670
2874
  }
2671
2875
  clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clOrdID')
@@ -2684,13 +2888,15 @@ class phemex(Exchange, ImplicitAPI):
2684
2888
  response = self.privateDeleteOrdersCancel(self.extend(request, params))
2685
2889
  else:
2686
2890
  response = self.privateDeleteSpotOrders(self.extend(request, params))
2687
- data = self.safe_value(response, 'data', {})
2891
+ data = self.safe_dict(response, 'data', {})
2688
2892
  return self.parse_order(data, market)
2689
2893
 
2690
2894
  def cancel_all_orders(self, symbol: Str = None, params={}):
2691
2895
  """
2692
2896
  cancel all open orders in a market
2693
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancelall
2897
+
2898
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancelall
2899
+
2694
2900
  :param str symbol: unified market symbol of the market to cancel orders in
2695
2901
  :param dict [params]: extra parameters specific to the exchange API endpoint
2696
2902
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2699,23 +2905,58 @@ class phemex(Exchange, ImplicitAPI):
2699
2905
  raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
2700
2906
  self.load_markets()
2701
2907
  market = self.market(symbol)
2702
- request = {
2908
+ trigger = self.safe_value_2(params, 'stop', 'trigger', False)
2909
+ params = self.omit(params, ['stop', 'trigger'])
2910
+ request: dict = {
2703
2911
  'symbol': market['id'],
2704
2912
  # 'untriggerred': False, # False to cancel non-conditional orders, True to cancel conditional orders
2705
2913
  # 'text': 'up to 40 characters max',
2706
2914
  }
2915
+ if trigger:
2916
+ request['untriggerred'] = trigger
2707
2917
  response = None
2708
2918
  if market['settle'] == 'USDT':
2709
2919
  response = self.privateDeleteGOrdersAll(self.extend(request, params))
2920
+ #
2921
+ # {
2922
+ # code: '0',
2923
+ # msg: '',
2924
+ # data: '1'
2925
+ # }
2926
+ #
2710
2927
  elif market['swap']:
2711
2928
  response = self.privateDeleteOrdersAll(self.extend(request, params))
2929
+ #
2930
+ # {
2931
+ # code: '0',
2932
+ # msg: '',
2933
+ # data: '1'
2934
+ # }
2935
+ #
2712
2936
  else:
2713
2937
  response = self.privateDeleteSpotOrdersAll(self.extend(request, params))
2714
- return response
2938
+ #
2939
+ # {
2940
+ # code: '0',
2941
+ # msg: '',
2942
+ # data: {
2943
+ # total: '1'
2944
+ # }
2945
+ # }
2946
+ #
2947
+ return [
2948
+ self.safe_order({
2949
+ 'info': response,
2950
+ }),
2951
+ ]
2715
2952
 
2716
2953
  def fetch_order(self, id: str, symbol: Str = None, params={}):
2717
2954
  """
2955
+
2956
+ https://phemex-docs.github.io/#query-orders-by-ids
2957
+
2718
2958
  fetches information on an order made by the user
2959
+ :param str id: the order id
2719
2960
  :param str symbol: unified symbol of the market the order was made in
2720
2961
  :param dict [params]: extra parameters specific to the exchange API endpoint
2721
2962
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2724,9 +2965,7 @@ class phemex(Exchange, ImplicitAPI):
2724
2965
  raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
2725
2966
  self.load_markets()
2726
2967
  market = self.market(symbol)
2727
- if market['settle'] == 'USDT':
2728
- raise NotSupported(self.id + 'fetchOrder() is not supported yet for USDT settled swap markets') # https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-order-by-orderid-or-query-user-order-by-client-order-id
2729
- request = {
2968
+ request: dict = {
2730
2969
  'symbol': market['id'],
2731
2970
  }
2732
2971
  clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clOrdID')
@@ -2736,8 +2975,10 @@ class phemex(Exchange, ImplicitAPI):
2736
2975
  else:
2737
2976
  request['orderID'] = id
2738
2977
  response = None
2739
- if market['spot']:
2740
- response = self.privateGetSpotOrdersActive(self.extend(request, params))
2978
+ if market['settle'] == 'USDT':
2979
+ response = self.privateGetApiDataGFuturesOrdersByOrderId(self.extend(request, params))
2980
+ elif market['spot']:
2981
+ response = self.privateGetApiDataSpotsOrdersByOrderId(self.extend(request, params))
2741
2982
  else:
2742
2983
  response = self.privateGetExchangeOrder(self.extend(request, params))
2743
2984
  data = self.safe_value(response, 'data', {})
@@ -2749,13 +2990,18 @@ class phemex(Exchange, ImplicitAPI):
2749
2990
  raise OrderNotFound(self.id + ' fetchOrder() ' + symbol + ' order with clientOrderId ' + clientOrderId + ' not found')
2750
2991
  else:
2751
2992
  raise OrderNotFound(self.id + ' fetchOrder() ' + symbol + ' order with id ' + id + ' not found')
2752
- order = self.safe_value(data, 0, {})
2993
+ order = self.safe_dict(data, 0, {})
2994
+ elif market['spot']:
2995
+ rows = self.safe_list(data, 'rows', [])
2996
+ order = self.safe_dict(rows, 0, {})
2753
2997
  return self.parse_order(order, market)
2754
2998
 
2755
2999
  def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2756
3000
  """
2757
3001
  fetches information on multiple orders made by the user
2758
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3002
+
3003
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3004
+
2759
3005
  :param str symbol: unified market symbol of the market orders were made in
2760
3006
  :param int [since]: the earliest time in ms to fetch orders for
2761
3007
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2766,7 +3012,7 @@ class phemex(Exchange, ImplicitAPI):
2766
3012
  raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
2767
3013
  self.load_markets()
2768
3014
  market = self.market(symbol)
2769
- request = {
3015
+ request: dict = {
2770
3016
  'symbol': market['id'],
2771
3017
  }
2772
3018
  if since is not None:
@@ -2780,17 +3026,19 @@ class phemex(Exchange, ImplicitAPI):
2780
3026
  elif market['swap']:
2781
3027
  response = self.privateGetExchangeOrderList(self.extend(request, params))
2782
3028
  else:
2783
- response = self.privateGetSpotOrders(self.extend(request, params))
3029
+ response = self.privateGetApiDataSpotsOrders(self.extend(request, params))
2784
3030
  data = self.safe_value(response, 'data', {})
2785
- rows = self.safe_value(data, 'rows', data)
3031
+ rows = self.safe_list(data, 'rows', data)
2786
3032
  return self.parse_orders(rows, market, since, limit)
2787
3033
 
2788
3034
  def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2789
3035
  """
2790
3036
  fetch all unfilled currently open orders
2791
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryopenorder
2792
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md
2793
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotListAllOpenOrder
3037
+
3038
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryopenorder
3039
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md
3040
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotListAllOpenOrder
3041
+
2794
3042
  :param str symbol: unified market symbol
2795
3043
  :param int [since]: the earliest time in ms to fetch open orders for
2796
3044
  :param int [limit]: the maximum number of open order structures to retrieve
@@ -2802,7 +3050,7 @@ class phemex(Exchange, ImplicitAPI):
2802
3050
  raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument')
2803
3051
  self.load_markets()
2804
3052
  market = self.market(symbol)
2805
- request = {
3053
+ request: dict = {
2806
3054
  'symbol': market['id'],
2807
3055
  }
2808
3056
  response = None
@@ -2821,16 +3069,18 @@ class phemex(Exchange, ImplicitAPI):
2821
3069
  if isinstance(data, list):
2822
3070
  return self.parse_orders(data, market, since, limit)
2823
3071
  else:
2824
- rows = self.safe_value(data, 'rows', [])
3072
+ rows = self.safe_list(data, 'rows', [])
2825
3073
  return self.parse_orders(rows, market, since, limit)
2826
3074
 
2827
3075
  def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2828
3076
  """
2829
3077
  fetches information on multiple closed orders made by the user
2830
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
2831
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#queryorder
2832
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedgedd-Perpetual-API.md#query-closed-orders-by-symbol
2833
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataOrdersByIds
3078
+
3079
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3080
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#queryorder
3081
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedgedd-Perpetual-API.md#query-closed-orders-by-symbol
3082
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataOrdersByIds
3083
+
2834
3084
  :param str symbol: unified market symbol of the market orders were made in
2835
3085
  :param int [since]: the earliest time in ms to fetch orders for
2836
3086
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2842,7 +3092,7 @@ class phemex(Exchange, ImplicitAPI):
2842
3092
  market = None
2843
3093
  if symbol is not None:
2844
3094
  market = self.market(symbol)
2845
- request = {
3095
+ request: dict = {
2846
3096
  }
2847
3097
  if market is not None:
2848
3098
  request['symbol'] = market['id']
@@ -2898,15 +3148,17 @@ class phemex(Exchange, ImplicitAPI):
2898
3148
  if isinstance(data, list):
2899
3149
  return self.parse_orders(data, market, since, limit)
2900
3150
  else:
2901
- rows = self.safe_value(data, 'rows', [])
3151
+ rows = self.safe_list(data, 'rows', [])
2902
3152
  return self.parse_orders(rows, market, since, limit)
2903
3153
 
2904
3154
  def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2905
3155
  """
2906
3156
  fetch all trades made by the user
2907
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-user-trade
2908
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-trade
2909
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataTradesHist
3157
+
3158
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-user-trade
3159
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-trade
3160
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#spotDataTradesHist
3161
+
2910
3162
  :param str symbol: unified market symbol
2911
3163
  :param int [since]: the earliest time in ms to fetch trades for
2912
3164
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -2917,7 +3169,7 @@ class phemex(Exchange, ImplicitAPI):
2917
3169
  market = None
2918
3170
  if symbol is not None:
2919
3171
  market = self.market(symbol)
2920
- request = {}
3172
+ request: dict = {}
2921
3173
  if limit is not None:
2922
3174
  limit = min(200, limit)
2923
3175
  request['limit'] = limit
@@ -3050,7 +3302,7 @@ class phemex(Exchange, ImplicitAPI):
3050
3302
  data = self.safe_value(data, 'rows', [])
3051
3303
  return self.parse_trades(data, market, since, limit)
3052
3304
 
3053
- def fetch_deposit_address(self, code: str, params={}):
3305
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
3054
3306
  """
3055
3307
  fetch the deposit address for a currency associated with self account
3056
3308
  :param str code: unified currency code
@@ -3059,12 +3311,12 @@ class phemex(Exchange, ImplicitAPI):
3059
3311
  """
3060
3312
  self.load_markets()
3061
3313
  currency = self.currency(code)
3062
- request = {
3314
+ request: dict = {
3063
3315
  'currency': currency['id'],
3064
3316
  }
3065
- defaultNetworks = self.safe_value(self.options, 'defaultNetworks')
3317
+ defaultNetworks = self.safe_dict(self.options, 'defaultNetworks')
3066
3318
  defaultNetwork = self.safe_string_upper(defaultNetworks, code)
3067
- networks = self.safe_value(self.options, 'networks', {})
3319
+ networks = self.safe_dict(self.options, 'networks', {})
3068
3320
  network = self.safe_string_upper(params, 'network', defaultNetwork)
3069
3321
  network = self.safe_string(networks, network, network)
3070
3322
  if network is None:
@@ -3087,11 +3339,11 @@ class phemex(Exchange, ImplicitAPI):
3087
3339
  tag = self.safe_string(data, 'tag')
3088
3340
  self.check_address(address)
3089
3341
  return {
3342
+ 'info': response,
3090
3343
  'currency': code,
3344
+ 'network': None,
3091
3345
  'address': address,
3092
3346
  'tag': tag,
3093
- 'network': None,
3094
- 'info': response,
3095
3347
  }
3096
3348
 
3097
3349
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -3168,8 +3420,8 @@ class phemex(Exchange, ImplicitAPI):
3168
3420
  data = self.safe_list(response, 'data', [])
3169
3421
  return self.parse_transactions(data, currency, since, limit)
3170
3422
 
3171
- def parse_transaction_status(self, status):
3172
- statuses = {
3423
+ def parse_transaction_status(self, status: Str):
3424
+ statuses: dict = {
3173
3425
  'Success': 'ok',
3174
3426
  'Succeed': 'ok',
3175
3427
  'Rejected': 'failed',
@@ -3188,7 +3440,7 @@ class phemex(Exchange, ImplicitAPI):
3188
3440
  }
3189
3441
  return self.safe_string(statuses, status, status)
3190
3442
 
3191
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
3443
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
3192
3444
  #
3193
3445
  # withdraw
3194
3446
  #
@@ -3306,18 +3558,22 @@ class phemex(Exchange, ImplicitAPI):
3306
3558
  def fetch_positions(self, symbols: Strings = None, params={}):
3307
3559
  """
3308
3560
  fetch all open positions
3309
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-trading-account-and-positions
3310
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
3311
- :see: https://phemex-docs.github.io/#query-account-positions-with-unrealized-pnl
3561
+
3562
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-trading-account-and-positions
3563
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
3564
+ https://phemex-docs.github.io/#query-account-positions-with-unrealized-pnl
3565
+
3312
3566
  :param str[] [symbols]: list of unified market symbols
3313
3567
  :param dict [params]: extra parameters specific to the exchange API endpoint
3314
- :param str [param.method]: *USDT contracts only* 'privateGetGAccountsAccountPositions' or 'privateGetAccountsPositions' default is 'privateGetGAccountsAccountPositions'
3568
+ :param str [params.code]: the currency code to fetch positions for, USD, BTC or USDT, USD is the default
3569
+ :param str [params.method]: *USDT contracts only* 'privateGetGAccountsAccountPositions' or 'privateGetAccountsPositions' default is 'privateGetGAccountsAccountPositions'
3315
3570
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3316
3571
  """
3317
3572
  self.load_markets()
3318
3573
  symbols = self.market_symbols(symbols)
3319
3574
  subType = None
3320
- code = self.safe_string(params, 'currency')
3575
+ code = self.safe_string_2(params, 'currency', 'code', 'USD')
3576
+ params = self.omit(params, ['currency', 'code'])
3321
3577
  settle = None
3322
3578
  market = None
3323
3579
  firstSymbol = self.safe_string(symbols, 0)
@@ -3326,17 +3582,17 @@ class phemex(Exchange, ImplicitAPI):
3326
3582
  settle = market['settle']
3327
3583
  code = market['settle']
3328
3584
  else:
3329
- settle, params = self.handle_option_and_params(params, 'fetchPositions', 'settle', 'USD')
3585
+ settle, params = self.handle_option_and_params(params, 'fetchPositions', 'settle', code)
3330
3586
  subType, params = self.handle_sub_type_and_params('fetchPositions', market, params)
3331
3587
  isUSDTSettled = settle == 'USDT'
3332
3588
  if isUSDTSettled:
3333
3589
  code = 'USDT'
3590
+ elif settle == 'BTC':
3591
+ code = 'BTC'
3334
3592
  elif code is None:
3335
3593
  code = 'USD' if (subType == 'linear') else 'BTC'
3336
- else:
3337
- params = self.omit(params, 'code')
3338
3594
  currency = self.currency(code)
3339
- request = {
3595
+ request: dict = {
3340
3596
  'currency': currency['id'],
3341
3597
  }
3342
3598
  response = None
@@ -3433,7 +3689,7 @@ class phemex(Exchange, ImplicitAPI):
3433
3689
  result.append(self.parse_position(position))
3434
3690
  return self.filter_by_array_positions(result, 'symbol', symbols, False)
3435
3691
 
3436
- def parse_position(self, position, market: Market = None):
3692
+ def parse_position(self, position: dict, market: Market = None):
3437
3693
  #
3438
3694
  # {
3439
3695
  # "userID": "811370",
@@ -3574,7 +3830,9 @@ class phemex(Exchange, ImplicitAPI):
3574
3830
  def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3575
3831
  """
3576
3832
  fetch the history of funding payments paid and received on self account
3577
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#futureDataFundingFeesHist
3833
+
3834
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#futureDataFundingFeesHist
3835
+
3578
3836
  :param str symbol: unified market symbol
3579
3837
  :param int [since]: the earliest time in ms to fetch funding history for
3580
3838
  :param int [limit]: the maximum number of funding history structures to retrieve
@@ -3585,7 +3843,7 @@ class phemex(Exchange, ImplicitAPI):
3585
3843
  raise ArgumentsRequired(self.id + ' fetchFundingHistory() requires a symbol argument')
3586
3844
  self.load_markets()
3587
3845
  market = self.market(symbol)
3588
- request = {
3846
+ request: dict = {
3589
3847
  'symbol': market['id'],
3590
3848
  # 'limit': 20, # Page size default 20, max 200
3591
3849
  # 'offset': 0, # Page start default 0
@@ -3595,7 +3853,8 @@ class phemex(Exchange, ImplicitAPI):
3595
3853
  raise BadRequest(self.id + ' fetchFundingHistory() limit argument cannot exceed 200')
3596
3854
  request['limit'] = limit
3597
3855
  response = None
3598
- if market['settle'] == 'USDT':
3856
+ isUsdt = market['settle'] == 'USDT'
3857
+ if isUsdt:
3599
3858
  response = self.privateGetApiDataGFuturesFundingFees(self.extend(request, params))
3600
3859
  else:
3601
3860
  response = self.privateGetApiDataFuturesFundingFees(self.extend(request, params))
@@ -3608,13 +3867,13 @@ class phemex(Exchange, ImplicitAPI):
3608
3867
  # {
3609
3868
  # "symbol": "BTCUSD",
3610
3869
  # "currency": "BTC",
3611
- # "execQty": 18,
3870
+ # "execQty": 18, # "execQty" regular, but "execQtyRq" in hedge
3612
3871
  # "side": "Buy",
3613
- # "execPriceEp": 360086455,
3614
- # "execValueEv": 49987,
3615
- # "fundingRateEr": 10000,
3616
- # "feeRateEr": 10000,
3617
- # "execFeeEv": 5,
3872
+ # "execPriceEp": 360086455, # "execPriceEp" regular, but "execPriceRp" in hedge
3873
+ # "execValueEv": 49987, # "execValueEv" regular, but "execValueRv" in hedge
3874
+ # "fundingRateEr": 10000, # "fundingRateEr" regular, but "fundingRateRr" in hedge
3875
+ # "feeRateEr": 10000, # "feeRateEr" regular, but "feeRateRr" in hedge
3876
+ # "execFeeEv": 5, # "execFeeEv" regular, but "execFeeRv" in hedge
3618
3877
  # "createTime": 1651881600000
3619
3878
  # }
3620
3879
  # ]
@@ -3627,18 +3886,32 @@ class phemex(Exchange, ImplicitAPI):
3627
3886
  for i in range(0, len(rows)):
3628
3887
  entry = rows[i]
3629
3888
  timestamp = self.safe_integer(entry, 'createTime')
3889
+ execFee = self.safe_string_2(entry, 'execFeeEv', 'execFeeRv')
3890
+ currencyCode = self.safe_currency_code(self.safe_string(entry, 'currency'))
3630
3891
  result.append({
3631
3892
  'info': entry,
3632
3893
  'symbol': self.safe_string(entry, 'symbol'),
3633
- 'code': self.safe_currency_code(self.safe_string(entry, 'currency')),
3894
+ 'code': currencyCode,
3634
3895
  'timestamp': timestamp,
3635
3896
  'datetime': self.iso8601(timestamp),
3636
3897
  'id': None,
3637
- 'amount': self.from_ev(self.safe_string(entry, 'execFeeEv'), market),
3898
+ 'amount': self.parse_funding_fee_to_precision(execFee, market, currencyCode),
3638
3899
  })
3639
3900
  return result
3640
3901
 
3641
- def fetch_funding_rate(self, symbol: str, params={}):
3902
+ def parse_funding_fee_to_precision(self, value, market: Market = None, currencyCode: Str = None):
3903
+ if value is None or currencyCode is None:
3904
+ return value
3905
+ # it was confirmed by phemex support, that USDT contracts use direct amounts in funding fees, while USD & INVERSE needs 'valueScale'
3906
+ isUsdt = market['settle'] == 'USDT'
3907
+ if not isUsdt:
3908
+ currency = self.safe_currency(currencyCode)
3909
+ scale = self.safe_string(currency['info'], 'valueScale')
3910
+ tickPrecision = self.parse_precision(scale)
3911
+ value = Precise.string_mul(value, tickPrecision)
3912
+ return value
3913
+
3914
+ def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
3642
3915
  """
3643
3916
  fetch the current funding rate
3644
3917
  :param str symbol: unified market symbol
@@ -3649,10 +3922,10 @@ class phemex(Exchange, ImplicitAPI):
3649
3922
  market = self.market(symbol)
3650
3923
  if not market['swap']:
3651
3924
  raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
3652
- request = {
3925
+ request: dict = {
3653
3926
  'symbol': market['id'],
3654
3927
  }
3655
- response = {}
3928
+ response: dict = {}
3656
3929
  if not market['linear']:
3657
3930
  response = self.v1GetMdTicker24hr(self.extend(request, params))
3658
3931
  else:
@@ -3683,7 +3956,7 @@ class phemex(Exchange, ImplicitAPI):
3683
3956
  result = self.safe_value(response, 'result', {})
3684
3957
  return self.parse_funding_rate(result, market)
3685
3958
 
3686
- def parse_funding_rate(self, contract, market: Market = None):
3959
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
3687
3960
  #
3688
3961
  # {
3689
3962
  # "askEp": 2332500,
@@ -3724,30 +3997,37 @@ class phemex(Exchange, ImplicitAPI):
3724
3997
  marketId = self.safe_string(contract, 'symbol')
3725
3998
  symbol = self.safe_symbol(marketId, market)
3726
3999
  timestamp = self.safe_integer_product(contract, 'timestamp', 0.000001)
4000
+ markEp = self.from_ep(self.safe_string(contract, 'markEp'), market)
4001
+ indexEp = self.from_ep(self.safe_string(contract, 'indexEp'), market)
4002
+ fundingRateEr = self.from_er(self.safe_string(contract, 'fundingRateEr'), market)
4003
+ nextFundingRateEr = self.from_er(self.safe_string(contract, 'predFundingRateEr'), market)
3727
4004
  return {
3728
4005
  'info': contract,
3729
4006
  'symbol': symbol,
3730
- 'markPrice': self.from_ep(self.safe_string_2(contract, 'markEp', 'markPriceRp'), market),
3731
- 'indexPrice': self.from_ep(self.safe_string_2(contract, 'indexEp', 'indexPriceRp'), market),
4007
+ 'markPrice': self.safe_number(contract, 'markPriceRp', markEp),
4008
+ 'indexPrice': self.safe_number(contract, 'indexPriceRp', indexEp),
3732
4009
  'interestRate': None,
3733
4010
  'estimatedSettlePrice': None,
3734
4011
  'timestamp': timestamp,
3735
4012
  'datetime': self.iso8601(timestamp),
3736
- 'fundingRate': self.from_er(self.safe_string(contract, 'fundingRateEr'), market),
4013
+ 'fundingRate': self.safe_number(contract, 'fundingRateRr', fundingRateEr),
3737
4014
  'fundingTimestamp': None,
3738
4015
  'fundingDatetime': None,
3739
- 'nextFundingRate': self.from_er(self.safe_string_2(contract, 'predFundingRateEr', 'predFundingRateRr'), market),
4016
+ 'nextFundingRate': self.safe_number(contract, 'predFundingRateRr', nextFundingRateEr),
3740
4017
  'nextFundingTimestamp': None,
3741
4018
  'nextFundingDatetime': None,
3742
4019
  'previousFundingRate': None,
3743
4020
  'previousFundingTimestamp': None,
3744
4021
  'previousFundingDatetime': None,
4022
+ 'interval': None,
3745
4023
  }
3746
4024
 
3747
- def set_margin(self, symbol: str, amount: float, params={}):
4025
+ def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3748
4026
  """
3749
4027
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
3750
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
4028
+
4029
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
4030
+
3751
4031
  :param str symbol: unified market symbol of the market to set margin in
3752
4032
  :param float amount: the amount to set the margin to
3753
4033
  :param dict [params]: parameters specific to the exchange API endpoint
@@ -3755,7 +4035,7 @@ class phemex(Exchange, ImplicitAPI):
3755
4035
  """
3756
4036
  self.load_markets()
3757
4037
  market = self.market(symbol)
3758
- request = {
4038
+ request: dict = {
3759
4039
  'symbol': market['id'],
3760
4040
  'posBalanceEv': self.to_ev(amount, market),
3761
4041
  }
@@ -3772,12 +4052,12 @@ class phemex(Exchange, ImplicitAPI):
3772
4052
  })
3773
4053
 
3774
4054
  def parse_margin_status(self, status):
3775
- statuses = {
4055
+ statuses: dict = {
3776
4056
  '0': 'ok',
3777
4057
  }
3778
4058
  return self.safe_string(statuses, status, status)
3779
4059
 
3780
- def parse_margin_modification(self, data, market: Market = None):
4060
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
3781
4061
  #
3782
4062
  # {
3783
4063
  # "code": 0,
@@ -3790,17 +4070,23 @@ class phemex(Exchange, ImplicitAPI):
3790
4070
  codeCurrency = 'base' if inverse else 'quote'
3791
4071
  return {
3792
4072
  'info': data,
4073
+ 'symbol': self.safe_symbol(None, market),
3793
4074
  'type': 'set',
4075
+ 'marginMode': 'isolated',
3794
4076
  'amount': None,
3795
4077
  'total': None,
3796
4078
  'code': market[codeCurrency],
3797
- 'symbol': self.safe_symbol(None, market),
3798
4079
  'status': self.parse_margin_status(self.safe_string(data, 'code')),
4080
+ 'timestamp': None,
4081
+ 'datetime': None,
3799
4082
  }
3800
4083
 
3801
4084
  def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
3802
4085
  """
3803
4086
  set margin mode to 'cross' or 'isolated'
4087
+
4088
+ https://phemex-docs.github.io/#set-leverage
4089
+
3804
4090
  :param str marginMode: 'cross' or 'isolated'
3805
4091
  :param str symbol: unified market symbol
3806
4092
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3820,7 +4106,7 @@ class phemex(Exchange, ImplicitAPI):
3820
4106
  leverage = 0
3821
4107
  if leverage is None:
3822
4108
  raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter')
3823
- request = {
4109
+ request: dict = {
3824
4110
  'symbol': market['id'],
3825
4111
  'leverage': leverage,
3826
4112
  }
@@ -3829,7 +4115,9 @@ class phemex(Exchange, ImplicitAPI):
3829
4115
  def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
3830
4116
  """
3831
4117
  set hedged to True or False for a market
3832
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
4118
+
4119
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
4120
+
3833
4121
  :param bool hedged: set to True to use dualSidePosition
3834
4122
  :param str symbol: not used by binance setPositionMode()
3835
4123
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3840,7 +4128,7 @@ class phemex(Exchange, ImplicitAPI):
3840
4128
  market = self.market(symbol)
3841
4129
  if market['settle'] != 'USDT':
3842
4130
  raise BadSymbol(self.id + ' setPositionMode() supports USDT settled markets only')
3843
- request = {
4131
+ request: dict = {
3844
4132
  'symbol': market['id'],
3845
4133
  }
3846
4134
  if hedged:
@@ -3849,7 +4137,7 @@ class phemex(Exchange, ImplicitAPI):
3849
4137
  request['targetPosMode'] = 'OneWay'
3850
4138
  return self.privatePutGPositionsSwitchPosModeSync(self.extend(request, params))
3851
4139
 
3852
- def fetch_leverage_tiers(self, symbols: Strings = None, params={}):
4140
+ def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
3853
4141
  """
3854
4142
  retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
3855
4143
  :param str[]|None symbols: list of unified market symbols
@@ -3942,10 +4230,10 @@ class phemex(Exchange, ImplicitAPI):
3942
4230
  #
3943
4231
  #
3944
4232
  data = self.safe_value(response, 'data', {})
3945
- riskLimits = self.safe_value(data, 'riskLimits')
4233
+ riskLimits = self.safe_list(data, 'riskLimits')
3946
4234
  return self.parse_leverage_tiers(riskLimits, symbols, 'symbol')
3947
4235
 
3948
- def parse_market_leverage_tiers(self, info, market: Market = None):
4236
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
3949
4237
  """
3950
4238
  :param dict info: Exchange market response for 1 market
3951
4239
  :param dict market: CCXT market
@@ -3961,7 +4249,8 @@ class phemex(Exchange, ImplicitAPI):
3961
4249
  # ]
3962
4250
  # },
3963
4251
  #
3964
- market = self.safe_market(None, market)
4252
+ marketId = self.safe_string(info, 'symbol')
4253
+ market = self.safe_market(marketId, market)
3965
4254
  riskLimits = (market['info']['riskLimits'])
3966
4255
  tiers = []
3967
4256
  minNotional = 0
@@ -3970,6 +4259,7 @@ class phemex(Exchange, ImplicitAPI):
3970
4259
  maxNotional = self.safe_integer(tier, 'limit')
3971
4260
  tiers.append({
3972
4261
  'tier': self.sum(i, 1),
4262
+ 'symbol': self.safe_symbol(marketId, market),
3973
4263
  'currency': market['settle'],
3974
4264
  'minNotional': minNotional,
3975
4265
  'maxNotional': maxNotional,
@@ -4017,7 +4307,9 @@ class phemex(Exchange, ImplicitAPI):
4017
4307
  def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
4018
4308
  """
4019
4309
  set the level of leverage for a market
4020
- :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#set-leverage
4310
+
4311
+ https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#set-leverage
4312
+
4021
4313
  :param float leverage: the rate of leverage, 100 > leverage > -100 excluding numbers between -1 to 1
4022
4314
  :param str symbol: unified market symbol
4023
4315
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4037,7 +4329,7 @@ class phemex(Exchange, ImplicitAPI):
4037
4329
  longLeverageRr = self.safe_integer(params, 'longLeverageRr')
4038
4330
  shortLeverageRr = self.safe_integer(params, 'shortLeverageRr')
4039
4331
  market = self.market(symbol)
4040
- request = {
4332
+ request: dict = {
4041
4333
  'symbol': market['id'],
4042
4334
  }
4043
4335
  response = None
@@ -4058,6 +4350,10 @@ class phemex(Exchange, ImplicitAPI):
4058
4350
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4059
4351
  """
4060
4352
  transfer currency internally between wallets on the same account
4353
+
4354
+ https://phemex-docs.github.io/#transfer-between-spot-and-futures
4355
+ https://phemex-docs.github.io/#universal-transfer-main-account-only-transfer-between-sub-to-main-main-to-sub-or-sub-to-sub
4356
+
4061
4357
  :param str code: unified currency code
4062
4358
  :param float amount: amount to transfer
4063
4359
  :param str fromAccount: account to transfer from
@@ -4079,7 +4375,7 @@ class phemex(Exchange, ImplicitAPI):
4079
4375
  elif fromId == 'future' and toId == 'spot':
4080
4376
  direction = 1
4081
4377
  if direction is not None:
4082
- request = {
4378
+ request: dict = {
4083
4379
  'currency': currency['id'],
4084
4380
  'moveOp': direction,
4085
4381
  'amountEv': scaledAmmount,
@@ -4102,7 +4398,7 @@ class phemex(Exchange, ImplicitAPI):
4102
4398
  data = self.safe_value(response, 'data', {})
4103
4399
  transfer = self.parse_transfer(data, currency)
4104
4400
  else: # sub account transfer
4105
- request = {
4401
+ request: dict = {
4106
4402
  'fromUserId': fromId,
4107
4403
  'toUserId': toId,
4108
4404
  'amountEv': scaledAmmount,
@@ -4131,9 +4427,12 @@ class phemex(Exchange, ImplicitAPI):
4131
4427
  transfer['currency'] = code
4132
4428
  return transfer
4133
4429
 
4134
- def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4430
+ def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
4135
4431
  """
4136
4432
  fetch a history of internal transfers made on an account
4433
+
4434
+ https://phemex-docs.github.io/#query-transfer-history
4435
+
4137
4436
  :param str code: unified currency code of the currency transferred
4138
4437
  :param int [since]: the earliest time in ms to fetch transfers for
4139
4438
  :param int [limit]: the maximum number of transfers structures to retrieve
@@ -4144,7 +4443,7 @@ class phemex(Exchange, ImplicitAPI):
4144
4443
  if code is None:
4145
4444
  raise ArgumentsRequired(self.id + ' fetchTransfers() requires a code argument')
4146
4445
  currency = self.currency(code)
4147
- request = {
4446
+ request: dict = {
4148
4447
  'currency': currency['id'],
4149
4448
  }
4150
4449
  if since is not None:
@@ -4173,10 +4472,10 @@ class phemex(Exchange, ImplicitAPI):
4173
4472
  # }
4174
4473
  #
4175
4474
  data = self.safe_value(response, 'data', {})
4176
- transfers = self.safe_value(data, 'rows', [])
4475
+ transfers = self.safe_list(data, 'rows', [])
4177
4476
  return self.parse_transfers(transfers, currency, since, limit)
4178
4477
 
4179
- def parse_transfer(self, transfer, currency: Currency = None):
4478
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
4180
4479
  #
4181
4480
  # transfer
4182
4481
  #
@@ -4230,8 +4529,8 @@ class phemex(Exchange, ImplicitAPI):
4230
4529
  'status': self.parse_transfer_status(status),
4231
4530
  }
4232
4531
 
4233
- def parse_transfer_status(self, status):
4234
- statuses = {
4532
+ def parse_transfer_status(self, status: Str) -> Str:
4533
+ statuses: dict = {
4235
4534
  '3': 'rejected', # 'Rejected',
4236
4535
  '6': 'canceled', # 'Got error and wait for recovery',
4237
4536
  '10': 'ok', # 'Success',
@@ -4242,7 +4541,9 @@ class phemex(Exchange, ImplicitAPI):
4242
4541
  def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4243
4542
  """
4244
4543
  fetches historical funding rate prices
4245
- :see: https://phemex-docs.github.io/#query-funding-rate-history-2
4544
+
4545
+ https://phemex-docs.github.io/#query-funding-rate-history-2
4546
+
4246
4547
  :param str symbol: unified symbol of the market to fetch the funding rate history for
4247
4548
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
4248
4549
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
@@ -4267,7 +4568,7 @@ class phemex(Exchange, ImplicitAPI):
4267
4568
  customSymbol = '.' + market['id'] + 'FR8H' # phemex requires a custom symbol for funding rate history
4268
4569
  else:
4269
4570
  customSymbol = '.' + market['baseId'] + 'FR8H'
4270
- request = {
4571
+ request: dict = {
4271
4572
  'symbol': customSymbol,
4272
4573
  }
4273
4574
  if since is not None:
@@ -4312,10 +4613,12 @@ class phemex(Exchange, ImplicitAPI):
4312
4613
  sorted = self.sort_by(result, 'timestamp')
4313
4614
  return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
4314
4615
 
4315
- def withdraw(self, code: str, amount: float, address, tag=None, params={}):
4616
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
4316
4617
  """
4317
4618
  make a withdrawal
4318
- :see: https://phemex-docs.github.io/#create-withdraw-request
4619
+
4620
+ https://phemex-docs.github.io/#create-withdraw-request
4621
+
4319
4622
  :param str code: unified currency code
4320
4623
  :param float amount: the amount to withdraw
4321
4624
  :param str address: the address to withdraw to
@@ -4339,7 +4642,7 @@ class phemex(Exchange, ImplicitAPI):
4339
4642
  networkId = currency['id']
4340
4643
  else:
4341
4644
  raise ArgumentsRequired(self.id + ' withdraw() requires an extra argument params["network"]')
4342
- request = {
4645
+ request: dict = {
4343
4646
  'currency': currency['id'],
4344
4647
  'address': address,
4345
4648
  'amount': amount,
@@ -4375,10 +4678,83 @@ class phemex(Exchange, ImplicitAPI):
4375
4678
  # }
4376
4679
  # }
4377
4680
  #
4378
- data = self.safe_value(response, 'data', {})
4681
+ data = self.safe_dict(response, 'data', {})
4379
4682
  return self.parse_transaction(data, currency)
4380
4683
 
4381
- def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
4684
+ def fetch_open_interest(self, symbol: str, params={}):
4685
+ """
4686
+ retrieves the open interest of a trading pair
4687
+
4688
+ https://phemex-docs.github.io/#query-24-hours-ticker
4689
+
4690
+ :param str symbol: unified CCXT market symbol
4691
+ :param dict [params]: exchange specific parameters
4692
+ :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
4693
+ """
4694
+ self.load_markets()
4695
+ market = self.market(symbol)
4696
+ if not market['contract']:
4697
+ raise BadRequest(self.id + ' fetchOpenInterest is only supported for contract markets.')
4698
+ request: dict = {
4699
+ 'symbol': market['id'],
4700
+ }
4701
+ response = self.v2GetMdV2Ticker24hr(self.extend(request, params))
4702
+ #
4703
+ # {
4704
+ # error: null,
4705
+ # id: '0',
4706
+ # result: {
4707
+ # closeRp: '67550.1',
4708
+ # fundingRateRr: '0.0001',
4709
+ # highRp: '68400',
4710
+ # indexPriceRp: '67567.15389794',
4711
+ # lowRp: '66096.4',
4712
+ # markPriceRp: '67550.1',
4713
+ # openInterestRv: '1848.1144186',
4714
+ # openRp: '66330',
4715
+ # predFundingRateRr: '0.0001',
4716
+ # symbol: 'BTCUSDT',
4717
+ # timestamp: '1729114315443343001',
4718
+ # turnoverRv: '228863389.3237532',
4719
+ # volumeRq: '3388.5600312'
4720
+ # }
4721
+ # }
4722
+ #
4723
+ result = self.safe_dict(response, 'result')
4724
+ return self.parse_open_interest(result, market)
4725
+
4726
+ def parse_open_interest(self, interest, market: Market = None):
4727
+ #
4728
+ # {
4729
+ # closeRp: '67550.1',
4730
+ # fundingRateRr: '0.0001',
4731
+ # highRp: '68400',
4732
+ # indexPriceRp: '67567.15389794',
4733
+ # lowRp: '66096.4',
4734
+ # markPriceRp: '67550.1',
4735
+ # openInterestRv: '1848.1144186',
4736
+ # openRp: '66330',
4737
+ # predFundingRateRr: '0.0001',
4738
+ # symbol: 'BTCUSDT',
4739
+ # timestamp: '1729114315443343001',
4740
+ # turnoverRv: '228863389.3237532',
4741
+ # volumeRq: '3388.5600312'
4742
+ # }
4743
+ #
4744
+ timestamp = self.safe_integer(interest, 'timestamp') / 1000000
4745
+ id = self.safe_string(interest, 'symbol')
4746
+ return self.safe_open_interest({
4747
+ 'info': interest,
4748
+ 'symbol': self.safe_symbol(id, market),
4749
+ 'baseVolume': self.safe_string(interest, 'volumeRq'),
4750
+ 'quoteVolume': None, # deprecated
4751
+ 'openInterestAmount': self.safe_string(interest, 'openInterestRv'),
4752
+ 'openInterestValue': None,
4753
+ 'timestamp': timestamp,
4754
+ 'datetime': self.iso8601(timestamp),
4755
+ }, market)
4756
+
4757
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
4382
4758
  if response is None:
4383
4759
  return None # fallback to default error handler
4384
4760
  #