ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__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 +3205 -937
  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 +1525 -573
  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 +223 -97
  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 +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -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 +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -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 +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -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 +3205 -937
  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 +1525 -573
  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 +223 -97
  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 +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -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 +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -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 +143 -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.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.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.49.dist-info}/top_level.txt +0 -0
ccxt/async_support/okx.py CHANGED
@@ -7,29 +7,33 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, Market, MarketInterface, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Balances, BorrowInterest, Conversion, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, LongShortRatio, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
11
11
  from typing import List
12
+ from typing import Any
12
13
  from ccxt.base.errors import ExchangeError
14
+ from ccxt.base.errors import AuthenticationError
13
15
  from ccxt.base.errors import PermissionDenied
14
16
  from ccxt.base.errors import AccountNotEnabled
15
17
  from ccxt.base.errors import AccountSuspended
16
18
  from ccxt.base.errors import ArgumentsRequired
17
19
  from ccxt.base.errors import BadRequest
18
20
  from ccxt.base.errors import BadSymbol
21
+ from ccxt.base.errors import OperationRejected
22
+ from ccxt.base.errors import ManualInteractionNeeded
19
23
  from ccxt.base.errors import InsufficientFunds
20
24
  from ccxt.base.errors import InvalidAddress
21
25
  from ccxt.base.errors import InvalidOrder
22
26
  from ccxt.base.errors import OrderNotFound
23
- from ccxt.base.errors import CancelPending
27
+ from ccxt.base.errors import ContractUnavailable
24
28
  from ccxt.base.errors import NotSupported
25
29
  from ccxt.base.errors import NetworkError
30
+ from ccxt.base.errors import DDoSProtection
26
31
  from ccxt.base.errors import RateLimitExceeded
27
32
  from ccxt.base.errors import ExchangeNotAvailable
28
33
  from ccxt.base.errors import OnMaintenance
29
34
  from ccxt.base.errors import InvalidNonce
30
35
  from ccxt.base.errors import RequestTimeout
31
- from ccxt.base.errors import AuthenticationError
32
- from ccxt.base.errors import ContractUnavailable
36
+ from ccxt.base.errors import CancelPending
33
37
  from ccxt.base.decimal_to_precision import TICK_SIZE
34
38
  from ccxt.base.precise import Precise
35
39
 
@@ -54,10 +58,13 @@ class okx(Exchange, ImplicitAPI):
54
58
  'option': True,
55
59
  'addMargin': True,
56
60
  'cancelAllOrders': False,
61
+ 'cancelAllOrdersAfter': True,
57
62
  'cancelOrder': True,
58
63
  'cancelOrders': True,
64
+ 'cancelOrdersForSymbols': True,
59
65
  'closeAllPositions': False,
60
66
  'closePosition': True,
67
+ 'createConvertTrade': True,
61
68
  'createDepositAddress': False,
62
69
  'createMarketBuyOrderWithCost': True,
63
70
  'createMarketSellOrderWithCost': True,
@@ -83,6 +90,10 @@ class okx(Exchange, ImplicitAPI):
83
90
  'fetchCanceledOrders': True,
84
91
  'fetchClosedOrder': None,
85
92
  'fetchClosedOrders': True,
93
+ 'fetchConvertCurrencies': True,
94
+ 'fetchConvertQuote': True,
95
+ 'fetchConvertTrade': True,
96
+ 'fetchConvertTradeHistory': True,
86
97
  'fetchCrossBorrowRate': True,
87
98
  'fetchCrossBorrowRates': True,
88
99
  'fetchCurrencies': True,
@@ -95,6 +106,8 @@ class okx(Exchange, ImplicitAPI):
95
106
  'fetchDepositWithdrawFee': 'emulated',
96
107
  'fetchDepositWithdrawFees': True,
97
108
  'fetchFundingHistory': True,
109
+ 'fetchFundingInterval': True,
110
+ 'fetchFundingIntervals': False,
98
111
  'fetchFundingRate': True,
99
112
  'fetchFundingRateHistory': True,
100
113
  'fetchFundingRates': False,
@@ -107,9 +120,14 @@ class okx(Exchange, ImplicitAPI):
107
120
  'fetchLedgerEntry': None,
108
121
  'fetchLeverage': True,
109
122
  'fetchLeverageTiers': False,
123
+ 'fetchLongShortRatio': False,
124
+ 'fetchLongShortRatioHistory': True,
125
+ 'fetchMarginAdjustmentHistory': True,
110
126
  'fetchMarketLeverageTiers': True,
111
127
  'fetchMarkets': True,
112
128
  'fetchMarkOHLCV': True,
129
+ 'fetchMarkPrice': True,
130
+ 'fetchMarkPrices': True,
113
131
  'fetchMySettlementHistory': False,
114
132
  'fetchMyTrades': True,
115
133
  'fetchOHLCV': True,
@@ -117,15 +135,18 @@ class okx(Exchange, ImplicitAPI):
117
135
  'fetchOpenInterestHistory': True,
118
136
  'fetchOpenOrder': None,
119
137
  'fetchOpenOrders': True,
138
+ 'fetchOption': True,
139
+ 'fetchOptionChain': True,
120
140
  'fetchOrder': True,
121
141
  'fetchOrderBook': True,
122
142
  'fetchOrderBooks': False,
123
143
  'fetchOrders': False,
124
144
  'fetchOrderTrades': True,
125
- 'fetchPermissions': None,
126
145
  'fetchPosition': True,
146
+ 'fetchPositionHistory': 'emulated',
127
147
  'fetchPositions': True,
128
148
  'fetchPositionsForSymbol': True,
149
+ 'fetchPositionsHistory': True,
129
150
  'fetchPositionsRisk': False,
130
151
  'fetchPremiumIndexOHLCV': False,
131
152
  'fetchSettlementHistory': True,
@@ -149,6 +170,7 @@ class okx(Exchange, ImplicitAPI):
149
170
  'fetchWithdrawalWhitelist': False,
150
171
  'reduceMargin': True,
151
172
  'repayCrossMargin': True,
173
+ 'sandbox': True,
152
174
  'setLeverage': True,
153
175
  'setMargin': False,
154
176
  'setMarginMode': True,
@@ -242,6 +264,7 @@ class okx(Exchange, ImplicitAPI):
242
264
  'rubik/stat/margin/loan-ratio': 4,
243
265
  # long/short
244
266
  'rubik/stat/contracts/long-short-account-ratio': 4,
267
+ 'rubik/stat/contracts/long-short-account-ratio-contract': 4,
245
268
  'rubik/stat/contracts/open-interest-volume': 4,
246
269
  'rubik/stat/option/open-interest-volume': 4,
247
270
  # put/call
@@ -255,13 +278,20 @@ class okx(Exchange, ImplicitAPI):
255
278
  'sprd/books': 1 / 2,
256
279
  'sprd/ticker': 1,
257
280
  'sprd/public-trades': 1 / 5,
281
+ 'market/sprd-ticker': 2,
282
+ 'market/sprd-candles': 2,
283
+ 'market/sprd-history-candles': 2,
258
284
  'tradingBot/grid/ai-param': 1,
259
285
  'tradingBot/grid/min-investment': 1,
260
286
  'tradingBot/public/rsi-back-testing': 1,
261
287
  'asset/exchange-list': 5 / 3,
262
288
  'finance/staking-defi/eth/apy-history': 5 / 3,
289
+ 'finance/staking-defi/sol/apy-history': 5 / 3,
263
290
  'finance/savings/lending-rate-summary': 5 / 3,
264
291
  'finance/savings/lending-rate-history': 5 / 3,
292
+ 'finance/fixed-loan/lending-offers': 10 / 3,
293
+ 'finance/fixed-loan/lending-apy-history': 10 / 3,
294
+ 'finance/fixed-loan/pending-lending-volume': 10 / 3,
265
295
  # public broker
266
296
  'finance/sfp/dcd/products': 2 / 3,
267
297
  # copytrading
@@ -271,6 +301,7 @@ class okx(Exchange, ImplicitAPI):
271
301
  'copytrading/public-preference-currency': 4,
272
302
  'copytrading/public-current-subpositions': 4,
273
303
  'copytrading/public-subpositions-history': 4,
304
+ 'support/announcements-types': 20,
274
305
  },
275
306
  },
276
307
  'private': {
@@ -322,12 +353,14 @@ class okx(Exchange, ImplicitAPI):
322
353
  'asset/convert/history': 5 / 3,
323
354
  'asset/monthly-statement': 2,
324
355
  # account
356
+ 'account/instruments': 1,
325
357
  'account/balance': 2,
326
358
  'account/positions': 2,
327
359
  'account/positions-history': 100,
328
360
  'account/account-position-risk': 2,
329
361
  'account/bills': 5 / 3,
330
362
  'account/bills-archive': 5 / 3,
363
+ 'account/bills-history-archive': 2,
331
364
  'account/config': 4,
332
365
  'account/max-size': 1,
333
366
  'account/max-avail-size': 1,
@@ -349,6 +382,12 @@ class okx(Exchange, ImplicitAPI):
349
382
  'account/greeks': 2,
350
383
  'account/position-tiers': 2,
351
384
  'account/mmp-config': 4,
385
+ 'account/fixed-loan/borrowing-limit': 4,
386
+ 'account/fixed-loan/borrowing-quote': 5,
387
+ 'account/fixed-loan/borrowing-orders-list': 5,
388
+ 'account/spot-manual-borrow-repay': 10,
389
+ 'account/set-auto-repay': 4,
390
+ 'account/spot-borrow-repay-history': 4,
352
391
  # subaccount
353
392
  'users/subaccount/list': 10,
354
393
  'account/subaccount/balances': 10 / 3,
@@ -385,6 +424,9 @@ class okx(Exchange, ImplicitAPI):
385
424
  # eth staking
386
425
  'finance/staking-defi/eth/balance': 5 / 3,
387
426
  'finance/staking-defi/eth/purchase-redeem-history': 5 / 3,
427
+ 'finance/staking-defi/eth/product-info': 3,
428
+ 'finance/staking-defi/sol/balance': 5 / 3,
429
+ 'finance/staking-defi/sol/purchase-redeem-history': 5 / 3,
388
430
  # copytrading
389
431
  'copytrading/current-subpositions': 1,
390
432
  'copytrading/subpositions-history': 1,
@@ -412,6 +454,7 @@ class okx(Exchange, ImplicitAPI):
412
454
  # affiliate
413
455
  'affiliate/invitee/detail': 1,
414
456
  'users/partner/if-rebate': 1,
457
+ 'support/announcements': 4,
415
458
  },
416
459
  'post': {
417
460
  # rfq
@@ -432,6 +475,7 @@ class okx(Exchange, ImplicitAPI):
432
475
  'sprd/cancel-order': 1,
433
476
  'sprd/mass-cancel': 1,
434
477
  'sprd/amend-order': 1,
478
+ 'sprd/cancel-all-after': 10,
435
479
  # trade
436
480
  'trade/order': 1 / 3,
437
481
  'trade/batch-orders': 1 / 15,
@@ -474,6 +518,11 @@ class okx(Exchange, ImplicitAPI):
474
518
  'account/set-account-level': 4,
475
519
  'account/mmp-reset': 4,
476
520
  'account/mmp-config': 100,
521
+ 'account/fixed-loan/borrowing-order': 5,
522
+ 'account/fixed-loan/amend-borrowing-order': 5,
523
+ 'account/fixed-loan/manual-reborrow': 5,
524
+ 'account/fixed-loan/repay-borrowing-order': 5,
525
+ 'account/bills-history-archive': 72000, # 12 req/day
477
526
  # subaccount
478
527
  'users/subaccount/modify-apikey': 10,
479
528
  'asset/subaccount/transfer': 10,
@@ -490,6 +539,7 @@ class okx(Exchange, ImplicitAPI):
490
539
  'tradingBot/grid/compute-margin-balance': 1,
491
540
  'tradingBot/grid/margin-balance': 1,
492
541
  'tradingBot/grid/min-investment': 1,
542
+ 'tradingBot/grid/adjust-investment': 1,
493
543
  'tradingBot/signal/create-signal': 1,
494
544
  'tradingBot/signal/order-algo': 1,
495
545
  'tradingBot/signal/stop-order-algo': 1,
@@ -511,6 +561,8 @@ class okx(Exchange, ImplicitAPI):
511
561
  # eth staking
512
562
  'finance/staking-defi/eth/purchase': 5,
513
563
  'finance/staking-defi/eth/redeem': 5,
564
+ 'finance/staking-defi/sol/purchase': 5,
565
+ 'finance/staking-defi/sol/redeem': 5,
514
566
  # copytrading
515
567
  'copytrading/algo-order': 1,
516
568
  'copytrading/close-subposition': 1,
@@ -567,6 +619,7 @@ class okx(Exchange, ImplicitAPI):
567
619
  # General Class
568
620
  '1': ExchangeError, # Operation failed
569
621
  '2': ExchangeError, # Bulk operation partially succeeded
622
+ '4088': ManualInteractionNeeded, # {"code":"4088","data":[],"msg":"You can’t trade or deposit until you’ve verified your identity again. Head to Identity Verification to complete it."}
570
623
  '50000': BadRequest, # Body can not be empty
571
624
  '50001': OnMaintenance, # Matching engine upgrading. Please try again later
572
625
  '50002': BadRequest, # Json data format error
@@ -596,6 +649,7 @@ class okx(Exchange, ImplicitAPI):
596
649
  '50027': PermissionDenied, # The account is restricted from trading
597
650
  '50028': ExchangeError, # Unable to take the order, please reach out to support center for details
598
651
  '50044': BadRequest, # Must select one broker type
652
+ '50061': ExchangeError, # You've reached the maximum order rate limit for self account.
599
653
  '50062': ExchangeError, # This feature is currently unavailable.
600
654
  # API Class
601
655
  '50100': ExchangeError, # API frozen, please contact customer service
@@ -783,6 +837,18 @@ class okx(Exchange, ImplicitAPI):
783
837
  # SPOT/MARGIN error codes 54000-54999
784
838
  '54000': ExchangeError, # Margin transactions unavailable
785
839
  '54001': ExchangeError, # Only Multi-currency margin account can be set to borrow coins automatically
840
+ '54008': InvalidOrder, # This operation is disabled by the 'mass cancel order' endpoint. Please enable it using self endpoint.
841
+ '54009': InvalidOrder, # The range of {param0} should be [{param1}, {param2}].
842
+ '54011': InvalidOrder, # 200 Pre-market trading contracts are only allowed to reduce the number of positions within 1 hour before delivery. Please modify or cancel the order.
843
+ # Trading bot Error Code from 55100 to 55999
844
+ '55100': InvalidOrder, # Take profit % should be within the range of {parameter1}-{parameter2}
845
+ '55101': InvalidOrder, # Stop loss % should be within the range of {parameter1}-{parameter2}
846
+ '55102': InvalidOrder, # Take profit % should be greater than the current bot’s PnL%
847
+ '55103': InvalidOrder, # Stop loss % should be less than the current bot’s PnL%
848
+ '55104': InvalidOrder, # Only futures grid supports take profit or stop loss based on profit percentage
849
+ '55111': InvalidOrder, # This signal name is in use, please try a new name
850
+ '55112': InvalidOrder, # This signal does not exist
851
+ '55113': InvalidOrder, # Create signal strategies with leverage greater than the maximum leverage of the instruments
786
852
  # FUNDING error codes 58000-58999
787
853
  '58000': ExchangeError, # Account type {0} does not supported when getting the sub-account balance
788
854
  '58001': AuthenticationError, # Incorrect trade password
@@ -858,6 +924,11 @@ class okx(Exchange, ImplicitAPI):
858
924
  '59301': ExchangeError, # Margin adjustment failed for exceeding the max limit
859
925
  '59313': ExchangeError, # Unable to repay. You haven't borrowed any {ccy} {ccyPair} in Quick margin mode.
860
926
  '59401': ExchangeError, # Holdings already reached the limit
927
+ '59410': OperationRejected, # You can only borrow self crypto if it supports borrowing and borrowing is enabled.
928
+ '59411': InsufficientFunds, # Manual borrowing failed. Your account's free margin is insufficient
929
+ '59412': OperationRejected, # Manual borrowing failed. The amount exceeds your borrowing limit.
930
+ '59413': OperationRejected, # You didn't borrow self crypto. No repayment needed.
931
+ '59414': BadRequest, # Manual borrowing failed. The minimum borrowing limit is {param0}.needed.
861
932
  '59500': ExchangeError, # Only the APIKey of the main account has permission
862
933
  '59501': ExchangeError, # Only 50 APIKeys can be created per account
863
934
  '59502': ExchangeError, # Note name cannot be duplicate with the currently created APIKey note name
@@ -889,10 +960,36 @@ class okx(Exchange, ImplicitAPI):
889
960
  '60017': BadRequest, # Invalid url path
890
961
  '60018': BadRequest, # The {0} {1} {2} {3} {4} does not exist
891
962
  '60019': BadRequest, # Invalid op {op}
963
+ '60020': ExchangeError, # APIKey subscription amount exceeds the limit
964
+ '60021': AccountNotEnabled, # This operation does not support multiple accounts login
965
+ '60022': AuthenticationError, # Bulk login partially succeeded
966
+ '60023': DDoSProtection, # Bulk login requests too frequent
967
+ '60024': AuthenticationError, # Wrong passphrase
968
+ '60025': ExchangeError, # Token subscription amount exceeds the limit
969
+ '60026': AuthenticationError, # Batch login by APIKey and token simultaneously is not supported
970
+ '60027': ArgumentsRequired, # Parameter {0} can not be empty
971
+ '60028': NotSupported, # The current operation is not supported by self URL
972
+ '60029': AccountNotEnabled, # Only users who are VIP5 and above in trading fee tier are allowed to subscribe to books-l2-tbt channel
973
+ '60030': AccountNotEnabled, # Only users who are VIP4 and above in trading fee tier are allowed to subscribe to books50-l2-tbt channel
974
+ '60031': AuthenticationError, # The WebSocket endpoint does not support multiple account batch login,
975
+ '60032': AuthenticationError, # API key doesn't exist,
892
976
  '63999': ExchangeError, # Internal system error
977
+ '64000': BadRequest, # Subscription parameter uly is unavailable anymore, please replace uly with instFamily. More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
978
+ '64001': BadRequest, # This channel has been migrated to the business URL. Please subscribe using the new URL. More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
979
+ '64002': BadRequest, # This channel is not supported by business URL. Please use "/private" URL(for private channels), or "/public" URL(for public channels). More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
980
+ '64003': AccountNotEnabled, # Your trading fee tier doesnt meet the requirement to access self channel
893
981
  '70010': BadRequest, # Timestamp parameters need to be in Unix timestamp format in milliseconds.
894
982
  '70013': BadRequest, # endTs needs to be bigger than or equal to beginTs.
895
983
  '70016': BadRequest, # Please specify your instrument settings for at least one instType.
984
+ '1009': BadRequest, # Request message exceeds the maximum frame length
985
+ '4001': AuthenticationError, # Login Failed
986
+ '4002': BadRequest, # Invalid Request
987
+ '4003': RateLimitExceeded, # APIKey subscription amount exceeds the limit 100
988
+ '4004': NetworkError, # No data received in 30s
989
+ '4005': ExchangeNotAvailable, # Buffer is full, cannot write data
990
+ '4006': BadRequest, # Abnormal disconnection
991
+ '4007': AuthenticationError, # API key has been updated or deleted. Please reconnect.
992
+ '4008': RateLimitExceeded, # The number of subscribed channels exceeds the maximum limit.
896
993
  },
897
994
  'broad': {
898
995
  'Internal Server Error': ExchangeNotAvailable, # {"code":500,"data":{},"detailMsg":"","error_code":"500","error_message":"Internal Server Error","msg":"Internal Server Error"}
@@ -924,7 +1021,7 @@ class okx(Exchange, ImplicitAPI):
924
1021
  'BHP': 'BHP',
925
1022
  'APT': 'Aptos',
926
1023
  'ARBONE': 'Arbitrum One',
927
- 'AVAXC': 'Avalanche C',
1024
+ 'AVAXC': 'Avalanche C-Chain',
928
1025
  'AVAXX': 'Avalanche X-Chain',
929
1026
  'ARK': 'ARK',
930
1027
  'AR': 'Arweave',
@@ -997,6 +1094,7 @@ class okx(Exchange, ImplicitAPI):
997
1094
  'ZEC': 'Zcash',
998
1095
  'ZIL': 'Zilliqa',
999
1096
  'ZKSYNC': 'ZKSYNC',
1097
+ 'OMNI': 'Omni',
1000
1098
  # 'NEON3': 'N3', # tbd
1001
1099
  # undetermined : "CELO-TOKEN", "Digital Cash", Khala
1002
1100
  # todo: uncomment below after consensus
@@ -1042,6 +1140,8 @@ class okx(Exchange, ImplicitAPI):
1042
1140
  'createOrder': 'privatePostTradeBatchOrders', # or 'privatePostTradeOrder' or 'privatePostTradeOrderAlgo'
1043
1141
  'createMarketBuyOrderRequiresPrice': False,
1044
1142
  'fetchMarkets': ['spot', 'future', 'swap', 'option'], # spot, future, swap, option
1143
+ 'timeDifference': 0, # the difference between system clock and exchange server clock
1144
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
1045
1145
  'defaultType': 'spot', # 'funding', 'spot', 'margin', 'future', 'swap', 'option'
1046
1146
  # 'fetchBalance': {
1047
1147
  # 'type': 'spot', # 'funding', 'trading', 'spot'
@@ -1108,6 +1208,96 @@ class okx(Exchange, ImplicitAPI):
1108
1208
  },
1109
1209
  'brokerId': 'e847386590ce4dBC',
1110
1210
  },
1211
+ 'features': {
1212
+ 'default': {
1213
+ 'sandbox': True,
1214
+ 'createOrder': {
1215
+ 'marginMode': True,
1216
+ 'triggerPrice': True,
1217
+ 'triggerPriceType': {
1218
+ 'last': True,
1219
+ 'mark': True,
1220
+ 'index': True,
1221
+ },
1222
+ 'triggerDirection': False,
1223
+ 'stopLossPrice': True,
1224
+ 'takeProfitPrice': True,
1225
+ 'attachedStopLossTakeProfit': {
1226
+ 'triggerPriceType': {
1227
+ 'last': True,
1228
+ 'mark': True,
1229
+ 'index': True,
1230
+ },
1231
+ 'price': True,
1232
+ },
1233
+ 'timeInForce': {
1234
+ 'IOC': True,
1235
+ 'FOK': True,
1236
+ 'PO': True,
1237
+ 'GTD': False,
1238
+ },
1239
+ 'hedged': True,
1240
+ 'trailing': True,
1241
+ 'iceberg': True, # todo implement
1242
+ 'leverage': False,
1243
+ 'selfTradePrevention': True, # todo implement
1244
+ 'marketBuyByCost': True,
1245
+ 'marketBuyRequiresPrice': False,
1246
+ },
1247
+ 'createOrders': {
1248
+ 'max': 20,
1249
+ },
1250
+ 'fetchMyTrades': {
1251
+ 'marginMode': False,
1252
+ 'daysBack': 90,
1253
+ 'limit': 100,
1254
+ 'untilDays': 10000,
1255
+ },
1256
+ 'fetchOrder': {
1257
+ 'marginMode': False,
1258
+ 'trigger': True,
1259
+ 'trailing': True,
1260
+ },
1261
+ 'fetchOpenOrders': {
1262
+ 'marginMode': False,
1263
+ 'limit': 100,
1264
+ 'trigger': True,
1265
+ 'trailing': True,
1266
+ },
1267
+ 'fetchOrders': None, # not supported
1268
+ 'fetchClosedOrders': {
1269
+ 'marginMode': False,
1270
+ 'limit': 100,
1271
+ 'daysBack': 90, # 3 months
1272
+ 'daysBackCanceled': 1 / 12, # 2 hour
1273
+ 'untilDays': None,
1274
+ 'trigger': True,
1275
+ 'trailing': True,
1276
+ },
1277
+ 'fetchOHLCV': {
1278
+ 'limit': 300,
1279
+ },
1280
+ },
1281
+ 'spot': {
1282
+ 'extends': 'default',
1283
+ },
1284
+ 'swap': {
1285
+ 'linear': {
1286
+ 'extends': 'default',
1287
+ },
1288
+ 'inverse': {
1289
+ 'extends': 'default',
1290
+ },
1291
+ },
1292
+ 'future': {
1293
+ 'linear': {
1294
+ 'extends': 'default',
1295
+ },
1296
+ 'inverse': {
1297
+ 'extends': 'default',
1298
+ },
1299
+ },
1300
+ },
1111
1301
  'commonCurrencies': {
1112
1302
  # the exchange refers to ERC20 version of Aeternity(AEToken)
1113
1303
  'AE': 'AET', # https://github.com/ccxt/ccxt/issues/4981
@@ -1115,26 +1305,18 @@ class okx(Exchange, ImplicitAPI):
1115
1305
  },
1116
1306
  })
1117
1307
 
1118
- def handle_market_type_and_params(self, methodName, market=None, params={}):
1308
+ def handle_market_type_and_params(self, methodName: str, market: Market = None, params={}, defaultValue=None) -> Any:
1119
1309
  instType = self.safe_string(params, 'instType')
1120
1310
  params = self.omit(params, 'instType')
1121
1311
  type = self.safe_string(params, 'type')
1122
1312
  if (type is None) and (instType is not None):
1123
1313
  params['type'] = instType
1124
- return super(okx, self).handle_market_type_and_params(methodName, market, params)
1314
+ return super(okx, self).handle_market_type_and_params(methodName, market, params, defaultValue)
1125
1315
 
1126
1316
  def convert_to_instrument_type(self, type):
1127
- exchangeTypes = self.safe_value(self.options, 'exchangeType', {})
1317
+ exchangeTypes = self.safe_dict(self.options, 'exchangeType', {})
1128
1318
  return self.safe_string(exchangeTypes, type, type)
1129
1319
 
1130
- def convert_expire_date(self, date):
1131
- # parse YYMMDD to timestamp
1132
- year = date[0:2]
1133
- month = date[2:4]
1134
- day = date[4:6]
1135
- reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z'
1136
- return reconstructedDate
1137
-
1138
1320
  def create_expired_option_market(self, symbol: str):
1139
1321
  # support expired option contracts
1140
1322
  quote = 'USD'
@@ -1206,7 +1388,9 @@ class okx(Exchange, ImplicitAPI):
1206
1388
  async def fetch_status(self, params={}):
1207
1389
  """
1208
1390
  the latest known information on the availability of the exchange API
1209
- :see: https://www.okx.com/docs-v5/en/#status-get-status
1391
+
1392
+ https://www.okx.com/docs-v5/en/#status-get-status
1393
+
1210
1394
  :param dict [params]: extra parameters specific to the exchange API endpoint
1211
1395
  :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
1212
1396
  """
@@ -1231,9 +1415,9 @@ class okx(Exchange, ImplicitAPI):
1231
1415
  # ]
1232
1416
  # }
1233
1417
  #
1234
- data = self.safe_value(response, 'data', [])
1418
+ data = self.safe_list(response, 'data', [])
1235
1419
  dataLength = len(data)
1236
- update = {
1420
+ update: dict = {
1237
1421
  'updated': None,
1238
1422
  'status': 'ok' if (dataLength == 0) else 'maintenance',
1239
1423
  'eta': None,
@@ -1258,7 +1442,9 @@ class okx(Exchange, ImplicitAPI):
1258
1442
  async def fetch_time(self, params={}):
1259
1443
  """
1260
1444
  fetches the current integer timestamp in milliseconds from the exchange server
1261
- :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-system-time
1445
+
1446
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-system-time
1447
+
1262
1448
  :param dict [params]: extra parameters specific to the exchange API endpoint
1263
1449
  :returns int: the current integer timestamp in milliseconds from the exchange server
1264
1450
  """
@@ -1272,14 +1458,16 @@ class okx(Exchange, ImplicitAPI):
1272
1458
  # "msg": ""
1273
1459
  # }
1274
1460
  #
1275
- data = self.safe_value(response, 'data', [])
1276
- first = self.safe_value(data, 0, {})
1461
+ data = self.safe_list(response, 'data', [])
1462
+ first = self.safe_dict(data, 0, {})
1277
1463
  return self.safe_integer(first, 'ts')
1278
1464
 
1279
1465
  async def fetch_accounts(self, params={}) -> List[Account]:
1280
1466
  """
1281
1467
  fetch all the accounts associated with a profile
1282
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-account-configuration
1468
+
1469
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-account-configuration
1470
+
1283
1471
  :param dict [params]: extra parameters specific to the exchange API endpoint
1284
1472
  :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
1285
1473
  """
@@ -1303,7 +1491,7 @@ class okx(Exchange, ImplicitAPI):
1303
1491
  # "msg": ""
1304
1492
  # }
1305
1493
  #
1306
- data = self.safe_value(response, 'data', [])
1494
+ data = self.safe_list(response, 'data', [])
1307
1495
  result = []
1308
1496
  for i in range(0, len(data)):
1309
1497
  account = data[i]
@@ -1318,14 +1506,21 @@ class okx(Exchange, ImplicitAPI):
1318
1506
  })
1319
1507
  return result
1320
1508
 
1321
- async def fetch_markets(self, params={}):
1509
+ def nonce(self):
1510
+ return self.milliseconds() - self.options['timeDifference']
1511
+
1512
+ async def fetch_markets(self, params={}) -> List[Market]:
1322
1513
  """
1323
1514
  retrieves data on all markets for okx
1324
- :see: https://www.okx.com/docs-v5/en/#rest-api-public-data-get-instruments
1515
+
1516
+ https://www.okx.com/docs-v5/en/#rest-api-public-data-get-instruments
1517
+
1325
1518
  :param dict [params]: extra parameters specific to the exchange API endpoint
1326
1519
  :returns dict[]: an array of objects representing market data
1327
1520
  """
1328
- types = self.safe_value(self.options, 'fetchMarkets')
1521
+ if self.options['adjustForTimeDifference']:
1522
+ await self.load_time_difference()
1523
+ types = self.safe_list(self.options, 'fetchMarkets', [])
1329
1524
  promises = []
1330
1525
  result = []
1331
1526
  for i in range(0, len(types)):
@@ -1335,7 +1530,7 @@ class okx(Exchange, ImplicitAPI):
1335
1530
  result = self.array_concat(result, promises[i])
1336
1531
  return result
1337
1532
 
1338
- def parse_market(self, market) -> Market:
1533
+ def parse_market(self, market: dict) -> Market:
1339
1534
  #
1340
1535
  # {
1341
1536
  # "alias": "", # self_week, next_week, quarter, next_quarter
@@ -1422,7 +1617,7 @@ class okx(Exchange, ImplicitAPI):
1422
1617
  symbol = symbol + '-' + ymd + '-' + strikePrice + '-' + optionType
1423
1618
  optionType = 'put' if (optionType == 'P') else 'call'
1424
1619
  tickSize = self.safe_string(market, 'tickSz')
1425
- fees = self.safe_value_2(self.fees, type, 'trading', {})
1620
+ fees = self.safe_dict_2(self.fees, type, 'trading', {})
1426
1621
  maxLeverage = self.safe_string(market, 'lever', '1')
1427
1622
  maxLeverage = Precise.string_max(maxLeverage, '1')
1428
1623
  maxSpotCost = self.safe_number(market, 'maxMktSz')
@@ -1448,7 +1643,7 @@ class okx(Exchange, ImplicitAPI):
1448
1643
  'contractSize': self.safe_number(market, 'ctVal') if contract else None,
1449
1644
  'expiry': expiry,
1450
1645
  'expiryDatetime': self.iso8601(expiry),
1451
- 'strike': strikePrice,
1646
+ 'strike': self.parse_number(strikePrice),
1452
1647
  'optionType': optionType,
1453
1648
  'created': self.safe_integer(market, 'listTime'),
1454
1649
  'precision': {
@@ -1477,11 +1672,11 @@ class okx(Exchange, ImplicitAPI):
1477
1672
  })
1478
1673
 
1479
1674
  async def fetch_markets_by_type(self, type, params={}):
1480
- request = {
1675
+ request: dict = {
1481
1676
  'instType': self.convert_to_instrument_type(type),
1482
1677
  }
1483
1678
  if type == 'option':
1484
- optionsUnderlying = self.safe_value(self.options, 'defaultUnderlying', ['BTC-USD', 'ETH-USD'])
1679
+ optionsUnderlying = self.safe_list(self.options, 'defaultUnderlying', ['BTC-USD', 'ETH-USD'])
1485
1680
  promises = []
1486
1681
  for i in range(0, len(optionsUnderlying)):
1487
1682
  underlying = optionsUnderlying[i]
@@ -1490,8 +1685,8 @@ class okx(Exchange, ImplicitAPI):
1490
1685
  promisesResult = await asyncio.gather(*promises)
1491
1686
  markets = []
1492
1687
  for i in range(0, len(promisesResult)):
1493
- res = self.safe_value(promisesResult, i, {})
1494
- options = self.safe_value(res, 'data', [])
1688
+ res = self.safe_dict(promisesResult, i, {})
1689
+ options = self.safe_list(res, 'data', [])
1495
1690
  markets = self.array_concat(markets, options)
1496
1691
  return self.parse_markets(markets)
1497
1692
  response = await self.publicGetPublicInstruments(self.extend(request, params))
@@ -1528,21 +1723,15 @@ class okx(Exchange, ImplicitAPI):
1528
1723
  # "msg": ""
1529
1724
  # }
1530
1725
  #
1531
- dataResponse = self.safe_value(response, 'data', [])
1726
+ dataResponse = self.safe_list(response, 'data', [])
1532
1727
  return self.parse_markets(dataResponse)
1533
1728
 
1534
- def safe_network(self, networkId):
1535
- networksById = {
1536
- 'Bitcoin': 'BTC',
1537
- 'Omni': 'OMNI',
1538
- 'TRON': 'TRC20',
1539
- }
1540
- return self.safe_string(networksById, networkId, networkId)
1541
-
1542
- async def fetch_currencies(self, params={}):
1729
+ async def fetch_currencies(self, params={}) -> Currencies:
1543
1730
  """
1544
1731
  fetches all available currencies on an exchange
1545
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
1732
+
1733
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
1734
+
1546
1735
  :param dict [params]: extra parameters specific to the exchange API endpoint
1547
1736
  :returns dict: an associative dictionary of currencies
1548
1737
  """
@@ -1602,8 +1791,8 @@ class okx(Exchange, ImplicitAPI):
1602
1791
  # "msg": ""
1603
1792
  # }
1604
1793
  #
1605
- data = self.safe_value(response, 'data', [])
1606
- result = {}
1794
+ data = self.safe_list(response, 'data', [])
1795
+ result: dict = {}
1607
1796
  dataByCurrencyId = self.group_by(data, 'ccy')
1608
1797
  currencyIds = list(dataByCurrencyId.keys())
1609
1798
  for i in range(0, len(currencyIds)):
@@ -1611,24 +1800,24 @@ class okx(Exchange, ImplicitAPI):
1611
1800
  currency = self.safe_currency(currencyId)
1612
1801
  code = currency['code']
1613
1802
  chains = dataByCurrencyId[currencyId]
1614
- networks = {}
1803
+ networks: dict = {}
1615
1804
  currencyActive = False
1616
1805
  depositEnabled = False
1617
1806
  withdrawEnabled = False
1618
1807
  maxPrecision = None
1619
1808
  for j in range(0, len(chains)):
1620
1809
  chain = chains[j]
1621
- canDeposit = self.safe_value(chain, 'canDep')
1810
+ canDeposit = self.safe_bool(chain, 'canDep')
1622
1811
  depositEnabled = canDeposit if (canDeposit) else depositEnabled
1623
- canWithdraw = self.safe_value(chain, 'canWd')
1812
+ canWithdraw = self.safe_bool(chain, 'canWd')
1624
1813
  withdrawEnabled = canWithdraw if (canWithdraw) else withdrawEnabled
1625
- canInternal = self.safe_value(chain, 'canInternal')
1814
+ canInternal = self.safe_bool(chain, 'canInternal')
1626
1815
  active = True if (canDeposit and canWithdraw and canInternal) else False
1627
1816
  currencyActive = active if (active) else currencyActive
1628
1817
  networkId = self.safe_string(chain, 'chain')
1629
1818
  if (networkId is not None) and (networkId.find('-') >= 0):
1630
- parts = networkId.split('-')
1631
- chainPart = self.safe_string(parts, 1, networkId)
1819
+ parts = networkId.split('-')[1:]
1820
+ chainPart = '-'.join(parts)
1632
1821
  networkCode = self.network_id_to_code(chainPart, currency['code'])
1633
1822
  precision = self.parse_precision(self.safe_string(chain, 'wdTickSz'))
1634
1823
  if maxPrecision is None:
@@ -1641,7 +1830,7 @@ class okx(Exchange, ImplicitAPI):
1641
1830
  'active': active,
1642
1831
  'deposit': canDeposit,
1643
1832
  'withdraw': canWithdraw,
1644
- 'fee': self.safe_number(chain, 'minFee'),
1833
+ 'fee': self.safe_number(chain, 'fee'),
1645
1834
  'precision': self.parse_number(precision),
1646
1835
  'limits': {
1647
1836
  'withdraw': {
@@ -1651,9 +1840,9 @@ class okx(Exchange, ImplicitAPI):
1651
1840
  },
1652
1841
  'info': chain,
1653
1842
  }
1654
- firstChain = self.safe_value(chains, 0)
1843
+ firstChain = self.safe_dict(chains, 0, {})
1655
1844
  result[code] = {
1656
- 'info': None,
1845
+ 'info': chains,
1657
1846
  'code': code,
1658
1847
  'id': currencyId,
1659
1848
  'name': self.safe_string(firstChain, 'name'),
@@ -1675,7 +1864,9 @@ class okx(Exchange, ImplicitAPI):
1675
1864
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1676
1865
  """
1677
1866
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1678
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-order-book
1867
+
1868
+ https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-order-book
1869
+
1679
1870
  :param str symbol: unified symbol of the market to fetch the order book for
1680
1871
  :param int [limit]: the maximum amount of order book entries to return
1681
1872
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1684,7 +1875,7 @@ class okx(Exchange, ImplicitAPI):
1684
1875
  """
1685
1876
  await self.load_markets()
1686
1877
  market = self.market(symbol)
1687
- request = {
1878
+ request: dict = {
1688
1879
  'instId': market['id'],
1689
1880
  }
1690
1881
  method = None
@@ -1720,12 +1911,19 @@ class okx(Exchange, ImplicitAPI):
1720
1911
  # ]
1721
1912
  # }
1722
1913
  #
1723
- data = self.safe_value(response, 'data', [])
1724
- first = self.safe_value(data, 0, {})
1914
+ data = self.safe_list(response, 'data', [])
1915
+ first = self.safe_dict(data, 0, {})
1725
1916
  timestamp = self.safe_integer(first, 'ts')
1726
1917
  return self.parse_order_book(first, symbol, timestamp)
1727
1918
 
1728
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1919
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1920
+ #
1921
+ # {
1922
+ # "instType":"SWAP",
1923
+ # "instId":"BTC-USDT-SWAP",
1924
+ # "markPx":"200",
1925
+ # "ts":"1597026383085"
1926
+ # }
1729
1927
  #
1730
1928
  # {
1731
1929
  # "instType": "SPOT",
@@ -1745,6 +1943,16 @@ class okx(Exchange, ImplicitAPI):
1745
1943
  # "sodUtc0": "0.07872",
1746
1944
  # "sodUtc8": "0.07345"
1747
1945
  # }
1946
+ # {
1947
+ # instId: 'LTC-USDT',
1948
+ # idxPx: '65.74',
1949
+ # open24h: '65.37',
1950
+ # high24h: '66.15',
1951
+ # low24h: '64.97',
1952
+ # sodUtc0: '65.68',
1953
+ # sodUtc8: '65.54',
1954
+ # ts: '1728467346900'
1955
+ # },
1748
1956
  #
1749
1957
  timestamp = self.safe_integer(ticker, 'ts')
1750
1958
  marketId = self.safe_string(ticker, 'instId')
@@ -1777,20 +1985,24 @@ class okx(Exchange, ImplicitAPI):
1777
1985
  'average': None,
1778
1986
  'baseVolume': baseVolume,
1779
1987
  'quoteVolume': quoteVolume,
1988
+ 'markPrice': self.safe_string(ticker, 'markPx'),
1989
+ 'indexPrice': self.safe_string(ticker, 'idxPx'),
1780
1990
  'info': ticker,
1781
1991
  }, market)
1782
1992
 
1783
1993
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1784
1994
  """
1785
1995
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1786
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-ticker
1996
+
1997
+ https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-ticker
1998
+
1787
1999
  :param str symbol: unified symbol of the market to fetch the ticker for
1788
2000
  :param dict [params]: extra parameters specific to the exchange API endpoint
1789
2001
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1790
2002
  """
1791
2003
  await self.load_markets()
1792
2004
  market = self.market(symbol)
1793
- request = {
2005
+ request: dict = {
1794
2006
  'instId': market['id'],
1795
2007
  }
1796
2008
  response = await self.publicGetMarketTicker(self.extend(request, params))
@@ -1820,20 +2032,33 @@ class okx(Exchange, ImplicitAPI):
1820
2032
  # ]
1821
2033
  # }
1822
2034
  #
1823
- data = self.safe_value(response, 'data', [])
1824
- first = self.safe_value(data, 0, {})
2035
+ data = self.safe_list(response, 'data', [])
2036
+ first = self.safe_dict(data, 0, {})
1825
2037
  return self.parse_ticker(first, market)
1826
2038
 
1827
- async def fetch_tickers_by_type(self, type, symbols: Strings = None, params={}):
2039
+ async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
2040
+ """
2041
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
2042
+
2043
+ https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-tickers
2044
+
2045
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
2046
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2047
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
2048
+ """
1828
2049
  await self.load_markets()
1829
- request = {
1830
- 'instType': self.convert_to_instrument_type(type),
2050
+ symbols = self.market_symbols(symbols)
2051
+ market = self.get_market_from_symbols(symbols)
2052
+ marketType = None
2053
+ marketType, params = self.handle_market_type_and_params('fetchTickers', market, params)
2054
+ request: dict = {
2055
+ 'instType': self.convert_to_instrument_type(marketType),
1831
2056
  }
1832
- if type == 'option':
1833
- defaultUnderlying = self.safe_value(self.options, 'defaultUnderlying', 'BTC-USD')
2057
+ if marketType == 'option':
2058
+ defaultUnderlying = self.safe_string(self.options, 'defaultUnderlying', 'BTC-USD')
1834
2059
  currencyId = self.safe_string_2(params, 'uly', 'marketId', defaultUnderlying)
1835
2060
  if currencyId is None:
1836
- raise ArgumentsRequired(self.id + ' fetchTickersByType() requires an underlying uly or marketId parameter for options markets')
2061
+ raise ArgumentsRequired(self.id + ' fetchTickers() requires an underlying uly or marketId parameter for options markets')
1837
2062
  else:
1838
2063
  request['uly'] = currencyId
1839
2064
  response = await self.publicGetMarketTickers(self.extend(request, params))
@@ -1863,27 +2088,72 @@ class okx(Exchange, ImplicitAPI):
1863
2088
  # ]
1864
2089
  # }
1865
2090
  #
1866
- tickers = self.safe_value(response, 'data', [])
2091
+ tickers = self.safe_list(response, 'data', [])
1867
2092
  return self.parse_tickers(tickers, symbols)
1868
2093
 
1869
- async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
2094
+ async def fetch_mark_price(self, symbol: str, params={}) -> Ticker:
2095
+ """
2096
+ fetches mark price for the market
2097
+
2098
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-mark-price
2099
+
2100
+ :param str symbol: unified symbol of the market to fetch the ticker for
2101
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2102
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
2103
+ """
2104
+ await self.load_markets()
2105
+ market = self.market(symbol)
2106
+ request: dict = {
2107
+ 'instId': market['id'],
2108
+ }
2109
+ response = await self.publicGetPublicMarkPrice(self.extend(request, params))
2110
+ #
2111
+ # {
2112
+ # "code": "0",
2113
+ # "data": [
2114
+ # {
2115
+ # "instId": "ETH-USDT",
2116
+ # "instType": "MARGIN",
2117
+ # "markPx": "2403.98",
2118
+ # "ts": "1728578500703"
2119
+ # }
2120
+ # ],
2121
+ # "msg": ""
2122
+ # }
2123
+ #
2124
+ data = self.safe_list(response, 'data')
2125
+ return self.parse_ticker(self.safe_dict(data, 0), market)
2126
+
2127
+ async def fetch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1870
2128
  """
1871
2129
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1872
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-tickers
1873
- :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
2130
+
2131
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-mark-price
2132
+
2133
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1874
2134
  :param dict [params]: extra parameters specific to the exchange API endpoint
1875
2135
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1876
2136
  """
1877
2137
  await self.load_markets()
1878
2138
  symbols = self.market_symbols(symbols)
1879
- first = self.safe_string(symbols, 0)
1880
- market = None
1881
- if first is not None:
1882
- market = self.market(first)
1883
- type, query = self.handle_market_type_and_params('fetchTickers', market, params)
1884
- return await self.fetch_tickers_by_type(type, symbols, query)
2139
+ market = self.get_market_from_symbols(symbols)
2140
+ marketType = None
2141
+ marketType, params = self.handle_market_type_and_params('fetchTickers', market, params, 'swap')
2142
+ request: dict = {
2143
+ 'instType': self.convert_to_instrument_type(marketType),
2144
+ }
2145
+ if marketType == 'option':
2146
+ defaultUnderlying = self.safe_string(self.options, 'defaultUnderlying', 'BTC-USD')
2147
+ currencyId = self.safe_string_2(params, 'uly', 'marketId', defaultUnderlying)
2148
+ if currencyId is None:
2149
+ raise ArgumentsRequired(self.id + ' fetchMarkPrices() requires an underlying uly or marketId parameter for options markets')
2150
+ else:
2151
+ request['uly'] = currencyId
2152
+ response = await self.publicGetPublicMarkPrice(self.extend(request, params))
2153
+ tickers = self.safe_list(response, 'data', [])
2154
+ return self.parse_tickers(tickers, symbols)
1885
2155
 
1886
- def parse_trade(self, trade, market: Market = None) -> Trade:
2156
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1887
2157
  #
1888
2158
  # public fetchTrades
1889
2159
  #
@@ -1976,12 +2246,15 @@ class okx(Exchange, ImplicitAPI):
1976
2246
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1977
2247
  """
1978
2248
  get the list of most recent trades for a particular symbol
1979
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-trades
1980
- :see: https://www.okx.com/docs-v5/en/#rest-api-public-data-get-option-trades
2249
+
2250
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-trades
2251
+ https://www.okx.com/docs-v5/en/#rest-api-public-data-get-option-trades
2252
+
1981
2253
  :param str symbol: unified symbol of the market to fetch trades for
1982
2254
  :param int [since]: timestamp in ms of the earliest trade to fetch
1983
2255
  :param int [limit]: the maximum amount of trades to fetch
1984
2256
  :param dict [params]: extra parameters specific to the exchange API endpoint
2257
+ :param str [params.method]: 'publicGetMarketTrades' or 'publicGetMarketHistoryTrades' default is 'publicGetMarketTrades'
1985
2258
  :param boolean [params.paginate]: *only applies to publicGetMarketHistoryTrades* default False, when True will automatically paginate by calling self endpoint multiple times
1986
2259
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1987
2260
  """
@@ -1991,7 +2264,7 @@ class okx(Exchange, ImplicitAPI):
1991
2264
  if paginate:
1992
2265
  return await self.fetch_paginated_call_cursor('fetchTrades', symbol, since, limit, params, 'tradeId', 'after', None, 100)
1993
2266
  market = self.market(symbol)
1994
- request = {
2267
+ request: dict = {
1995
2268
  'instId': market['id'],
1996
2269
  }
1997
2270
  response = None
@@ -2040,7 +2313,7 @@ class okx(Exchange, ImplicitAPI):
2040
2313
  # "msg": ""
2041
2314
  # }
2042
2315
  #
2043
- data = self.safe_value(response, 'data', [])
2316
+ data = self.safe_list(response, 'data', [])
2044
2317
  return self.parse_trades(data, market, since, limit)
2045
2318
 
2046
2319
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
@@ -2072,12 +2345,14 @@ class okx(Exchange, ImplicitAPI):
2072
2345
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
2073
2346
  """
2074
2347
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
2075
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks
2076
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history
2077
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-mark-price-candlesticks
2078
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-mark-price-candlesticks-history
2079
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-index-candlesticks
2080
- :see: https://www.okx.com/docs-v5/en/#rest-api-market-data-get-index-candlesticks-history
2348
+
2349
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks
2350
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history
2351
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-mark-price-candlesticks
2352
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-mark-price-candlesticks-history
2353
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-index-candlesticks
2354
+ https://www.okx.com/docs-v5/en/#rest-api-market-data-get-index-candlesticks-history
2355
+
2081
2356
  :param str symbol: unified symbol of the market to fetch OHLCV data for
2082
2357
  :param str timeframe: the length of time each candle represents
2083
2358
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -2096,7 +2371,7 @@ class okx(Exchange, ImplicitAPI):
2096
2371
  return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 200)
2097
2372
  price = self.safe_string(params, 'price')
2098
2373
  params = self.omit(params, 'price')
2099
- options = self.safe_value(self.options, 'fetchOHLCV', {})
2374
+ options = self.safe_dict(self.options, 'fetchOHLCV', {})
2100
2375
  timezone = self.safe_string(options, 'timezone', 'UTC')
2101
2376
  if limit is None:
2102
2377
  limit = 100 # default 100, max 100
@@ -2104,7 +2379,7 @@ class okx(Exchange, ImplicitAPI):
2104
2379
  bar = self.safe_string(self.timeframes, timeframe, timeframe)
2105
2380
  if (timezone == 'UTC') and (duration >= 21600): # if utc and timeframe >= 6h
2106
2381
  bar += timezone.lower()
2107
- request = {
2382
+ request: dict = {
2108
2383
  'instId': market['id'],
2109
2384
  'bar': bar,
2110
2385
  'limit': limit,
@@ -2156,13 +2431,15 @@ class okx(Exchange, ImplicitAPI):
2156
2431
  # ]
2157
2432
  # }
2158
2433
  #
2159
- data = self.safe_value(response, 'data', [])
2434
+ data = self.safe_list(response, 'data', [])
2160
2435
  return self.parse_ohlcvs(data, market, timeframe, since, limit)
2161
2436
 
2162
2437
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2163
2438
  """
2164
2439
  fetches historical funding rate prices
2165
- :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-funding-rate-history
2440
+
2441
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-funding-rate-history
2442
+
2166
2443
  :param str symbol: unified symbol of the market to fetch the funding rate history for
2167
2444
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
2168
2445
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
@@ -2178,7 +2455,7 @@ class okx(Exchange, ImplicitAPI):
2178
2455
  if paginate:
2179
2456
  return await self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 100)
2180
2457
  market = self.market(symbol)
2181
- request = {
2458
+ request: dict = {
2182
2459
  'instId': market['id'],
2183
2460
  }
2184
2461
  if since is not None:
@@ -2209,7 +2486,7 @@ class okx(Exchange, ImplicitAPI):
2209
2486
  # }
2210
2487
  #
2211
2488
  rates = []
2212
- data = self.safe_value(response, 'data', [])
2489
+ data = self.safe_list(response, 'data', [])
2213
2490
  for i in range(0, len(data)):
2214
2491
  rate = data[i]
2215
2492
  timestamp = self.safe_integer(rate, 'fundingTime')
@@ -2230,11 +2507,11 @@ class okx(Exchange, ImplicitAPI):
2230
2507
  return self.parse_trading_balance(response)
2231
2508
 
2232
2509
  def parse_trading_balance(self, response):
2233
- result = {'info': response}
2234
- data = self.safe_value(response, 'data', [])
2235
- first = self.safe_value(data, 0, {})
2510
+ result: dict = {'info': response}
2511
+ data = self.safe_list(response, 'data', [])
2512
+ first = self.safe_dict(data, 0, {})
2236
2513
  timestamp = self.safe_integer(first, 'uTime')
2237
- details = self.safe_value(first, 'details', [])
2514
+ details = self.safe_list(first, 'details', [])
2238
2515
  for i in range(0, len(details)):
2239
2516
  balance = details[i]
2240
2517
  currencyId = self.safe_string(balance, 'ccy')
@@ -2255,8 +2532,8 @@ class okx(Exchange, ImplicitAPI):
2255
2532
  return self.safe_balance(result)
2256
2533
 
2257
2534
  def parse_funding_balance(self, response):
2258
- result = {'info': response}
2259
- data = self.safe_value(response, 'data', [])
2535
+ result: dict = {'info': response}
2536
+ data = self.safe_list(response, 'data', [])
2260
2537
  for i in range(0, len(data)):
2261
2538
  balance = data[i]
2262
2539
  currencyId = self.safe_string(balance, 'ccy')
@@ -2269,7 +2546,7 @@ class okx(Exchange, ImplicitAPI):
2269
2546
  result[code] = account
2270
2547
  return self.safe_balance(result)
2271
2548
 
2272
- def parse_trading_fee(self, fee, market: Market = None):
2549
+ def parse_trading_fee(self, fee: dict, market: Market = None) -> TradingFeeInterface:
2273
2550
  # https://www.okx.com/docs-v5/en/#rest-api-account-get-fee-rates
2274
2551
  #
2275
2552
  # {
@@ -2289,19 +2566,23 @@ class okx(Exchange, ImplicitAPI):
2289
2566
  # OKX returns the fees values opposed to other exchanges, so the sign needs to be flipped
2290
2567
  'maker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'maker', 'makerU'))),
2291
2568
  'taker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'taker', 'takerU'))),
2569
+ 'percentage': None,
2570
+ 'tierBased': None,
2292
2571
  }
2293
2572
 
2294
- async def fetch_trading_fee(self, symbol: str, params={}):
2573
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2295
2574
  """
2296
2575
  fetch the trading fees for a market
2297
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-fee-rates
2576
+
2577
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-fee-rates
2578
+
2298
2579
  :param str symbol: unified market symbol
2299
2580
  :param dict [params]: extra parameters specific to the exchange API endpoint
2300
2581
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
2301
2582
  """
2302
2583
  await self.load_markets()
2303
2584
  market = self.market(symbol)
2304
- request = {
2585
+ request: dict = {
2305
2586
  'instType': self.convert_to_instrument_type(market['type']), # SPOT, MARGIN, SWAP, FUTURES, OPTION
2306
2587
  # "instId": market["id"], # only applicable to SPOT/MARGIN
2307
2588
  # "uly": market["id"], # only applicable to FUTURES/SWAP/OPTION
@@ -2332,21 +2613,24 @@ class okx(Exchange, ImplicitAPI):
2332
2613
  # "msg": ""
2333
2614
  # }
2334
2615
  #
2335
- data = self.safe_value(response, 'data', [])
2336
- first = self.safe_value(data, 0, {})
2616
+ data = self.safe_list(response, 'data', [])
2617
+ first = self.safe_dict(data, 0, {})
2337
2618
  return self.parse_trading_fee(first, market)
2338
2619
 
2339
2620
  async def fetch_balance(self, params={}) -> Balances:
2340
2621
  """
2341
2622
  query for balance and get the amount of funds available for trading or funds locked in orders
2342
- :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-balance
2343
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-balance
2623
+
2624
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-balance
2625
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-balance
2626
+
2344
2627
  :param dict [params]: extra parameters specific to the exchange API endpoint
2628
+ :param str [params.type]: wallet type, ['funding' or 'trading'] default is 'trading'
2345
2629
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
2346
2630
  """
2347
2631
  await self.load_markets()
2348
2632
  marketType, query = self.handle_market_type_and_params('fetchBalance', None, params)
2349
- request = {
2633
+ request: dict = {
2350
2634
  # 'ccy': 'BTC,ETH', # comma-separated list of currency ids
2351
2635
  }
2352
2636
  response = None
@@ -2460,7 +2744,9 @@ class okx(Exchange, ImplicitAPI):
2460
2744
 
2461
2745
  async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
2462
2746
  """
2463
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
2747
+
2748
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
2749
+
2464
2750
  create a market buy order by providing the symbol and cost
2465
2751
  :param str symbol: unified symbol of the market to create an order in
2466
2752
  :param float cost: how much you want to trade in units of the quote currency
@@ -2471,13 +2757,17 @@ class okx(Exchange, ImplicitAPI):
2471
2757
  market = self.market(symbol)
2472
2758
  if not market['spot']:
2473
2759
  raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot markets only')
2474
- params['createMarketBuyOrderRequiresPrice'] = False
2475
- params['tgtCcy'] = 'quote_ccy'
2476
- return await self.create_order(symbol, 'market', 'buy', cost, None, params)
2760
+ req = {
2761
+ 'createMarketBuyOrderRequiresPrice': False,
2762
+ 'tgtCcy': 'quote_ccy',
2763
+ }
2764
+ return await self.create_order(symbol, 'market', 'buy', cost, None, self.extend(req, params))
2477
2765
 
2478
2766
  async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
2479
2767
  """
2480
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
2768
+
2769
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
2770
+
2481
2771
  create a market buy order by providing the symbol and cost
2482
2772
  :param str symbol: unified symbol of the market to create an order in
2483
2773
  :param float cost: how much you want to trade in units of the quote currency
@@ -2488,13 +2778,15 @@ class okx(Exchange, ImplicitAPI):
2488
2778
  market = self.market(symbol)
2489
2779
  if not market['spot']:
2490
2780
  raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot markets only')
2491
- params['createMarketBuyOrderRequiresPrice'] = False
2492
- params['tgtCcy'] = 'quote_ccy'
2493
- return await self.create_order(symbol, 'market', 'sell', cost, None, params)
2781
+ req = {
2782
+ 'createMarketBuyOrderRequiresPrice': False,
2783
+ 'tgtCcy': 'quote_ccy',
2784
+ }
2785
+ return await self.create_order(symbol, 'market', 'sell', cost, None, self.extend(req, params))
2494
2786
 
2495
2787
  def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2496
2788
  market = self.market(symbol)
2497
- request = {
2789
+ request: dict = {
2498
2790
  'instId': market['id'],
2499
2791
  # 'ccy': currency['id'], # only applicable to cross MARGIN orders in single-currency margin
2500
2792
  # 'clOrdId': clientOrderId, # up to 32 characters, must be unique
@@ -2537,6 +2829,8 @@ class okx(Exchange, ImplicitAPI):
2537
2829
  takeProfitDefined = (takeProfit is not None)
2538
2830
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRatio')
2539
2831
  isTrailingPercentOrder = trailingPercent is not None
2832
+ trigger = (triggerPrice is not None) or (type == 'trigger')
2833
+ isReduceOnly = self.safe_value(params, 'reduceOnly', False)
2540
2834
  defaultMarginMode = self.safe_string_2(self.options, 'defaultMarginMode', 'marginMode', 'cross')
2541
2835
  marginMode = self.safe_string_2(params, 'marginMode', 'tdMode') # cross or isolated, tdMode not ommited so be extended into the request
2542
2836
  margin = False
@@ -2558,6 +2852,20 @@ class okx(Exchange, ImplicitAPI):
2558
2852
  positionSide, params = self.handle_option_and_params(params, 'createOrder', 'positionSide')
2559
2853
  if positionSide is not None:
2560
2854
  request['posSide'] = positionSide
2855
+ else:
2856
+ hedged = None
2857
+ hedged, params = self.handle_option_and_params(params, 'createOrder', 'hedged')
2858
+ if hedged:
2859
+ isBuy = (side == 'buy')
2860
+ isProtective = (takeProfitPrice is not None) or (stopLossPrice is not None) or isReduceOnly
2861
+ if isProtective:
2862
+ # in case of protective orders, the posSide should be opposite of position side
2863
+ # reduceOnly is emulated and not natively supported by the exchange
2864
+ request['posSide'] = 'short' if isBuy else 'long'
2865
+ if isReduceOnly:
2866
+ params = self.omit(params, 'reduceOnly')
2867
+ else:
2868
+ request['posSide'] = 'long' if isBuy else 'short'
2561
2869
  request['tdMode'] = marginMode
2562
2870
  isMarketOrder = type == 'market'
2563
2871
  postOnly = False
@@ -2565,7 +2873,6 @@ class okx(Exchange, ImplicitAPI):
2565
2873
  params = self.omit(params, ['currency', 'ccy', 'marginMode', 'timeInForce', 'stopPrice', 'triggerPrice', 'clientOrderId', 'stopLossPrice', 'takeProfitPrice', 'slOrdPx', 'tpOrdPx', 'margin', 'stopLoss', 'takeProfit', 'trailingPercent'])
2566
2874
  ioc = (timeInForce == 'IOC') or (type == 'ioc')
2567
2875
  fok = (timeInForce == 'FOK') or (type == 'fok')
2568
- trigger = (triggerPrice is not None) or (type == 'trigger')
2569
2876
  conditional = (stopLossPrice is not None) or (takeProfitPrice is not None) or (type == 'conditional')
2570
2877
  marketIOC = (isMarketOrder and ioc) or (type == 'optimal_limit_ioc')
2571
2878
  defaultTgtCcy = self.safe_string(self.options, 'tgtCcy', 'base_ccy')
@@ -2702,14 +3009,16 @@ class okx(Exchange, ImplicitAPI):
2702
3009
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2703
3010
  """
2704
3011
  create a trade order
2705
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
2706
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
2707
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-place-algo-order
3012
+
3013
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
3014
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
3015
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-place-algo-order
3016
+
2708
3017
  :param str symbol: unified symbol of the market to create an order in
2709
3018
  :param str type: 'market' or 'limit'
2710
3019
  :param str side: 'buy' or 'sell'
2711
3020
  :param float amount: how much of currency you want to trade in units of base currency
2712
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
3021
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2713
3022
  :param dict [params]: extra parameters specific to the exchange API endpoint
2714
3023
  :param bool [params.reduceOnly]: a mark to reduce the position size for margin, swap and future orders
2715
3024
  :param bool [params.postOnly]: True to place a post only order
@@ -2724,6 +3033,7 @@ class okx(Exchange, ImplicitAPI):
2724
3033
  :param str [params.positionSide]: if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
2725
3034
  :param str [params.trailingPercent]: the percent to trail away from the current market price
2726
3035
  :param str [params.tpOrdKind]: 'condition' or 'limit', the default is 'condition'
3036
+ :param bool [params.hedged]: *swap and future only* True for hedged mode, False for one way mode
2727
3037
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2728
3038
  """
2729
3039
  await self.load_markets()
@@ -2747,8 +3057,8 @@ class okx(Exchange, ImplicitAPI):
2747
3057
  response = await self.privatePostTradeOrderAlgo(request)
2748
3058
  else:
2749
3059
  response = await self.privatePostTradeBatchOrders(request)
2750
- data = self.safe_value(response, 'data', [])
2751
- first = self.safe_value(data, 0)
3060
+ data = self.safe_list(response, 'data', [])
3061
+ first = self.safe_dict(data, 0, {})
2752
3062
  order = self.parse_order(first, market)
2753
3063
  order['type'] = type
2754
3064
  order['side'] = side
@@ -2757,8 +3067,11 @@ class okx(Exchange, ImplicitAPI):
2757
3067
  async def create_orders(self, orders: List[OrderRequest], params={}):
2758
3068
  """
2759
3069
  create a list of trade orders
2760
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
3070
+
3071
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
3072
+
2761
3073
  :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
3074
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2762
3075
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2763
3076
  """
2764
3077
  await self.load_markets()
@@ -2770,7 +3083,7 @@ class okx(Exchange, ImplicitAPI):
2770
3083
  side = self.safe_string(rawOrder, 'side')
2771
3084
  amount = self.safe_value(rawOrder, 'amount')
2772
3085
  price = self.safe_value(rawOrder, 'price')
2773
- orderParams = self.safe_value(rawOrder, 'params', {})
3086
+ orderParams = self.safe_dict(rawOrder, 'params', {})
2774
3087
  extendedParams = self.extend(orderParams, params) # the request does not accept extra params since it's a list, so we're extending each order with the common params
2775
3088
  orderRequest = self.create_order_request(marketId, type, side, amount, price, extendedParams)
2776
3089
  ordersRequests.append(orderRequest)
@@ -2797,12 +3110,12 @@ class okx(Exchange, ImplicitAPI):
2797
3110
  # "msg": "",
2798
3111
  # "outTime": "1697979038586493"
2799
3112
  # }
2800
- data = self.safe_value(response, 'data', [])
3113
+ data = self.safe_list(response, 'data', [])
2801
3114
  return self.parse_orders(data)
2802
3115
 
2803
3116
  def edit_order_request(self, id: str, symbol, type, side, amount=None, price=None, params={}):
2804
3117
  market = self.market(symbol)
2805
- request = {
3118
+ request: dict = {
2806
3119
  'instId': market['id'],
2807
3120
  }
2808
3121
  isAlgoOrder = None
@@ -2873,20 +3186,22 @@ class okx(Exchange, ImplicitAPI):
2873
3186
  if not isAlgoOrder:
2874
3187
  if price is not None:
2875
3188
  request['newPx'] = self.price_to_precision(symbol, price)
2876
- params = self.omit(params, ['clOrdId', 'clientOrderId', 'takeProfitPrice', 'stopLossPrice', 'stopLoss', 'takeProfit'])
3189
+ params = self.omit(params, ['clOrdId', 'clientOrderId', 'takeProfitPrice', 'stopLossPrice', 'stopLoss', 'takeProfit', 'postOnly'])
2877
3190
  return self.extend(request, params)
2878
3191
 
2879
3192
  async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
2880
3193
  """
2881
3194
  edit a trade order
2882
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-amend-order
2883
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-amend-algo-order
3195
+
3196
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-amend-order
3197
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-amend-algo-order
3198
+
2884
3199
  :param str id: order id
2885
3200
  :param str symbol: unified symbol of the market to create an order in
2886
3201
  :param str type: 'market' or 'limit'
2887
3202
  :param str side: 'buy' or 'sell'
2888
3203
  :param float amount: how much of the currency you want to trade in units of the base currency
2889
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
3204
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2890
3205
  :param dict [params]: extra parameters specific to the exchange API endpoint
2891
3206
  :param str [params.clientOrderId]: client order id, uses id if not passed
2892
3207
  :param float [params.stopLossPrice]: stop loss trigger price
@@ -2932,8 +3247,8 @@ class okx(Exchange, ImplicitAPI):
2932
3247
  # "msg": ""
2933
3248
  # }
2934
3249
  #
2935
- data = self.safe_value(response, 'data', [])
2936
- first = self.safe_value(data, 0)
3250
+ data = self.safe_list(response, 'data', [])
3251
+ first = self.safe_dict(data, 0, {})
2937
3252
  order = self.parse_order(first, market)
2938
3253
  order['type'] = type
2939
3254
  order['side'] = side
@@ -2942,8 +3257,10 @@ class okx(Exchange, ImplicitAPI):
2942
3257
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
2943
3258
  """
2944
3259
  cancels an open order
2945
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-order
2946
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-cancel-algo-order
3260
+
3261
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-order
3262
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-cancel-algo-order
3263
+
2947
3264
  :param str id: order id
2948
3265
  :param str symbol: unified symbol of the market the order was made in
2949
3266
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2953,14 +3270,14 @@ class okx(Exchange, ImplicitAPI):
2953
3270
  """
2954
3271
  if symbol is None:
2955
3272
  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
2956
- stop = self.safe_value_2(params, 'stop', 'trigger')
3273
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
2957
3274
  trailing = self.safe_bool(params, 'trailing', False)
2958
- if stop or trailing:
3275
+ if trigger or trailing:
2959
3276
  orderInner = await self.cancel_orders([id], symbol, params)
2960
3277
  return self.safe_value(orderInner, 0)
2961
3278
  await self.load_markets()
2962
3279
  market = self.market(symbol)
2963
- request = {
3280
+ request: dict = {
2964
3281
  'instId': market['id'],
2965
3282
  # 'ordId': id, # either ordId or clOrdId is required
2966
3283
  # 'clOrdId': clientOrderId,
@@ -2974,12 +3291,12 @@ class okx(Exchange, ImplicitAPI):
2974
3291
  response = await self.privatePostTradeCancelOrder(self.extend(request, query))
2975
3292
  # {"code":"0","data":[{"clOrdId":"","ordId":"317251910906576896","sCode":"0","sMsg":""}],"msg":""}
2976
3293
  data = self.safe_value(response, 'data', [])
2977
- order = self.safe_value(data, 0)
3294
+ order = self.safe_dict(data, 0)
2978
3295
  return self.parse_order(order, market)
2979
3296
 
2980
3297
  def parse_ids(self, ids):
2981
3298
  """
2982
- * @ignore
3299
+ @ignore
2983
3300
  :param string[]|str ids: order ids
2984
3301
  :returns str[]: list of order ids
2985
3302
  """
@@ -2991,8 +3308,10 @@ class okx(Exchange, ImplicitAPI):
2991
3308
  async def cancel_orders(self, ids, symbol: Str = None, params={}):
2992
3309
  """
2993
3310
  cancel multiple orders
2994
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-multiple-orders
2995
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-cancel-algo-order
3311
+
3312
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-multiple-orders
3313
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-cancel-algo-order
3314
+
2996
3315
  :param str[] ids: order ids
2997
3316
  :param str symbol: unified market symbol
2998
3317
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3011,9 +3330,9 @@ class okx(Exchange, ImplicitAPI):
3011
3330
  method = self.safe_string(params, 'method', defaultMethod)
3012
3331
  clientOrderIds = self.parse_ids(self.safe_value_2(params, 'clOrdId', 'clientOrderId'))
3013
3332
  algoIds = self.parse_ids(self.safe_value(params, 'algoId'))
3014
- stop = self.safe_value_2(params, 'stop', 'trigger')
3333
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
3015
3334
  trailing = self.safe_bool(params, 'trailing', False)
3016
- if stop or trailing:
3335
+ if trigger or trailing:
3017
3336
  method = 'privatePostTradeCancelAlgos'
3018
3337
  if clientOrderIds is None:
3019
3338
  ids = self.parse_ids(ids)
@@ -3024,7 +3343,7 @@ class okx(Exchange, ImplicitAPI):
3024
3343
  'instId': market['id'],
3025
3344
  })
3026
3345
  for i in range(0, len(ids)):
3027
- if trailing or stop:
3346
+ if trailing or trigger:
3028
3347
  request.append({
3029
3348
  'algoId': ids[i],
3030
3349
  'instId': market['id'],
@@ -3074,11 +3393,116 @@ class okx(Exchange, ImplicitAPI):
3074
3393
  # "msg": ""
3075
3394
  # }
3076
3395
  #
3077
- ordersData = self.safe_value(response, 'data', [])
3396
+ ordersData = self.safe_list(response, 'data', [])
3078
3397
  return self.parse_orders(ordersData, market, None, None, params)
3079
3398
 
3080
- def parse_order_status(self, status):
3081
- statuses = {
3399
+ async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
3400
+ """
3401
+ cancel multiple orders for multiple symbols
3402
+
3403
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-multiple-orders
3404
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-cancel-algo-order
3405
+
3406
+ :param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol, example [{"id": "a", "symbol": "BTC/USDT"}, {"id": "b", "symbol": "ETH/USDT"}]
3407
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3408
+ :param boolean [params.trigger]: whether the order is a stop/trigger order
3409
+ :param boolean [params.trailing]: set to True if you want to cancel trailing orders
3410
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3411
+ """
3412
+ await self.load_markets()
3413
+ request = []
3414
+ options = self.safe_dict(self.options, 'cancelOrders', {})
3415
+ defaultMethod = self.safe_string(options, 'method', 'privatePostTradeCancelBatchOrders')
3416
+ method = self.safe_string(params, 'method', defaultMethod)
3417
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
3418
+ trailing = self.safe_bool(params, 'trailing', False)
3419
+ isStopOrTrailing = trigger or trailing
3420
+ if isStopOrTrailing:
3421
+ method = 'privatePostTradeCancelAlgos'
3422
+ for i in range(0, len(orders)):
3423
+ order = orders[i]
3424
+ id = self.safe_string(order, 'id')
3425
+ clientOrderId = self.safe_string_2(order, 'clOrdId', 'clientOrderId')
3426
+ symbol = self.safe_string(order, 'symbol')
3427
+ market = self.market(symbol)
3428
+ idKey = 'ordId'
3429
+ if isStopOrTrailing:
3430
+ idKey = 'algoId'
3431
+ elif clientOrderId is not None:
3432
+ idKey = 'clOrdId'
3433
+ requestItem: dict = {
3434
+ 'instId': market['id'],
3435
+ }
3436
+ requestItem[idKey] = clientOrderId if (clientOrderId is not None) else id
3437
+ request.append(requestItem)
3438
+ response = None
3439
+ if method == 'privatePostTradeCancelAlgos':
3440
+ response = await self.privatePostTradeCancelAlgos(request) # * dont self.extend with params, otherwise ARRAY will be turned into OBJECT
3441
+ else:
3442
+ response = await self.privatePostTradeCancelBatchOrders(request) # * dont self.extend with params, otherwise ARRAY will be turned into OBJECT
3443
+ #
3444
+ # {
3445
+ # "code": "0",
3446
+ # "data": [
3447
+ # {
3448
+ # "clOrdId": "e123456789ec4dBC1123456ba123b45e",
3449
+ # "ordId": "405071912345641543",
3450
+ # "sCode": "0",
3451
+ # "sMsg": ""
3452
+ # },
3453
+ # ...
3454
+ # ],
3455
+ # "msg": ""
3456
+ # }
3457
+ #
3458
+ # Algo order
3459
+ #
3460
+ # {
3461
+ # "code": "0",
3462
+ # "data": [
3463
+ # {
3464
+ # "algoId": "431375349042380800",
3465
+ # "sCode": "0",
3466
+ # "sMsg": ""
3467
+ # }
3468
+ # ],
3469
+ # "msg": ""
3470
+ # }
3471
+ #
3472
+ ordersData = self.safe_list(response, 'data', [])
3473
+ return self.parse_orders(ordersData, None, None, None, params)
3474
+
3475
+ async def cancel_all_orders_after(self, timeout: Int, params={}):
3476
+ """
3477
+ dead man's switch, cancel all orders after the given timeout
3478
+
3479
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-cancel-all-after
3480
+
3481
+ :param number timeout: time in milliseconds, 0 represents cancel the timer
3482
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3483
+ :returns dict: the api result
3484
+ """
3485
+ await self.load_markets()
3486
+ request: dict = {
3487
+ 'timeOut': self.parse_to_int(timeout / 1000) if (timeout > 0) else 0,
3488
+ }
3489
+ response = await self.privatePostTradeCancelAllAfter(self.extend(request, params))
3490
+ #
3491
+ # {
3492
+ # "code":"0",
3493
+ # "msg":"",
3494
+ # "data":[
3495
+ # {
3496
+ # "triggerTime":"1587971460",
3497
+ # "ts":"1587971400"
3498
+ # }
3499
+ # ]
3500
+ # }
3501
+ #
3502
+ return response
3503
+
3504
+ def parse_order_status(self, status: Str):
3505
+ statuses: dict = {
3082
3506
  'canceled': 'canceled',
3083
3507
  'order_failed': 'canceled',
3084
3508
  'live': 'open',
@@ -3088,7 +3512,7 @@ class okx(Exchange, ImplicitAPI):
3088
3512
  }
3089
3513
  return self.safe_string(statuses, status, status)
3090
3514
 
3091
- def parse_order(self, order, market: Market = None) -> Order:
3515
+ def parse_order(self, order: dict, market: Market = None) -> Order:
3092
3516
  #
3093
3517
  # createOrder
3094
3518
  #
@@ -3254,7 +3678,6 @@ class okx(Exchange, ImplicitAPI):
3254
3678
  clientOrderId = None # fix empty clientOrderId string
3255
3679
  stopLossPrice = self.safe_number_2(order, 'slTriggerPx', 'slOrdPx')
3256
3680
  takeProfitPrice = self.safe_number_2(order, 'tpTriggerPx', 'tpOrdPx')
3257
- stopPrice = self.safe_number_n(order, ['triggerPx', 'moveTriggerPx'])
3258
3681
  reduceOnlyRaw = self.safe_string(order, 'reduceOnly')
3259
3682
  reduceOnly = False
3260
3683
  if reduceOnly is not None:
@@ -3275,8 +3698,7 @@ class okx(Exchange, ImplicitAPI):
3275
3698
  'price': price,
3276
3699
  'stopLossPrice': stopLossPrice,
3277
3700
  'takeProfitPrice': takeProfitPrice,
3278
- 'stopPrice': stopPrice,
3279
- 'triggerPrice': stopPrice,
3701
+ 'triggerPrice': self.safe_number_n(order, ['triggerPx', 'moveTriggerPx']),
3280
3702
  'average': average,
3281
3703
  'cost': cost,
3282
3704
  'amount': amount,
@@ -3291,8 +3713,10 @@ class okx(Exchange, ImplicitAPI):
3291
3713
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
3292
3714
  """
3293
3715
  fetch an order by the id
3294
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-details
3295
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-details
3716
+
3717
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-details
3718
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-details
3719
+
3296
3720
  :param str id: the order id
3297
3721
  :param str symbol: unified market symbol
3298
3722
  :param dict [params]: extra and exchange specific parameters
@@ -3303,7 +3727,7 @@ class okx(Exchange, ImplicitAPI):
3303
3727
  raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
3304
3728
  await self.load_markets()
3305
3729
  market = self.market(symbol)
3306
- request = {
3730
+ request: dict = {
3307
3731
  'instId': market['id'],
3308
3732
  # 'clOrdId': 'abcdef12345', # optional, [a-z0-9]{1,32}
3309
3733
  # 'ordId': id,
@@ -3313,8 +3737,8 @@ class okx(Exchange, ImplicitAPI):
3313
3737
  options = self.safe_value(self.options, 'fetchOrder', {})
3314
3738
  defaultMethod = self.safe_string(options, 'method', 'privateGetTradeOrder')
3315
3739
  method = self.safe_string(params, 'method', defaultMethod)
3316
- stop = self.safe_value_2(params, 'stop', 'trigger')
3317
- if stop:
3740
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
3741
+ if trigger:
3318
3742
  method = 'privateGetTradeOrderAlgo'
3319
3743
  if clientOrderId is not None:
3320
3744
  request['algoClOrdId'] = clientOrderId
@@ -3428,19 +3852,21 @@ class okx(Exchange, ImplicitAPI):
3428
3852
  # }
3429
3853
  #
3430
3854
  data = self.safe_value(response, 'data', [])
3431
- order = self.safe_value(data, 0)
3855
+ order = self.safe_dict(data, 0)
3432
3856
  return self.parse_order(order, market)
3433
3857
 
3434
3858
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3435
3859
  """
3436
3860
  fetch all unfilled currently open orders
3437
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-list
3438
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-list
3861
+
3862
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-list
3863
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-list
3864
+
3439
3865
  :param str symbol: unified market symbol
3440
3866
  :param int [since]: the earliest time in ms to fetch open orders for
3441
3867
  :param int [limit]: the maximum number of open orders structures to retrieve
3442
3868
  :param dict [params]: extra parameters specific to the exchange API endpoint
3443
- :param bool [params.stop]: True if fetching trigger or conditional orders
3869
+ :param bool [params.trigger]: True if fetching trigger or conditional orders
3444
3870
  :param str [params.ordType]: "conditional", "oco", "trigger", "move_order_stop", "iceberg", or "twap"
3445
3871
  :param str [params.algoId]: Algo ID "'433845797218942976'"
3446
3872
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
@@ -3452,7 +3878,7 @@ class okx(Exchange, ImplicitAPI):
3452
3878
  paginate, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'paginate')
3453
3879
  if paginate:
3454
3880
  return await self.fetch_paginated_call_dynamic('fetchOpenOrders', symbol, since, limit, params)
3455
- request = {
3881
+ request: dict = {
3456
3882
  # 'instType': 'SPOT', # SPOT, MARGIN, SWAP, FUTURES, OPTION
3457
3883
  # 'uly': currency['id'],
3458
3884
  # 'instId': market['id'],
@@ -3473,13 +3899,13 @@ class okx(Exchange, ImplicitAPI):
3473
3899
  defaultMethod = self.safe_string(options, 'method', 'privateGetTradeOrdersPending')
3474
3900
  method = self.safe_string(params, 'method', defaultMethod)
3475
3901
  ordType = self.safe_string(params, 'ordType')
3476
- stop = self.safe_value_2(params, 'stop', 'trigger')
3902
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
3477
3903
  trailing = self.safe_bool(params, 'trailing', False)
3478
- if trailing or stop or (ordType in algoOrderTypes):
3904
+ if trailing or trigger or (ordType in algoOrderTypes):
3479
3905
  method = 'privateGetTradeOrdersAlgoPending'
3480
3906
  if trailing:
3481
3907
  request['ordType'] = 'move_order_stop'
3482
- elif stop and (ordType is None):
3908
+ elif trigger and (ordType is None):
3483
3909
  request['ordType'] = 'trigger'
3484
3910
  query = self.omit(params, ['method', 'stop', 'trigger', 'trailing'])
3485
3911
  response = None
@@ -3582,19 +4008,21 @@ class okx(Exchange, ImplicitAPI):
3582
4008
  # "msg": ""
3583
4009
  # }
3584
4010
  #
3585
- data = self.safe_value(response, 'data', [])
4011
+ data = self.safe_list(response, 'data', [])
3586
4012
  return self.parse_orders(data, market, since, limit)
3587
4013
 
3588
4014
  async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3589
4015
  """
3590
4016
  fetches information on multiple canceled orders made by the user
3591
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-7-days
3592
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-history
4017
+
4018
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-7-days
4019
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-history
4020
+
3593
4021
  :param str symbol: unified market symbol of the market orders were made in
3594
4022
  :param int [since]: timestamp in ms of the earliest order, default is None
3595
4023
  :param int [limit]: max number of orders to return, default is None
3596
4024
  :param dict [params]: extra parameters specific to the exchange API endpoint
3597
- :param bool [params.stop]: True if fetching trigger or conditional orders
4025
+ :param bool [params.trigger]: True if fetching trigger or conditional orders
3598
4026
  :param str [params.ordType]: "conditional", "oco", "trigger", "move_order_stop", "iceberg", or "twap"
3599
4027
  :param str [params.algoId]: Algo ID "'433845797218942976'"
3600
4028
  :param int [params.until]: timestamp in ms to fetch orders for
@@ -3602,7 +4030,7 @@ class okx(Exchange, ImplicitAPI):
3602
4030
  :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3603
4031
  """
3604
4032
  await self.load_markets()
3605
- request = {
4033
+ request: dict = {
3606
4034
  # 'instType': type.upper(), # SPOT, MARGIN, SWAP, FUTURES, OPTION
3607
4035
  # 'uly': currency['id'],
3608
4036
  # 'instId': market['id'],
@@ -3629,27 +4057,27 @@ class okx(Exchange, ImplicitAPI):
3629
4057
  defaultMethod = self.safe_string(options, 'method', 'privateGetTradeOrdersHistory')
3630
4058
  method = self.safe_string(params, 'method', defaultMethod)
3631
4059
  ordType = self.safe_string(params, 'ordType')
3632
- stop = self.safe_value_2(params, 'stop', 'trigger')
4060
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
3633
4061
  trailing = self.safe_bool(params, 'trailing', False)
3634
4062
  if trailing:
3635
4063
  method = 'privateGetTradeOrdersAlgoHistory'
3636
4064
  request['ordType'] = 'move_order_stop'
3637
- elif stop or (ordType in algoOrderTypes):
4065
+ elif trigger or (ordType in algoOrderTypes):
3638
4066
  method = 'privateGetTradeOrdersAlgoHistory'
3639
4067
  algoId = self.safe_string(params, 'algoId')
3640
4068
  if algoId is not None:
3641
4069
  request['algoId'] = algoId
3642
4070
  params = self.omit(params, 'algoId')
3643
- if stop:
4071
+ if trigger:
3644
4072
  if ordType is None:
3645
4073
  raise ArgumentsRequired(self.id + ' fetchCanceledOrders() requires an "ordType" string parameter, "conditional", "oco", "trigger", "move_order_stop", "iceberg", or "twap"')
3646
4074
  else:
3647
4075
  if since is not None:
3648
4076
  request['begin'] = since
3649
- until = self.safe_integer_2(query, 'till', 'until')
4077
+ until = self.safe_integer(query, 'until')
3650
4078
  if until is not None:
3651
4079
  request['end'] = until
3652
- query = self.omit(query, ['until', 'till'])
4080
+ query = self.omit(query, ['until'])
3653
4081
  send = self.omit(query, ['method', 'stop', 'trigger', 'trailing'])
3654
4082
  response = None
3655
4083
  if method == 'privateGetTradeOrdersAlgoHistory':
@@ -3755,15 +4183,17 @@ class okx(Exchange, ImplicitAPI):
3755
4183
  # "msg": ""
3756
4184
  # }
3757
4185
  #
3758
- data = self.safe_value(response, 'data', [])
4186
+ data = self.safe_list(response, 'data', [])
3759
4187
  return self.parse_orders(data, market, since, limit)
3760
4188
 
3761
4189
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3762
4190
  """
3763
4191
  fetches information on multiple closed orders made by the user
3764
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-7-days
3765
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-history
3766
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-3-months
4192
+
4193
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-7-days
4194
+ https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-get-algo-order-history
4195
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-order-history-last-3-months
4196
+
3767
4197
  :param str symbol: unified market symbol of the market orders were made in
3768
4198
  :param int [since]: the earliest time in ms to fetch orders for
3769
4199
  :param int [limit]: the maximum number of order structures to retrieve
@@ -3782,7 +4212,7 @@ class okx(Exchange, ImplicitAPI):
3782
4212
  paginate, params = self.handle_option_and_params(params, 'fetchClosedOrders', 'paginate')
3783
4213
  if paginate:
3784
4214
  return await self.fetch_paginated_call_dynamic('fetchClosedOrders', symbol, since, limit, params)
3785
- request = {
4215
+ request: dict = {
3786
4216
  # 'instType': type.upper(), # SPOT, MARGIN, SWAP, FUTURES, OPTION
3787
4217
  # 'uly': currency['id'],
3788
4218
  # 'instId': market['id'],
@@ -3808,23 +4238,23 @@ class okx(Exchange, ImplicitAPI):
3808
4238
  defaultMethod = self.safe_string(options, 'method', 'privateGetTradeOrdersHistory')
3809
4239
  method = self.safe_string(params, 'method', defaultMethod)
3810
4240
  ordType = self.safe_string(params, 'ordType')
3811
- stop = self.safe_bool_2(params, 'stop', 'trigger')
4241
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
3812
4242
  trailing = self.safe_bool(params, 'trailing', False)
3813
- if trailing or stop or (ordType in algoOrderTypes):
4243
+ if trailing or trigger or (ordType in algoOrderTypes):
3814
4244
  method = 'privateGetTradeOrdersAlgoHistory'
3815
4245
  request['state'] = 'effective'
3816
4246
  if trailing:
3817
4247
  request['ordType'] = 'move_order_stop'
3818
- elif stop:
4248
+ elif trigger:
3819
4249
  if ordType is None:
3820
4250
  request['ordType'] = 'trigger'
3821
4251
  else:
3822
4252
  if since is not None:
3823
4253
  request['begin'] = since
3824
- until = self.safe_integer_2(query, 'till', 'until')
4254
+ until = self.safe_integer(query, 'until')
3825
4255
  if until is not None:
3826
4256
  request['end'] = until
3827
- query = self.omit(query, ['until', 'till'])
4257
+ query = self.omit(query, ['until'])
3828
4258
  request['state'] = 'filled'
3829
4259
  send = self.omit(query, ['method', 'stop', 'trigger', 'trailing'])
3830
4260
  response = None
@@ -3929,13 +4359,15 @@ class okx(Exchange, ImplicitAPI):
3929
4359
  # "msg": ""
3930
4360
  # }
3931
4361
  #
3932
- data = self.safe_value(response, 'data', [])
4362
+ data = self.safe_list(response, 'data', [])
3933
4363
  return self.parse_orders(data, market, since, limit)
3934
4364
 
3935
4365
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3936
4366
  """
3937
4367
  fetch all trades made by the user
3938
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-transaction-details-last-3-months
4368
+
4369
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-transaction-details-last-3-months
4370
+
3939
4371
  :param str symbol: unified market symbol
3940
4372
  :param int [since]: the earliest time in ms to fetch trades for
3941
4373
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -3949,7 +4381,7 @@ class okx(Exchange, ImplicitAPI):
3949
4381
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
3950
4382
  if paginate:
3951
4383
  return await self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
3952
- request = {
4384
+ request: dict = {
3953
4385
  # 'instType': 'SPOT', # SPOT, MARGIN, SWAP, FUTURES, OPTION
3954
4386
  # 'uly': currency['id'],
3955
4387
  # 'instId': market['id'],
@@ -3995,13 +4427,15 @@ class okx(Exchange, ImplicitAPI):
3995
4427
  # "msg": ""
3996
4428
  # }
3997
4429
  #
3998
- data = self.safe_value(response, 'data', [])
4430
+ data = self.safe_list(response, 'data', [])
3999
4431
  return self.parse_trades(data, market, since, limit, query)
4000
4432
 
4001
4433
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4002
4434
  """
4003
4435
  fetch all the trades made from a single order
4004
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-transaction-details-last-3-months
4436
+
4437
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-get-transaction-details-last-3-months
4438
+
4005
4439
  :param str id: order id
4006
4440
  :param str symbol: unified market symbol
4007
4441
  :param int [since]: the earliest time in ms to fetch trades for
@@ -4009,7 +4443,7 @@ class okx(Exchange, ImplicitAPI):
4009
4443
  :param dict [params]: extra parameters specific to the exchange API endpoint
4010
4444
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
4011
4445
  """
4012
- request = {
4446
+ request: dict = {
4013
4447
  # 'instrument_id': market['id'],
4014
4448
  'ordId': id,
4015
4449
  # 'after': '1', # return the page after the specified page number
@@ -4018,31 +4452,33 @@ class okx(Exchange, ImplicitAPI):
4018
4452
  }
4019
4453
  return await self.fetch_my_trades(symbol, since, limit, self.extend(request, params))
4020
4454
 
4021
- async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4455
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
4022
4456
  """
4023
4457
  fetch the history of changes, actions done by the user or operations that altered balance of the user
4024
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-bills-details-last-7-days
4025
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-bills-details-last-3-months
4026
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-asset-bills-details
4027
- :param str code: unified currency code, default is None
4458
+
4459
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-bills-details-last-7-days
4460
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-bills-details-last-3-months
4461
+ https://www.okx.com/docs-v5/en/#rest-api-funding-asset-bills-details
4462
+
4463
+ :param str [code]: unified currency code, default is None
4028
4464
  :param int [since]: timestamp in ms of the earliest ledger entry, default is None
4029
- :param int [limit]: max number of ledger entrys to return, default is None
4465
+ :param int [limit]: max number of ledger entries to return, default is None
4030
4466
  :param dict [params]: extra parameters specific to the exchange API endpoint
4031
4467
  :param str [params.marginMode]: 'cross' or 'isolated'
4032
4468
  :param int [params.until]: the latest time in ms to fetch entries for
4033
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4034
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
4469
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4470
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
4035
4471
  """
4036
4472
  await self.load_markets()
4037
4473
  paginate = False
4038
4474
  paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
4039
4475
  if paginate:
4040
4476
  return await self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params)
4041
- options = self.safe_value(self.options, 'fetchLedger', {})
4477
+ options = self.safe_dict(self.options, 'fetchLedger', {})
4042
4478
  method = self.safe_string(options, 'method')
4043
4479
  method = self.safe_string(params, 'method', method)
4044
4480
  params = self.omit(params, 'method')
4045
- request = {
4481
+ request: dict = {
4046
4482
  # 'instType': None, # 'SPOT', 'MARGIN', 'SWAP', 'FUTURES", 'OPTION'
4047
4483
  # 'ccy': None, # currency['id'],
4048
4484
  # 'mgnMode': None, # 'isolated', 'cross'
@@ -4127,11 +4563,11 @@ class okx(Exchange, ImplicitAPI):
4127
4563
  # ]
4128
4564
  # }
4129
4565
  #
4130
- data = self.safe_value(response, 'data', [])
4566
+ data = self.safe_list(response, 'data', [])
4131
4567
  return self.parse_ledger(data, currency, since, limit)
4132
4568
 
4133
4569
  def parse_ledger_entry_type(self, type):
4134
- types = {
4570
+ types: dict = {
4135
4571
  '1': 'transfer', # transfer
4136
4572
  '2': 'trade', # trade
4137
4573
  '3': 'trade', # delivery
@@ -4146,7 +4582,7 @@ class okx(Exchange, ImplicitAPI):
4146
4582
  }
4147
4583
  return self.safe_string(types, type, type)
4148
4584
 
4149
- def parse_ledger_entry(self, item, currency: Currency = None):
4585
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
4150
4586
  #
4151
4587
  # privateGetAccountBills, privateGetAccountBillsArchive
4152
4588
  #
@@ -4183,14 +4619,9 @@ class okx(Exchange, ImplicitAPI):
4183
4619
  # "ts": "1597026383085"
4184
4620
  # }
4185
4621
  #
4186
- id = self.safe_string(item, 'billId')
4187
- account = None
4188
- referenceId = self.safe_string(item, 'ordId')
4189
- referenceAccount = None
4190
- type = self.parse_ledger_entry_type(self.safe_string(item, 'type'))
4191
- code = self.safe_currency_code(self.safe_string(item, 'ccy'), currency)
4192
- amountString = self.safe_string(item, 'balChg')
4193
- amount = self.parse_number(amountString)
4622
+ currencyId = self.safe_string(item, 'ccy')
4623
+ code = self.safe_currency_code(currencyId, currency)
4624
+ currency = self.safe_currency(currencyId, currency)
4194
4625
  timestamp = self.safe_integer(item, 'ts')
4195
4626
  feeCostString = self.safe_string(item, 'fee')
4196
4627
  fee = None
@@ -4199,31 +4630,27 @@ class okx(Exchange, ImplicitAPI):
4199
4630
  'cost': self.parse_number(Precise.string_neg(feeCostString)),
4200
4631
  'currency': code,
4201
4632
  }
4202
- before = None
4203
- afterString = self.safe_string(item, 'bal')
4204
- after = self.parse_number(afterString)
4205
- status = 'ok'
4206
4633
  marketId = self.safe_string(item, 'instId')
4207
4634
  symbol = self.safe_symbol(marketId, None, '-')
4208
- return {
4209
- 'id': id,
4635
+ return self.safe_ledger_entry({
4210
4636
  'info': item,
4637
+ 'id': self.safe_string(item, 'billId'),
4211
4638
  'timestamp': timestamp,
4212
4639
  'datetime': self.iso8601(timestamp),
4213
- 'account': account,
4214
- 'referenceId': referenceId,
4215
- 'referenceAccount': referenceAccount,
4216
- 'type': type,
4640
+ 'account': None,
4641
+ 'referenceId': self.safe_string(item, 'ordId'),
4642
+ 'referenceAccount': None,
4643
+ 'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
4217
4644
  'currency': code,
4218
4645
  'symbol': symbol,
4219
- 'amount': amount,
4220
- 'before': before, # balance before
4221
- 'after': after, # balance after
4222
- 'status': status,
4646
+ 'amount': self.safe_number(item, 'balChg'),
4647
+ 'before': None,
4648
+ 'after': self.safe_number(item, 'bal'),
4649
+ 'status': 'ok',
4223
4650
  'fee': fee,
4224
- }
4651
+ }, currency)
4225
4652
 
4226
- def parse_deposit_address(self, depositAddress, currency: Currency = None):
4653
+ def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
4227
4654
  #
4228
4655
  # {
4229
4656
  # "addr": "okbtothemoon",
@@ -4311,24 +4738,26 @@ class okx(Exchange, ImplicitAPI):
4311
4738
  networkCode = self.network_id_to_code(network, code)
4312
4739
  self.check_address(address)
4313
4740
  return {
4741
+ 'info': depositAddress,
4314
4742
  'currency': code,
4743
+ 'network': networkCode,
4315
4744
  'address': address,
4316
4745
  'tag': tag,
4317
- 'network': networkCode,
4318
- 'info': depositAddress,
4319
4746
  }
4320
4747
 
4321
- async def fetch_deposit_addresses_by_network(self, code: str, params={}):
4748
+ async def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
4322
4749
  """
4323
4750
  fetch a dictionary of addresses for a currency, indexed by network
4324
- :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-deposit-address
4751
+
4752
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-deposit-address
4753
+
4325
4754
  :param str code: unified currency code of the currency for the deposit address
4326
4755
  :param dict [params]: extra parameters specific to the exchange API endpoint
4327
4756
  :returns dict: a dictionary of `address structures <https://docs.ccxt.com/#/?id=address-structure>` indexed by the network
4328
4757
  """
4329
4758
  await self.load_markets()
4330
4759
  currency = self.currency(code)
4331
- request = {
4760
+ request: dict = {
4332
4761
  'ccy': currency['id'],
4333
4762
  }
4334
4763
  response = await self.privateGetAssetDepositAddress(self.extend(request, params))
@@ -4353,48 +4782,47 @@ class okx(Exchange, ImplicitAPI):
4353
4782
  # ]
4354
4783
  # }
4355
4784
  #
4356
- data = self.safe_value(response, 'data', [])
4785
+ data = self.safe_list(response, 'data', [])
4357
4786
  filtered = self.filter_by(data, 'selected', True)
4358
4787
  parsed = self.parse_deposit_addresses(filtered, [currency['code']], False)
4359
4788
  return self.index_by(parsed, 'network')
4360
4789
 
4361
- async def fetch_deposit_address(self, code: str, params={}):
4790
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
4362
4791
  """
4363
4792
  fetch the deposit address for a currency associated with self account
4364
- :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-deposit-address
4793
+
4794
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-deposit-address
4795
+
4365
4796
  :param str code: unified currency code
4366
4797
  :param dict [params]: extra parameters specific to the exchange API endpoint
4798
+ :param str [params.network]: the network name for the deposit address
4367
4799
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
4368
4800
  """
4801
+ await self.load_markets()
4369
4802
  rawNetwork = self.safe_string_upper(params, 'network')
4370
- networks = self.safe_value(self.options, 'networks', {})
4371
- network = self.safe_string(networks, rawNetwork, rawNetwork)
4372
4803
  params = self.omit(params, 'network')
4804
+ code = self.safe_currency_code(code)
4805
+ network = self.network_id_to_code(rawNetwork, code)
4373
4806
  response = await self.fetch_deposit_addresses_by_network(code, params)
4374
- result = None
4375
- if network is None:
4376
- result = self.safe_value(response, code)
4807
+ if network is not None:
4808
+ result = self.safe_dict(response, network)
4377
4809
  if result is None:
4378
- alias = self.safe_string(networks, code, code)
4379
- result = self.safe_value(response, alias)
4380
- if result is None:
4381
- defaultNetwork = self.safe_string(self.options, 'defaultNetwork', 'ERC20')
4382
- result = self.safe_value(response, defaultNetwork)
4383
- if result is None:
4384
- values = list(response.values())
4385
- result = self.safe_value(values, 0)
4386
- if result is None:
4387
- raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find deposit address for ' + code)
4810
+ raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code)
4388
4811
  return result
4389
- result = self.safe_value(response, network)
4390
- if result is None:
4391
- raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code)
4392
- return result
4812
+ codeNetwork = self.network_id_to_code(code, code)
4813
+ if codeNetwork in response:
4814
+ return response[codeNetwork]
4815
+ # if the network is not specified, return the first address
4816
+ keys = list(response.keys())
4817
+ first = self.safe_string(keys, 0)
4818
+ return self.safe_dict(response, first)
4393
4819
 
4394
- async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
4820
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
4395
4821
  """
4396
4822
  make a withdrawal
4397
- :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-withdrawal
4823
+
4824
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-withdrawal
4825
+
4398
4826
  :param str code: unified currency code
4399
4827
  :param float amount: the amount to withdraw
4400
4828
  :param str address: the address to withdraw to
@@ -4408,7 +4836,7 @@ class okx(Exchange, ImplicitAPI):
4408
4836
  currency = self.currency(code)
4409
4837
  if (tag is not None) and (len(tag) > 0):
4410
4838
  address = address + ':' + tag
4411
- request = {
4839
+ request: dict = {
4412
4840
  'ccy': currency['id'],
4413
4841
  'toAddr': address,
4414
4842
  'dest': '4', # 2 = OKCoin International, 3 = OKX 4 = others
@@ -4416,7 +4844,7 @@ class okx(Exchange, ImplicitAPI):
4416
4844
  }
4417
4845
  network = self.safe_string(params, 'network') # self line allows the user to specify either ERC20 or ETH
4418
4846
  if network is not None:
4419
- networks = self.safe_value(self.options, 'networks', {})
4847
+ networks = self.safe_dict(self.options, 'networks', {})
4420
4848
  network = self.safe_string(networks, network.upper(), network) # handle ETH>ERC20 alias
4421
4849
  request['chain'] = currency['id'] + '-' + network
4422
4850
  params = self.omit(params, 'network')
@@ -4424,23 +4852,12 @@ class okx(Exchange, ImplicitAPI):
4424
4852
  if fee is None:
4425
4853
  currencies = await self.fetch_currencies()
4426
4854
  self.currencies = self.deep_extend(self.currencies, currencies)
4427
- targetNetwork = self.safe_value(currency['networks'], self.network_id_to_code(network), {})
4855
+ targetNetwork = self.safe_dict(currency['networks'], self.network_id_to_code(network), {})
4428
4856
  fee = self.safe_string(targetNetwork, 'fee')
4429
4857
  if fee is None:
4430
4858
  raise ArgumentsRequired(self.id + ' withdraw() requires a "fee" string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKX are fee-free, please set "0". Withdrawing to external digital asset address requires network transaction fee.')
4431
4859
  request['fee'] = self.number_to_string(fee) # withdrawals to OKCoin or OKX are fee-free, please set 0
4432
- if 'password' in params:
4433
- request['pwd'] = params['password']
4434
- elif 'pwd' in params:
4435
- request['pwd'] = params['pwd']
4436
- else:
4437
- options = self.safe_value(self.options, 'withdraw', {})
4438
- password = self.safe_string_2(options, 'password', 'pwd')
4439
- if password is not None:
4440
- request['pwd'] = password
4441
- query = self.omit(params, ['fee', 'password', 'pwd'])
4442
- if not ('pwd' in request):
4443
- raise ExchangeError(self.id + ' withdraw() requires a password parameter or a pwd parameter, it must be the funding password, not the API passphrase')
4860
+ query = self.omit(params, ['fee'])
4444
4861
  response = await self.privatePostAssetWithdrawal(self.extend(request, query))
4445
4862
  #
4446
4863
  # {
@@ -4455,14 +4872,16 @@ class okx(Exchange, ImplicitAPI):
4455
4872
  # ]
4456
4873
  # }
4457
4874
  #
4458
- data = self.safe_value(response, 'data', [])
4459
- transaction = self.safe_value(data, 0)
4875
+ data = self.safe_list(response, 'data', [])
4876
+ transaction = self.safe_dict(data, 0)
4460
4877
  return self.parse_transaction(transaction, currency)
4461
4878
 
4462
4879
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
4463
4880
  """
4464
4881
  fetch all deposits made to an account
4465
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-deposit-history
4882
+
4883
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-deposit-history
4884
+
4466
4885
  :param str code: unified currency code
4467
4886
  :param int [since]: the earliest time in ms to fetch deposits for
4468
4887
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -4476,7 +4895,7 @@ class okx(Exchange, ImplicitAPI):
4476
4895
  paginate, params = self.handle_option_and_params(params, 'fetchDeposits', 'paginate')
4477
4896
  if paginate:
4478
4897
  return await self.fetch_paginated_call_dynamic('fetchDeposits', code, since, limit, params)
4479
- request = {
4898
+ request: dict = {
4480
4899
  # 'ccy': currency['id'],
4481
4900
  # 'state': 2, # 0 waiting for confirmation, 1 deposit credited, 2 deposit successful
4482
4901
  # 'after': since,
@@ -4531,20 +4950,22 @@ class okx(Exchange, ImplicitAPI):
4531
4950
  # ]
4532
4951
  # }
4533
4952
  #
4534
- data = self.safe_value(response, 'data', [])
4953
+ data = self.safe_list(response, 'data', [])
4535
4954
  return self.parse_transactions(data, currency, since, limit, params)
4536
4955
 
4537
4956
  async def fetch_deposit(self, id: str, code: Str = None, params={}):
4538
4957
  """
4539
4958
  fetch data on a currency deposit via the deposit id
4540
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-deposit-history
4959
+
4960
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-deposit-history
4961
+
4541
4962
  :param str id: deposit id
4542
4963
  :param str code: filter by currency code
4543
4964
  :param dict [params]: extra parameters specific to the exchange API endpoint
4544
4965
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
4545
4966
  """
4546
4967
  await self.load_markets()
4547
- request = {
4968
+ request: dict = {
4548
4969
  'depId': id,
4549
4970
  }
4550
4971
  currency = None
@@ -4553,13 +4974,15 @@ class okx(Exchange, ImplicitAPI):
4553
4974
  request['ccy'] = currency['id']
4554
4975
  response = await self.privateGetAssetDepositHistory(self.extend(request, params))
4555
4976
  data = self.safe_value(response, 'data')
4556
- deposit = self.safe_value(data, 0, {})
4977
+ deposit = self.safe_dict(data, 0, {})
4557
4978
  return self.parse_transaction(deposit, currency)
4558
4979
 
4559
4980
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
4560
4981
  """
4561
4982
  fetch all withdrawals made from an account
4562
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-withdrawal-history
4983
+
4984
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-withdrawal-history
4985
+
4563
4986
  :param str code: unified currency code
4564
4987
  :param int [since]: the earliest time in ms to fetch withdrawals for
4565
4988
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -4573,7 +4996,7 @@ class okx(Exchange, ImplicitAPI):
4573
4996
  paginate, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'paginate')
4574
4997
  if paginate:
4575
4998
  return await self.fetch_paginated_call_dynamic('fetchWithdrawals', code, since, limit, params)
4576
- request = {
4999
+ request: dict = {
4577
5000
  # 'ccy': currency['id'],
4578
5001
  # 'state': 2, # -3: pending cancel, -2 canceled, -1 failed, 0, pending, 1 sending, 2 sent, 3 awaiting email verification, 4 awaiting manual verification, 5 awaiting identity verification
4579
5002
  # 'after': since,
@@ -4620,20 +5043,22 @@ class okx(Exchange, ImplicitAPI):
4620
5043
  # ]
4621
5044
  # }
4622
5045
  #
4623
- data = self.safe_value(response, 'data', [])
5046
+ data = self.safe_list(response, 'data', [])
4624
5047
  return self.parse_transactions(data, currency, since, limit, params)
4625
5048
 
4626
5049
  async def fetch_withdrawal(self, id: str, code: Str = None, params={}):
4627
5050
  """
4628
5051
  fetch data on a currency withdrawal via the withdrawal id
4629
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-withdrawal-history
5052
+
5053
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-withdrawal-history
5054
+
4630
5055
  :param str id: withdrawal id
4631
5056
  :param str code: unified currency code of the currency withdrawn, default is None
4632
5057
  :param dict [params]: extra parameters specific to the exchange API endpoint
4633
5058
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
4634
5059
  """
4635
5060
  await self.load_markets()
4636
- request = {
5061
+ request: dict = {
4637
5062
  'wdId': id,
4638
5063
  }
4639
5064
  currency = None
@@ -4662,11 +5087,11 @@ class okx(Exchange, ImplicitAPI):
4662
5087
  # "msg": ''
4663
5088
  # }
4664
5089
  #
4665
- data = self.safe_value(response, 'data')
4666
- withdrawal = self.safe_value(data, 0, {})
5090
+ data = self.safe_list(response, 'data', [])
5091
+ withdrawal = self.safe_dict(data, 0, {})
4667
5092
  return self.parse_transaction(withdrawal)
4668
5093
 
4669
- def parse_transaction_status(self, status):
5094
+ def parse_transaction_status(self, status: Str):
4670
5095
  #
4671
5096
  # deposit statuses
4672
5097
  #
@@ -4690,7 +5115,7 @@ class okx(Exchange, ImplicitAPI):
4690
5115
  # "5": "awaiting identity verification"
4691
5116
  # }
4692
5117
  #
4693
- statuses = {
5118
+ statuses: dict = {
4694
5119
  '-3': 'pending',
4695
5120
  '-2': 'canceled',
4696
5121
  '-1': 'failed',
@@ -4700,10 +5125,18 @@ class okx(Exchange, ImplicitAPI):
4700
5125
  '3': 'pending',
4701
5126
  '4': 'pending',
4702
5127
  '5': 'pending',
5128
+ '6': 'pending',
5129
+ '7': 'pending',
5130
+ '8': 'pending',
5131
+ '9': 'pending',
5132
+ '10': 'pending',
5133
+ '12': 'pending',
5134
+ '15': 'pending',
5135
+ '16': 'pending',
4703
5136
  }
4704
5137
  return self.safe_string(statuses, status, status)
4705
5138
 
4706
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
5139
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
4707
5140
  #
4708
5141
  # withdraw
4709
5142
  #
@@ -4799,7 +5232,9 @@ class okx(Exchange, ImplicitAPI):
4799
5232
  async def fetch_leverage(self, symbol: str, params={}) -> Leverage:
4800
5233
  """
4801
5234
  fetch the set leverage for a market
4802
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-leverage
5235
+
5236
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-leverage
5237
+
4803
5238
  :param str symbol: unified market symbol
4804
5239
  :param dict [params]: extra parameters specific to the exchange API endpoint
4805
5240
  :param str [params.marginMode]: 'cross' or 'isolated'
@@ -4813,7 +5248,7 @@ class okx(Exchange, ImplicitAPI):
4813
5248
  if (marginMode != 'cross') and (marginMode != 'isolated'):
4814
5249
  raise BadRequest(self.id + ' fetchLeverage() requires a marginMode parameter that must be either cross or isolated')
4815
5250
  market = self.market(symbol)
4816
- request = {
5251
+ request: dict = {
4817
5252
  'instId': market['id'],
4818
5253
  'mgnMode': marginMode,
4819
5254
  }
@@ -4835,7 +5270,7 @@ class okx(Exchange, ImplicitAPI):
4835
5270
  data = self.safe_list(response, 'data', [])
4836
5271
  return self.parse_leverage(data, market)
4837
5272
 
4838
- def parse_leverage(self, leverage, market=None) -> Leverage:
5273
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
4839
5274
  marketId = None
4840
5275
  marginMode = None
4841
5276
  longLeverage = None
@@ -4863,7 +5298,9 @@ class okx(Exchange, ImplicitAPI):
4863
5298
  async def fetch_position(self, symbol: str, params={}):
4864
5299
  """
4865
5300
  fetch data on a single open contract trade position
4866
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
5301
+
5302
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
5303
+
4867
5304
  :param str symbol: unified market symbol of the market the position is held in, default is None
4868
5305
  :param dict [params]: extra parameters specific to the exchange API endpoint
4869
5306
  :param str [params.instType]: MARGIN, SWAP, FUTURES, OPTION
@@ -4872,7 +5309,7 @@ class okx(Exchange, ImplicitAPI):
4872
5309
  await self.load_markets()
4873
5310
  market = self.market(symbol)
4874
5311
  type, query = self.handle_market_type_and_params('fetchPosition', market, params)
4875
- request = {
5312
+ request: dict = {
4876
5313
  # instType str No Instrument type, MARGIN, SWAP, FUTURES, OPTION
4877
5314
  'instId': market['id'],
4878
5315
  # posId str No Single position ID or multiple position IDs(no more than 20) separated with comma
@@ -4926,16 +5363,18 @@ class okx(Exchange, ImplicitAPI):
4926
5363
  # ]
4927
5364
  # }
4928
5365
  #
4929
- data = self.safe_value(response, 'data', [])
4930
- position = self.safe_value(data, 0)
5366
+ data = self.safe_list(response, 'data', [])
5367
+ position = self.safe_dict(data, 0)
4931
5368
  if position is None:
4932
5369
  return None
4933
5370
  return self.parse_position(position, market)
4934
5371
 
4935
5372
  async def fetch_positions(self, symbols: Strings = None, params={}):
4936
5373
  """
4937
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
4938
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-positions-history history
5374
+
5375
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
5376
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-positions-history history
5377
+
4939
5378
  fetch all open positions
4940
5379
  :param str[]|None symbols: list of unified market symbols
4941
5380
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4943,7 +5382,7 @@ class okx(Exchange, ImplicitAPI):
4943
5382
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
4944
5383
  """
4945
5384
  await self.load_markets()
4946
- request = {
5385
+ request: dict = {
4947
5386
  # 'instType': 'MARGIN', # optional string, MARGIN, SWAP, FUTURES, OPTION
4948
5387
  # 'instId': market['id'], # optional string, e.g. 'BTC-USD-190927-5000-C'
4949
5388
  # 'posId': '307173036051017730', # optional string, Single or multiple position IDs(no more than 20) separated with commas
@@ -4957,7 +5396,7 @@ class okx(Exchange, ImplicitAPI):
4957
5396
  marketIdsLength = len(marketIds)
4958
5397
  if marketIdsLength > 0:
4959
5398
  request['instId'] = ','.join(marketIds)
4960
- fetchPositionsOptions = self.safe_value(self.options, 'fetchPositions', {})
5399
+ fetchPositionsOptions = self.safe_dict(self.options, 'fetchPositions', {})
4961
5400
  method = self.safe_string(fetchPositionsOptions, 'method', 'privateGetAccountPositions')
4962
5401
  response = None
4963
5402
  if method == 'privateGetAccountPositionsHistory':
@@ -5010,15 +5449,17 @@ class okx(Exchange, ImplicitAPI):
5010
5449
  # ]
5011
5450
  # }
5012
5451
  #
5013
- positions = self.safe_value(response, 'data', [])
5452
+ positions = self.safe_list(response, 'data', [])
5014
5453
  result = []
5015
5454
  for i in range(0, len(positions)):
5016
5455
  result.append(self.parse_position(positions[i]))
5017
- return self.filter_by_array_positions(result, 'symbol', symbols, False)
5456
+ return self.filter_by_array_positions(result, 'symbol', self.market_symbols(symbols), False)
5018
5457
 
5019
5458
  async def fetch_positions_for_symbol(self, symbol: str, params={}):
5020
5459
  """
5021
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
5460
+
5461
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-positions
5462
+
5022
5463
  fetch all open positions for specific symbol
5023
5464
  :param str symbol: unified market symbol
5024
5465
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -5027,7 +5468,7 @@ class okx(Exchange, ImplicitAPI):
5027
5468
  """
5028
5469
  return await self.fetch_positions([symbol], params)
5029
5470
 
5030
- def parse_position(self, position, market: Market = None):
5471
+ def parse_position(self, position: dict, market: Market = None):
5031
5472
  #
5032
5473
  # {
5033
5474
  # "adl": "3",
@@ -5095,7 +5536,7 @@ class okx(Exchange, ImplicitAPI):
5095
5536
  # }
5096
5537
  #
5097
5538
  marketId = self.safe_string(position, 'instId')
5098
- market = self.safe_market(marketId, market)
5539
+ market = self.safe_market(marketId, market, None, 'contract')
5099
5540
  symbol = market['symbol']
5100
5541
  pos = self.safe_string(position, 'pos') # 'pos' field: One way mode: 0 if position is not open, 1 if open | Two way(hedge) mode: -1 if short, 1 if long, 0 if position is not open
5101
5542
  contractsAbs = Precise.string_abs(pos)
@@ -5188,7 +5629,9 @@ class okx(Exchange, ImplicitAPI):
5188
5629
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
5189
5630
  """
5190
5631
  transfer currency internally between wallets on the same account
5191
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-funds-transfer
5632
+
5633
+ https://www.okx.com/docs-v5/en/#rest-api-funding-funds-transfer
5634
+
5192
5635
  :param str code: unified currency code
5193
5636
  :param float amount: amount to transfer
5194
5637
  :param str fromAccount: account to transfer from
@@ -5198,10 +5641,10 @@ class okx(Exchange, ImplicitAPI):
5198
5641
  """
5199
5642
  await self.load_markets()
5200
5643
  currency = self.currency(code)
5201
- accountsByType = self.safe_value(self.options, 'accountsByType', {})
5644
+ accountsByType = self.safe_dict(self.options, 'accountsByType', {})
5202
5645
  fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
5203
5646
  toId = self.safe_string(accountsByType, toAccount, toAccount)
5204
- request = {
5647
+ request: dict = {
5205
5648
  'ccy': currency['id'],
5206
5649
  'amt': self.currency_to_precision(code, amount),
5207
5650
  'type': '0', # 0 = transfer within account by default, 1 = master account to sub-account, 2 = sub-account to master account, 3 = sub-account to master account(Only applicable to APIKey from sub-account), 4 = sub-account to sub-account
@@ -5238,11 +5681,11 @@ class okx(Exchange, ImplicitAPI):
5238
5681
  # ]
5239
5682
  # }
5240
5683
  #
5241
- data = self.safe_value(response, 'data', [])
5242
- rawTransfer = self.safe_value(data, 0, {})
5684
+ data = self.safe_list(response, 'data', [])
5685
+ rawTransfer = self.safe_dict(data, 0, {})
5243
5686
  return self.parse_transfer(rawTransfer, currency)
5244
5687
 
5245
- def parse_transfer(self, transfer, currency: Currency = None):
5688
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
5246
5689
  #
5247
5690
  # transfer
5248
5691
  #
@@ -5301,7 +5744,7 @@ class okx(Exchange, ImplicitAPI):
5301
5744
  amount = self.safe_number(transfer, 'amt')
5302
5745
  fromAccountId = self.safe_string(transfer, 'from')
5303
5746
  toAccountId = self.safe_string(transfer, 'to')
5304
- accountsById = self.safe_value(self.options, 'accountsById', {})
5747
+ accountsById = self.safe_dict(self.options, 'accountsById', {})
5305
5748
  timestamp = self.safe_integer(transfer, 'ts')
5306
5749
  balanceChange = self.safe_string(transfer, 'sz')
5307
5750
  if balanceChange is not None:
@@ -5318,15 +5761,15 @@ class okx(Exchange, ImplicitAPI):
5318
5761
  'status': self.parse_transfer_status(self.safe_string(transfer, 'state')),
5319
5762
  }
5320
5763
 
5321
- def parse_transfer_status(self, status):
5322
- statuses = {
5764
+ def parse_transfer_status(self, status: Str) -> Str:
5765
+ statuses: dict = {
5323
5766
  'success': 'ok',
5324
5767
  }
5325
5768
  return self.safe_string(statuses, status, status)
5326
5769
 
5327
- async def fetch_transfer(self, id: str, code: Str = None, params={}):
5770
+ async def fetch_transfer(self, id: str, code: Str = None, params={}) -> TransferEntry:
5328
5771
  await self.load_markets()
5329
- request = {
5772
+ request: dict = {
5330
5773
  'transId': id,
5331
5774
  # 'type': 0, # default is 0 transfer within account, 1 master to sub, 2 sub to master
5332
5775
  }
@@ -5351,14 +5794,16 @@ class okx(Exchange, ImplicitAPI):
5351
5794
  # "msg": ""
5352
5795
  # }
5353
5796
  #
5354
- data = self.safe_value(response, 'data', [])
5355
- transfer = self.safe_value(data, 0)
5797
+ data = self.safe_list(response, 'data', [])
5798
+ transfer = self.safe_dict(data, 0)
5356
5799
  return self.parse_transfer(transfer)
5357
5800
 
5358
- async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
5801
+ async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
5359
5802
  """
5360
5803
  fetch a history of internal transfers made on an account
5361
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
5804
+
5805
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
5806
+
5362
5807
  :param str code: unified currency code of the currency transferred
5363
5808
  :param int [since]: the earliest time in ms to fetch transfers for
5364
5809
  :param int [limit]: the maximum number of transfers structures to retrieve
@@ -5367,7 +5812,7 @@ class okx(Exchange, ImplicitAPI):
5367
5812
  """
5368
5813
  await self.load_markets()
5369
5814
  currency = None
5370
- request = {
5815
+ request: dict = {
5371
5816
  'type': '1', # https://www.okx.com/docs-v5/en/#rest-api-account-get-bills-details-last-3-months
5372
5817
  }
5373
5818
  if code is not None:
@@ -5410,7 +5855,7 @@ class okx(Exchange, ImplicitAPI):
5410
5855
  # "msg": ""
5411
5856
  # }
5412
5857
  #
5413
- transfers = self.safe_value(response, 'data', [])
5858
+ transfers = self.safe_list(response, 'data', [])
5414
5859
  return self.parse_transfers(transfers, currency, since, limit, params)
5415
5860
 
5416
5861
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
@@ -5440,7 +5885,7 @@ class okx(Exchange, ImplicitAPI):
5440
5885
  if clientOrderId is None:
5441
5886
  params['clOrdId'] = brokerId + self.uuid16()
5442
5887
  params['tag'] = brokerId
5443
- timestamp = self.iso8601(self.milliseconds())
5888
+ timestamp = self.iso8601(self.nonce())
5444
5889
  headers = {
5445
5890
  'OK-ACCESS-KEY': self.apiKey,
5446
5891
  'OK-ACCESS-PASSPHRASE': self.password,
@@ -5464,7 +5909,7 @@ class okx(Exchange, ImplicitAPI):
5464
5909
  headers['OK-ACCESS-SIGN'] = signature
5465
5910
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
5466
5911
 
5467
- def parse_funding_rate(self, contract, market: Market = None):
5912
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
5468
5913
  #
5469
5914
  # {
5470
5915
  # "fundingRate": "0.00027815",
@@ -5474,6 +5919,22 @@ class okx(Exchange, ImplicitAPI):
5474
5919
  # "nextFundingRate": "0.00017",
5475
5920
  # "nextFundingTime": "1634284800000"
5476
5921
  # }
5922
+ # ws
5923
+ # {
5924
+ # "fundingRate":"0.0001875391284828",
5925
+ # "fundingTime":"1700726400000",
5926
+ # "instId":"BTC-USD-SWAP",
5927
+ # "instType":"SWAP",
5928
+ # "method": "next_period",
5929
+ # "maxFundingRate":"0.00375",
5930
+ # "minFundingRate":"-0.00375",
5931
+ # "nextFundingRate":"0.0002608059239328",
5932
+ # "nextFundingTime":"1700755200000",
5933
+ # "premium": "0.0001233824646391",
5934
+ # "settFundingRate":"0.0001699799259033",
5935
+ # "settState":"settled",
5936
+ # "ts":"1700724675402"
5937
+ # }
5477
5938
  #
5478
5939
  # in the response above nextFundingRate is actually two funding rates from now
5479
5940
  #
@@ -5482,6 +5943,9 @@ class okx(Exchange, ImplicitAPI):
5482
5943
  symbol = self.safe_symbol(marketId, market)
5483
5944
  nextFundingRate = self.safe_number(contract, 'nextFundingRate')
5484
5945
  fundingTime = self.safe_integer(contract, 'fundingTime')
5946
+ fundingTimeString = self.safe_string(contract, 'fundingTime')
5947
+ nextFundingTimeString = self.safe_string(contract, 'nextFundingRate')
5948
+ millisecondsInterval = Precise.string_sub(nextFundingTimeString, fundingTimeString)
5485
5949
  # https://www.okx.com/support/hc/en-us/articles/360053909272-Ⅸ-Introduction-to-perpetual-swap-funding-fee
5486
5950
  # > The current interest is 0.
5487
5951
  return {
@@ -5502,12 +5966,37 @@ class okx(Exchange, ImplicitAPI):
5502
5966
  'previousFundingRate': None,
5503
5967
  'previousFundingTimestamp': None,
5504
5968
  'previousFundingDatetime': None,
5969
+ 'interval': self.parse_funding_interval(millisecondsInterval),
5505
5970
  }
5506
5971
 
5507
- async def fetch_funding_rate(self, symbol: str, params={}):
5972
+ def parse_funding_interval(self, interval):
5973
+ intervals: dict = {
5974
+ '3600000': '1h',
5975
+ '14400000': '4h',
5976
+ '28800000': '8h',
5977
+ '57600000': '16h',
5978
+ '86400000': '24h',
5979
+ }
5980
+ return self.safe_string(intervals, interval, interval)
5981
+
5982
+ async def fetch_funding_interval(self, symbol: str, params={}) -> FundingRate:
5983
+ """
5984
+ fetch the current funding rate interval
5985
+
5986
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-funding-rate
5987
+
5988
+ :param str symbol: unified market symbol
5989
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5990
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
5991
+ """
5992
+ return await self.fetch_funding_rate(symbol, params)
5993
+
5994
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
5508
5995
  """
5509
5996
  fetch the current funding rate
5510
- :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-funding-rate
5997
+
5998
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-funding-rate
5999
+
5511
6000
  :param str symbol: unified market symbol
5512
6001
  :param dict [params]: extra parameters specific to the exchange API endpoint
5513
6002
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
@@ -5516,7 +6005,7 @@ class okx(Exchange, ImplicitAPI):
5516
6005
  market = self.market(symbol)
5517
6006
  if not market['swap']:
5518
6007
  raise ExchangeError(self.id + ' fetchFundingRate() is only valid for swap markets')
5519
- request = {
6008
+ request: dict = {
5520
6009
  'instId': market['id'],
5521
6010
  }
5522
6011
  response = await self.publicGetPublicFundingRate(self.extend(request, params))
@@ -5536,14 +6025,16 @@ class okx(Exchange, ImplicitAPI):
5536
6025
  # "msg": ""
5537
6026
  # }
5538
6027
  #
5539
- data = self.safe_value(response, 'data', [])
5540
- entry = self.safe_value(data, 0, {})
6028
+ data = self.safe_list(response, 'data', [])
6029
+ entry = self.safe_dict(data, 0, {})
5541
6030
  return self.parse_funding_rate(entry, market)
5542
6031
 
5543
6032
  async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5544
6033
  """
5545
6034
  fetch the history of funding payments paid and received on self account
5546
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
6035
+
6036
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
6037
+
5547
6038
  :param str symbol: unified market symbol
5548
6039
  :param int [since]: the earliest time in ms to fetch funding history for
5549
6040
  :param int [limit]: the maximum number of funding history structures to retrieve
@@ -5551,7 +6042,7 @@ class okx(Exchange, ImplicitAPI):
5551
6042
  :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
5552
6043
  """
5553
6044
  await self.load_markets()
5554
- request = {
6045
+ request: dict = {
5555
6046
  # 'instType': 'SPOT', # SPOT, MARGIN, SWAP, FUTURES, OPTION
5556
6047
  # 'ccy': currency['id'],
5557
6048
  # 'mgnMode': 'isolated', # isolated, cross
@@ -5669,7 +6160,7 @@ class okx(Exchange, ImplicitAPI):
5669
6160
  # "type": "8"
5670
6161
  # }
5671
6162
  #
5672
- data = self.safe_value(response, 'data', [])
6163
+ data = self.safe_list(response, 'data', [])
5673
6164
  result = []
5674
6165
  for i in range(0, len(data)):
5675
6166
  entry = data[i]
@@ -5693,12 +6184,14 @@ class okx(Exchange, ImplicitAPI):
5693
6184
  async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
5694
6185
  """
5695
6186
  set the level of leverage for a market
5696
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-set-leverage
6187
+
6188
+ https://www.okx.com/docs-v5/en/#rest-api-account-set-leverage
6189
+
5697
6190
  :param float leverage: the rate of leverage
5698
6191
  :param str symbol: unified market symbol
5699
6192
  :param dict [params]: extra parameters specific to the exchange API endpoint
5700
6193
  :param str [params.marginMode]: 'cross' or 'isolated'
5701
- :param str [params.posSide]: 'long' or 'short' for isolated margin long/short mode on futures and swap markets
6194
+ :param str [params.posSide]: 'long' or 'short' or 'net' for isolated margin long/short mode on futures and swap markets, default is 'net'
5702
6195
  :returns dict: response from the exchange
5703
6196
  """
5704
6197
  if symbol is None:
@@ -5715,17 +6208,16 @@ class okx(Exchange, ImplicitAPI):
5715
6208
  marginMode = self.safe_string(params, 'mgnMode', 'cross') # cross marginMode
5716
6209
  if (marginMode != 'cross') and (marginMode != 'isolated'):
5717
6210
  raise BadRequest(self.id + ' setLeverage() requires a marginMode parameter that must be either cross or isolated')
5718
- request = {
6211
+ request: dict = {
5719
6212
  'lever': leverage,
5720
6213
  'mgnMode': marginMode,
5721
6214
  'instId': market['id'],
5722
6215
  }
5723
- posSide = self.safe_string(params, 'posSide')
6216
+ posSide = self.safe_string(params, 'posSide', 'net')
5724
6217
  if marginMode == 'isolated':
5725
- if posSide is None:
5726
- raise ArgumentsRequired(self.id + ' setLeverage() requires a posSide argument for isolated margin')
5727
6218
  if posSide != 'long' and posSide != 'short' and posSide != 'net':
5728
6219
  raise BadRequest(self.id + ' setLeverage() requires the posSide argument to be either "long", "short" or "net"')
6220
+ request['posSide'] = posSide
5729
6221
  response = await self.privatePostAccountSetLeverage(self.extend(request, params))
5730
6222
  #
5731
6223
  # {
@@ -5743,10 +6235,44 @@ class okx(Exchange, ImplicitAPI):
5743
6235
  #
5744
6236
  return response
5745
6237
 
6238
+ async def fetch_position_mode(self, symbol: Str = None, params={}):
6239
+ """
6240
+
6241
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-account-configuration
6242
+
6243
+ fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
6244
+ :param str symbol: unified symbol of the market to fetch the order book for
6245
+ :param dict [params]: extra parameters specific to the exchange API endpoint
6246
+ :param str [params.accountId]: if you have multiple accounts, you must specify the account id to fetch the position mode
6247
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
6248
+ """
6249
+ accounts = await self.fetch_accounts()
6250
+ length = len(accounts)
6251
+ selectedAccount = None
6252
+ if length > 1:
6253
+ accountId = self.safe_string(params, 'accountId')
6254
+ if accountId is None:
6255
+ accountIds = self.get_list_from_object_values(accounts, 'id')
6256
+ raise ExchangeError(self.id + ' fetchPositionMode() can not detect position mode, because you have multiple accounts. Set params["accountId"] to desired id from: ' + ', '.join(accountIds))
6257
+ else:
6258
+ accountsById = self.index_by(accounts, 'id')
6259
+ selectedAccount = self.safe_dict(accountsById, accountId)
6260
+ else:
6261
+ selectedAccount = accounts[0]
6262
+ mainAccount = selectedAccount['info']
6263
+ posMode = self.safe_string(mainAccount, 'posMode') # long_short_mode, net_mode
6264
+ isHedged = posMode == 'long_short_mode'
6265
+ return {
6266
+ 'info': mainAccount,
6267
+ 'hedged': isHedged,
6268
+ }
6269
+
5746
6270
  async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
5747
6271
  """
5748
6272
  set hedged to True or False for a market
5749
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-set-position-mode
6273
+
6274
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-set-position-mode
6275
+
5750
6276
  :param bool hedged: set to True to use long_short_mode, False for net_mode
5751
6277
  :param str symbol: not used by okx setPositionMode
5752
6278
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -5757,7 +6283,7 @@ class okx(Exchange, ImplicitAPI):
5757
6283
  hedgeMode = 'long_short_mode'
5758
6284
  else:
5759
6285
  hedgeMode = 'net_mode'
5760
- request = {
6286
+ request: dict = {
5761
6287
  'posMode': hedgeMode,
5762
6288
  }
5763
6289
  response = await self.privatePostAccountSetPositionMode(self.extend(request, params))
@@ -5777,7 +6303,9 @@ class okx(Exchange, ImplicitAPI):
5777
6303
  async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
5778
6304
  """
5779
6305
  set margin mode to 'cross' or 'isolated'
5780
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-set-leverage
6306
+
6307
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-set-leverage
6308
+
5781
6309
  :param str marginMode: 'cross' or 'isolated'
5782
6310
  :param str symbol: unified market symbol
5783
6311
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -5797,7 +6325,7 @@ class okx(Exchange, ImplicitAPI):
5797
6325
  if (lever is None) or (lever < 1) or (lever > 125):
5798
6326
  raise BadRequest(self.id + ' setMarginMode() params["lever"] should be between 1 and 125')
5799
6327
  params = self.omit(params, ['leverage'])
5800
- request = {
6328
+ request: dict = {
5801
6329
  'lever': lever,
5802
6330
  'mgnMode': marginMode,
5803
6331
  'instId': market['id'],
@@ -5819,10 +6347,12 @@ class okx(Exchange, ImplicitAPI):
5819
6347
  #
5820
6348
  return response
5821
6349
 
5822
- async def fetch_cross_borrow_rates(self, params={}):
6350
+ async def fetch_cross_borrow_rates(self, params={}) -> CrossBorrowRates:
5823
6351
  """
5824
6352
  fetch the borrow interest rates of all currencies
5825
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-interest-rate
6353
+
6354
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-interest-rate
6355
+
5826
6356
  :param dict [params]: extra parameters specific to the exchange API endpoint
5827
6357
  :returns dict: a list of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
5828
6358
  """
@@ -5840,23 +6370,25 @@ class okx(Exchange, ImplicitAPI):
5840
6370
  # ],
5841
6371
  # }
5842
6372
  #
5843
- data = self.safe_value(response, 'data', [])
6373
+ data = self.safe_list(response, 'data', [])
5844
6374
  rates = []
5845
6375
  for i in range(0, len(data)):
5846
6376
  rates.append(self.parse_borrow_rate(data[i]))
5847
6377
  return rates
5848
6378
 
5849
- async def fetch_cross_borrow_rate(self, code: str, params={}):
6379
+ async def fetch_cross_borrow_rate(self, code: str, params={}) -> CrossBorrowRate:
5850
6380
  """
5851
6381
  fetch the rate of interest to borrow a currency for margin trading
5852
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-interest-rate
6382
+
6383
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-interest-rate
6384
+
5853
6385
  :param str code: unified currency code
5854
6386
  :param dict [params]: extra parameters specific to the exchange API endpoint
5855
6387
  :returns dict: a `borrow rate structure <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
5856
6388
  """
5857
6389
  await self.load_markets()
5858
6390
  currency = self.currency(code)
5859
- request = {
6391
+ request: dict = {
5860
6392
  'ccy': currency['id'],
5861
6393
  }
5862
6394
  response = await self.privateGetAccountInterestRate(self.extend(request, params))
@@ -5873,8 +6405,8 @@ class okx(Exchange, ImplicitAPI):
5873
6405
  # "msg": ""
5874
6406
  # }
5875
6407
  #
5876
- data = self.safe_value(response, 'data')
5877
- rate = self.safe_value(data, 0)
6408
+ data = self.safe_list(response, 'data', [])
6409
+ rate = self.safe_dict(data, 0, {})
5878
6410
  return self.parse_borrow_rate(rate)
5879
6411
 
5880
6412
  def parse_borrow_rate(self, info, currency: Currency = None):
@@ -5909,7 +6441,7 @@ class okx(Exchange, ImplicitAPI):
5909
6441
  # ...
5910
6442
  # ]
5911
6443
  #
5912
- borrowRateHistories = {}
6444
+ borrowRateHistories: dict = {}
5913
6445
  for i in range(0, len(response)):
5914
6446
  item = response[i]
5915
6447
  code = self.safe_currency_code(self.safe_string(item, 'ccy'))
@@ -5924,19 +6456,12 @@ class okx(Exchange, ImplicitAPI):
5924
6456
  borrowRateHistories[code] = self.filter_by_currency_since_limit(borrowRateHistories[code], code, since, limit)
5925
6457
  return borrowRateHistories
5926
6458
 
5927
- def parse_borrow_rate_history(self, response, code, since, limit):
5928
- result = []
5929
- for i in range(0, len(response)):
5930
- item = response[i]
5931
- borrowRate = self.parse_borrow_rate(item)
5932
- result.append(borrowRate)
5933
- sorted = self.sort_by(result, 'timestamp')
5934
- return self.filter_by_currency_since_limit(sorted, code, since, limit)
5935
-
5936
6459
  async def fetch_borrow_rate_histories(self, codes=None, since: Int = None, limit: Int = None, params={}):
5937
6460
  """
5938
6461
  retrieves a history of a multiple currencies borrow interest rate at specific time slots, returns all currencies if no symbols passed, default is None
5939
- :see: https://www.okx.com/docs-v5/en/#financial-product-savings-get-public-borrow-history-public
6462
+
6463
+ https://www.okx.com/docs-v5/en/#financial-product-savings-get-public-borrow-history-public
6464
+
5940
6465
  :param str[]|None codes: list of unified currency codes, default is None
5941
6466
  :param int [since]: timestamp in ms of the earliest borrowRate, default is None
5942
6467
  :param int [limit]: max number of borrow rate prices to return, default is None
@@ -5944,7 +6469,7 @@ class okx(Exchange, ImplicitAPI):
5944
6469
  :returns dict: a dictionary of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` indexed by the market symbol
5945
6470
  """
5946
6471
  await self.load_markets()
5947
- request = {
6472
+ request: dict = {
5948
6473
  # 'ccy': currency['id'],
5949
6474
  # 'after': self.milliseconds(), # Pagination of data to return records earlier than the requested ts,
5950
6475
  # 'before': since, # Pagination of data to return records newer than the requested ts,
@@ -5969,13 +6494,15 @@ class okx(Exchange, ImplicitAPI):
5969
6494
  # "msg": ""
5970
6495
  # }
5971
6496
  #
5972
- data = self.safe_value(response, 'data')
6497
+ data = self.safe_list(response, 'data', [])
5973
6498
  return self.parse_borrow_rate_histories(data, codes, since, limit)
5974
6499
 
5975
6500
  async def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
5976
6501
  """
5977
6502
  retrieves a history of a currencies borrow interest rate at specific time slots
5978
- :see: https://www.okx.com/docs-v5/en/#financial-product-savings-get-public-borrow-history-public
6503
+
6504
+ https://www.okx.com/docs-v5/en/#financial-product-savings-get-public-borrow-history-public
6505
+
5979
6506
  :param str code: unified currency code
5980
6507
  :param int [since]: timestamp for the earliest borrow rate
5981
6508
  :param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
@@ -5984,7 +6511,7 @@ class okx(Exchange, ImplicitAPI):
5984
6511
  """
5985
6512
  await self.load_markets()
5986
6513
  currency = self.currency(code)
5987
- request = {
6514
+ request: dict = {
5988
6515
  'ccy': currency['id'],
5989
6516
  # 'after': self.milliseconds(), # Pagination of data to return records earlier than the requested ts,
5990
6517
  # 'before': since, # Pagination of data to return records newer than the requested ts,
@@ -6009,15 +6536,15 @@ class okx(Exchange, ImplicitAPI):
6009
6536
  # "msg": ""
6010
6537
  # }
6011
6538
  #
6012
- data = self.safe_value(response, 'data')
6539
+ data = self.safe_list(response, 'data', [])
6013
6540
  return self.parse_borrow_rate_history(data, code, since, limit)
6014
6541
 
6015
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
6542
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
6016
6543
  await self.load_markets()
6017
6544
  market = self.market(symbol)
6018
6545
  posSide = self.safe_string(params, 'posSide', 'net')
6019
6546
  params = self.omit(params, ['posSide'])
6020
- request = {
6547
+ request: dict = {
6021
6548
  'instId': market['id'],
6022
6549
  'amt': amount,
6023
6550
  'type': type,
@@ -6038,32 +6565,92 @@ class okx(Exchange, ImplicitAPI):
6038
6565
  # "msg": ""
6039
6566
  # }
6040
6567
  #
6041
- return self.parse_margin_modification(response, market)
6042
-
6043
- def parse_margin_modification(self, data, market: Market = None):
6044
- innerData = self.safe_value(data, 'data', [])
6045
- entry = self.safe_value(innerData, 0, {})
6046
- errorCode = self.safe_string(data, 'code')
6047
- status = 'ok' if (errorCode == '0') else 'failed'
6048
- amountRaw = self.safe_number(entry, 'amt')
6049
- typeRaw = self.safe_string(entry, 'type')
6050
- type = 'reduce' if (typeRaw == 'reduce') else 'add'
6051
- marketId = self.safe_string(entry, 'instId')
6568
+ data = self.safe_list(response, 'data', [])
6569
+ entry = self.safe_dict(data, 0, {})
6570
+ errorCode = self.safe_string(response, 'code')
6571
+ return self.extend(self.parse_margin_modification(entry, market), {
6572
+ 'status': 'ok' if (errorCode == '0') else 'failed',
6573
+ })
6574
+
6575
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
6576
+ #
6577
+ # addMargin/reduceMargin
6578
+ #
6579
+ # {
6580
+ # "amt": "0.01",
6581
+ # "instId": "ETH-USD-SWAP",
6582
+ # "posSide": "net",
6583
+ # "type": "reduce"
6584
+ # }
6585
+ #
6586
+ # fetchMarginAdjustmentHistory
6587
+ #
6588
+ # {
6589
+ # bal: '67621.4325135010619812',
6590
+ # balChg: '-10.0000000000000000',
6591
+ # billId: '691293628710342659',
6592
+ # ccy: 'USDT',
6593
+ # clOrdId: '',
6594
+ # execType: '',
6595
+ # fee: '0',
6596
+ # fillFwdPx: '',
6597
+ # fillIdxPx: '',
6598
+ # fillMarkPx: '',
6599
+ # fillMarkVol: '',
6600
+ # fillPxUsd: '',
6601
+ # fillPxVol: '',
6602
+ # fillTime: '1711089244850',
6603
+ # from: '',
6604
+ # instId: 'XRP-USDT-SWAP',
6605
+ # instType: 'SWAP',
6606
+ # interest: '0',
6607
+ # mgnMode: 'isolated',
6608
+ # notes: '',
6609
+ # ordId: '',
6610
+ # pnl: '0',
6611
+ # posBal: '73.12',
6612
+ # posBalChg: '10.00',
6613
+ # px: '',
6614
+ # subType: '160',
6615
+ # sz: '10',
6616
+ # tag: '',
6617
+ # to: '',
6618
+ # tradeId: '0',
6619
+ # ts: '1711089244699',
6620
+ # type: '6'
6621
+ # }
6622
+ #
6623
+ amountRaw = self.safe_string_2(data, 'amt', 'posBalChg')
6624
+ typeRaw = self.safe_string(data, 'type')
6625
+ type = None
6626
+ if typeRaw == '6':
6627
+ type = 'add' if Precise.string_gt(amountRaw, '0') else 'reduce'
6628
+ else:
6629
+ type = typeRaw
6630
+ amount = Precise.string_abs(amountRaw)
6631
+ marketId = self.safe_string(data, 'instId')
6052
6632
  responseMarket = self.safe_market(marketId, market)
6053
6633
  code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
6634
+ timestamp = self.safe_integer(data, 'ts')
6054
6635
  return {
6055
6636
  'info': data,
6637
+ 'symbol': responseMarket['symbol'],
6056
6638
  'type': type,
6057
- 'amount': amountRaw,
6639
+ 'marginMode': 'isolated',
6640
+ 'amount': self.parse_number(amount),
6058
6641
  'code': code,
6059
- 'symbol': responseMarket['symbol'],
6060
- 'status': status,
6642
+ 'total': None,
6643
+ 'status': None,
6644
+ 'timestamp': timestamp,
6645
+ 'datetime': self.iso8601(timestamp),
6061
6646
  }
6062
6647
 
6063
- async def reduce_margin(self, symbol: str, amount, params={}):
6648
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
6064
6649
  """
6065
6650
  remove margin from a position
6066
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
6651
+
6652
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
6653
+
6067
6654
  :param str symbol: unified market symbol
6068
6655
  :param float amount: the amount of margin to remove
6069
6656
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -6071,10 +6658,12 @@ class okx(Exchange, ImplicitAPI):
6071
6658
  """
6072
6659
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
6073
6660
 
6074
- async def add_margin(self, symbol: str, amount, params={}):
6661
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
6075
6662
  """
6076
6663
  add margin
6077
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
6664
+
6665
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
6666
+
6078
6667
  :param str symbol: unified market symbol
6079
6668
  :param float amount: amount of margin to add
6080
6669
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -6082,10 +6671,12 @@ class okx(Exchange, ImplicitAPI):
6082
6671
  """
6083
6672
  return await self.modify_margin_helper(symbol, amount, 'add', params)
6084
6673
 
6085
- async def fetch_market_leverage_tiers(self, symbol: str, params={}):
6674
+ async def fetch_market_leverage_tiers(self, symbol: str, params={}) -> List[LeverageTier]:
6086
6675
  """
6087
6676
  retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes for a single market
6088
- :see: https://www.okx.com/docs-v5/en/#rest-api-public-data-get-position-tiers
6677
+
6678
+ https://www.okx.com/docs-v5/en/#rest-api-public-data-get-position-tiers
6679
+
6089
6680
  :param str symbol: unified market symbol
6090
6681
  :param dict [params]: extra parameters specific to the exchange API endpoint
6091
6682
  :param str [params.marginMode]: 'cross' or 'isolated'
@@ -6102,7 +6693,7 @@ class okx(Exchange, ImplicitAPI):
6102
6693
  marginMode, params = self.handle_margin_mode_and_params('fetchMarketLeverageTiers', params)
6103
6694
  if marginMode is None:
6104
6695
  marginMode = self.safe_string(params, 'tdMode', 'cross') # cross marginMode
6105
- request = {
6696
+ request: dict = {
6106
6697
  'instType': type,
6107
6698
  'tdMode': marginMode,
6108
6699
  'uly': uly,
@@ -6131,12 +6722,12 @@ class okx(Exchange, ImplicitAPI):
6131
6722
  # ]
6132
6723
  # }
6133
6724
  #
6134
- data = self.safe_value(response, 'data')
6725
+ data = self.safe_list(response, 'data', [])
6135
6726
  return self.parse_market_leverage_tiers(data, market)
6136
6727
 
6137
- def parse_market_leverage_tiers(self, info, market: Market = None):
6728
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
6138
6729
  """
6139
- * @ignore
6730
+ @ignore
6140
6731
  :param dict info: Exchange response for 1 market
6141
6732
  :param dict market: CCXT market
6142
6733
  """
@@ -6161,8 +6752,10 @@ class okx(Exchange, ImplicitAPI):
6161
6752
  tiers = []
6162
6753
  for i in range(0, len(info)):
6163
6754
  tier = info[i]
6755
+ marketId = self.safe_string(tier, 'instId')
6164
6756
  tiers.append({
6165
6757
  'tier': self.safe_integer(tier, 'tier'),
6758
+ 'symbol': self.safe_symbol(marketId, market),
6166
6759
  'currency': market['quote'],
6167
6760
  'minNotional': self.safe_number(tier, 'minSz'),
6168
6761
  'maxNotional': self.safe_number(tier, 'maxSz'),
@@ -6172,10 +6765,12 @@ class okx(Exchange, ImplicitAPI):
6172
6765
  })
6173
6766
  return tiers
6174
6767
 
6175
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
6768
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6176
6769
  """
6177
6770
  fetch the interest owed by the user for borrowing currency for margin trading
6178
- :see: https://www.okx.com/docs-v5/en/#rest-api-account-get-interest-accrued-data
6771
+
6772
+ https://www.okx.com/docs-v5/en/#rest-api-account-get-interest-accrued-data
6773
+
6179
6774
  :param str code: the unified currency code for the currency of the interest
6180
6775
  :param str symbol: the market symbol of an isolated margin market, if None, the interest for cross margin markets is returned
6181
6776
  :param int [since]: timestamp in ms of the earliest time to receive interest records for
@@ -6190,7 +6785,7 @@ class okx(Exchange, ImplicitAPI):
6190
6785
  marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params)
6191
6786
  if marginMode is None:
6192
6787
  marginMode = self.safe_string(params, 'mgnMode', 'cross') # cross marginMode
6193
- request = {
6788
+ request: dict = {
6194
6789
  'mgnMode': marginMode,
6195
6790
  }
6196
6791
  market = None
@@ -6224,31 +6819,33 @@ class okx(Exchange, ImplicitAPI):
6224
6819
  # "msg": ""
6225
6820
  # }
6226
6821
  #
6227
- data = self.safe_value(response, 'data')
6822
+ data = self.safe_list(response, 'data', [])
6228
6823
  interest = self.parse_borrow_interests(data)
6229
6824
  return self.filter_by_currency_since_limit(interest, code, since, limit)
6230
6825
 
6231
- def parse_borrow_interest(self, info, market: Market = None):
6826
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
6232
6827
  instId = self.safe_string(info, 'instId')
6233
6828
  if instId is not None:
6234
6829
  market = self.safe_market(instId, market)
6235
6830
  timestamp = self.safe_integer(info, 'ts')
6236
6831
  return {
6832
+ 'info': info,
6237
6833
  'symbol': self.safe_string(market, 'symbol'),
6238
- 'marginMode': self.safe_string(info, 'mgnMode'),
6239
6834
  'currency': self.safe_currency_code(self.safe_string(info, 'ccy')),
6240
6835
  'interest': self.safe_number(info, 'interest'),
6241
6836
  'interestRate': self.safe_number(info, 'interestRate'),
6242
6837
  'amountBorrowed': self.safe_number(info, 'liab'),
6838
+ 'marginMode': self.safe_string(info, 'mgnMode'),
6243
6839
  'timestamp': timestamp, # Interest accrued time
6244
6840
  'datetime': self.iso8601(timestamp),
6245
- 'info': info,
6246
6841
  }
6247
6842
 
6248
6843
  async def borrow_cross_margin(self, code: str, amount: float, params={}):
6249
6844
  """
6250
6845
  create a loan to borrow margin(need to be VIP 5 and above)
6251
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-vip-loans-borrow-and-repay
6846
+
6847
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-vip-loans-borrow-and-repay
6848
+
6252
6849
  :param str code: unified currency code of the currency to borrow
6253
6850
  :param float amount: the amount to borrow
6254
6851
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -6256,7 +6853,7 @@ class okx(Exchange, ImplicitAPI):
6256
6853
  """
6257
6854
  await self.load_markets()
6258
6855
  currency = self.currency(code)
6259
- request = {
6856
+ request: dict = {
6260
6857
  'ccy': currency['id'],
6261
6858
  'amt': self.currency_to_precision(code, amount),
6262
6859
  'side': 'borrow',
@@ -6277,14 +6874,16 @@ class okx(Exchange, ImplicitAPI):
6277
6874
  # "msg": ""
6278
6875
  # }
6279
6876
  #
6280
- data = self.safe_value(response, 'data', [])
6281
- loan = self.safe_value(data, 0)
6877
+ data = self.safe_list(response, 'data', [])
6878
+ loan = self.safe_dict(data, 0, {})
6282
6879
  return self.parse_margin_loan(loan, currency)
6283
6880
 
6284
6881
  async def repay_cross_margin(self, code: str, amount, params={}):
6285
6882
  """
6286
6883
  repay borrowed margin and interest
6287
- :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-vip-loans-borrow-and-repay
6884
+
6885
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-vip-loans-borrow-and-repay
6886
+
6288
6887
  :param str code: unified currency code of the currency to repay
6289
6888
  :param float amount: the amount to repay
6290
6889
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -6297,7 +6896,7 @@ class okx(Exchange, ImplicitAPI):
6297
6896
  if id is None:
6298
6897
  raise ArgumentsRequired(self.id + ' repayCrossMargin() requires an id parameter')
6299
6898
  currency = self.currency(code)
6300
- request = {
6899
+ request: dict = {
6301
6900
  'ccy': currency['id'],
6302
6901
  'amt': self.currency_to_precision(code, amount),
6303
6902
  'side': 'repay',
@@ -6319,8 +6918,8 @@ class okx(Exchange, ImplicitAPI):
6319
6918
  # "msg": ""
6320
6919
  # }
6321
6920
  #
6322
- data = self.safe_value(response, 'data', [])
6323
- loan = self.safe_value(data, 0)
6921
+ data = self.safe_list(response, 'data', [])
6922
+ loan = self.safe_dict(data, 0, {})
6324
6923
  return self.parse_margin_loan(loan, currency)
6325
6924
 
6326
6925
  def parse_margin_loan(self, info, currency: Currency = None):
@@ -6349,7 +6948,9 @@ class okx(Exchange, ImplicitAPI):
6349
6948
  async def fetch_open_interest(self, symbol: str, params={}):
6350
6949
  """
6351
6950
  Retrieves the open interest of a currency
6352
- :see: https://www.okx.com/docs-v5/en/#rest-api-public-data-get-open-interest
6951
+
6952
+ https://www.okx.com/docs-v5/en/#rest-api-public-data-get-open-interest
6953
+
6353
6954
  :param str symbol: Unified CCXT market symbol
6354
6955
  :param dict [params]: exchange specific parameters
6355
6956
  :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
@@ -6360,7 +6961,7 @@ class okx(Exchange, ImplicitAPI):
6360
6961
  raise BadRequest(self.id + ' fetchOpenInterest() supports contract markets only')
6361
6962
  type = self.convert_to_instrument_type(market['type'])
6362
6963
  uly = self.safe_string(market['info'], 'uly')
6363
- request = {
6964
+ request: dict = {
6364
6965
  'instType': type,
6365
6966
  'uly': uly,
6366
6967
  'instId': market['id'],
@@ -6381,14 +6982,16 @@ class okx(Exchange, ImplicitAPI):
6381
6982
  # "msg": ""
6382
6983
  # }
6383
6984
  #
6384
- data = self.safe_value(response, 'data', [])
6985
+ data = self.safe_list(response, 'data', [])
6385
6986
  return self.parse_open_interest(data[0], market)
6386
6987
 
6387
6988
  async def fetch_open_interest_history(self, symbol: str, timeframe='1d', since: Int = None, limit: Int = None, params={}):
6388
6989
  """
6389
6990
  Retrieves the open interest history of a currency
6390
- :see: https://www.okx.com/docs-v5/en/#rest-api-trading-data-get-contracts-open-interest-and-volume
6391
- :see: https://www.okx.com/docs-v5/en/#rest-api-trading-data-get-options-open-interest-and-volume
6991
+
6992
+ https://www.okx.com/docs-v5/en/#rest-api-trading-data-get-contracts-open-interest-and-volume
6993
+ https://www.okx.com/docs-v5/en/#rest-api-trading-data-get-options-open-interest-and-volume
6994
+
6392
6995
  :param str symbol: Unified CCXT currency code or unified symbol
6393
6996
  :param str timeframe: "5m", "1h", or "1d" for option only "1d" or "8h"
6394
6997
  :param int [since]: The time in ms of the earliest record to retrieve unix timestamp
@@ -6397,8 +7000,8 @@ class okx(Exchange, ImplicitAPI):
6397
7000
  :param int [params.until]: The time in ms of the latest record to retrieve unix timestamp
6398
7001
  :returns: An array of `open interest structures <https://docs.ccxt.com/#/?id=open-interest-structure>`
6399
7002
  """
6400
- options = self.safe_value(self.options, 'fetchOpenInterestHistory', {})
6401
- timeframes = self.safe_value(options, 'timeframes', {})
7003
+ options = self.safe_dict(self.options, 'fetchOpenInterestHistory', {})
7004
+ timeframes = self.safe_dict(options, 'timeframes', {})
6402
7005
  timeframe = self.safe_string(timeframes, timeframe, timeframe)
6403
7006
  if timeframe != '5m' and timeframe != '1H' and timeframe != '1D':
6404
7007
  raise BadRequest(self.id + ' fetchOpenInterestHistory cannot only use the 5m, 1h, and 1d timeframe')
@@ -6412,7 +7015,7 @@ class okx(Exchange, ImplicitAPI):
6412
7015
  else:
6413
7016
  currency = self.currency(symbol)
6414
7017
  currencyId = currency['id']
6415
- request = {
7018
+ request: dict = {
6416
7019
  'ccy': currencyId,
6417
7020
  'period': timeframe,
6418
7021
  }
@@ -6424,10 +7027,10 @@ class okx(Exchange, ImplicitAPI):
6424
7027
  else:
6425
7028
  if since is not None:
6426
7029
  request['begin'] = since
6427
- until = self.safe_integer_2(params, 'till', 'until')
7030
+ until = self.safe_integer(params, 'until')
6428
7031
  if until is not None:
6429
7032
  request['end'] = until
6430
- params = self.omit(params, ['until', 'till'])
7033
+ params = self.omit(params, ['until'])
6431
7034
  response = await self.publicGetRubikStatContractsOpenInterestVolume(self.extend(request, params))
6432
7035
  #
6433
7036
  # {
@@ -6443,8 +7046,8 @@ class okx(Exchange, ImplicitAPI):
6443
7046
  # "msg": ''
6444
7047
  # }
6445
7048
  #
6446
- data = self.safe_value(response, 'data', [])
6447
- return self.parse_open_interests(data, None, since, limit)
7049
+ data = self.safe_list(response, 'data', [])
7050
+ return self.parse_open_interests_history(data, None, since, limit)
6448
7051
 
6449
7052
  def parse_open_interest(self, interest, market: Market = None):
6450
7053
  #
@@ -6463,6 +7066,7 @@ class okx(Exchange, ImplicitAPI):
6463
7066
  # "instType": "OPTION",
6464
7067
  # "oi": "300",
6465
7068
  # "oiCcy": "3",
7069
+ # "oiUsd": "3",
6466
7070
  # "ts": "1684551166251"
6467
7071
  # }
6468
7072
  #
@@ -6485,7 +7089,7 @@ class okx(Exchange, ImplicitAPI):
6485
7089
  else:
6486
7090
  baseVolume = self.safe_number(interest, 'oiCcy')
6487
7091
  openInterestAmount = self.safe_number(interest, 'oi')
6488
- openInterestValue = self.safe_number(interest, 'oiCcy')
7092
+ openInterestValue = self.safe_number(interest, 'oiUsd')
6489
7093
  return self.safe_open_interest({
6490
7094
  'symbol': self.safe_symbol(id),
6491
7095
  'baseVolume': baseVolume, # deprecated
@@ -6508,13 +7112,19 @@ class okx(Exchange, ImplicitAPI):
6508
7112
  async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
6509
7113
  """
6510
7114
  fetch deposit and withdraw fees
6511
- :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
7115
+
7116
+ https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
7117
+
6512
7118
  :param str[]|None codes: list of unified currency codes
6513
7119
  :param dict [params]: extra parameters specific to the exchange API endpoint
6514
7120
  :returns dict[]: a list of `fees structures <https://docs.ccxt.com/#/?id=fee-structure>`
6515
7121
  """
6516
7122
  await self.load_markets()
6517
- response = await self.privateGetAssetCurrencies(params)
7123
+ request = {}
7124
+ if codes is not None:
7125
+ ids = self.currency_ids(codes)
7126
+ request['ccy'] = ','.join(ids)
7127
+ response = await self.privateGetAssetCurrencies(self.extend(request, params))
6518
7128
  #
6519
7129
  # {
6520
7130
  # "code": "0",
@@ -6558,7 +7168,7 @@ class okx(Exchange, ImplicitAPI):
6558
7168
  # "msg": ""
6559
7169
  # }
6560
7170
  #
6561
- data = self.safe_value(response, 'data')
7171
+ data = self.safe_list(response, 'data')
6562
7172
  return self.parse_deposit_withdraw_fees(data, codes)
6563
7173
 
6564
7174
  def parse_deposit_withdraw_fees(self, response, codes=None, currencyIdKey=None):
@@ -6583,7 +7193,7 @@ class okx(Exchange, ImplicitAPI):
6583
7193
  # }
6584
7194
  # ]
6585
7195
  #
6586
- depositWithdrawFees = {}
7196
+ depositWithdrawFees: dict = {}
6587
7197
  codes = self.market_codes(codes)
6588
7198
  for i in range(0, len(response)):
6589
7199
  feeInfo = response[i]
@@ -6595,14 +7205,16 @@ class okx(Exchange, ImplicitAPI):
6595
7205
  depositWithdrawFees[code] = self.deposit_withdraw_fee({})
6596
7206
  depositWithdrawFees[code]['info'][currencyId] = feeInfo
6597
7207
  chain = self.safe_string(feeInfo, 'chain')
7208
+ if chain is None:
7209
+ continue
6598
7210
  chainSplit = chain.split('-')
6599
7211
  networkId = self.safe_value(chainSplit, 1)
6600
- withdrawFee = self.safe_number(feeInfo, 'minFee')
6601
- withdrawResult = {
7212
+ withdrawFee = self.safe_number(feeInfo, 'fee')
7213
+ withdrawResult: dict = {
6602
7214
  'fee': withdrawFee,
6603
7215
  'percentage': False if (withdrawFee is not None) else None,
6604
7216
  }
6605
- depositResult = {
7217
+ depositResult: dict = {
6606
7218
  'fee': None,
6607
7219
  'percentage': None,
6608
7220
  }
@@ -6621,7 +7233,9 @@ class okx(Exchange, ImplicitAPI):
6621
7233
  async def fetch_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
6622
7234
  """
6623
7235
  fetches historical settlement records
6624
- :see: https://www.okx.com/docs-v5/en/#rest-api-public-data-get-delivery-exercise-history
7236
+
7237
+ https://www.okx.com/docs-v5/en/#rest-api-public-data-get-delivery-exercise-history
7238
+
6625
7239
  :param str symbol: unified market symbol to fetch the settlement history for
6626
7240
  :param int [since]: timestamp in ms
6627
7241
  :param int [limit]: number of records
@@ -6636,7 +7250,7 @@ class okx(Exchange, ImplicitAPI):
6636
7250
  type, params = self.handle_market_type_and_params('fetchSettlementHistory', market, params)
6637
7251
  if type != 'future' and type != 'option':
6638
7252
  raise NotSupported(self.id + ' fetchSettlementHistory() supports futures and options markets only')
6639
- request = {
7253
+ request: dict = {
6640
7254
  'instType': self.convert_to_instrument_type(type),
6641
7255
  'uly': market['baseId'] + '-' + market['quoteId'],
6642
7256
  }
@@ -6663,7 +7277,7 @@ class okx(Exchange, ImplicitAPI):
6663
7277
  # "msg": ""
6664
7278
  # }
6665
7279
  #
6666
- data = self.safe_value(response, 'data', [])
7280
+ data = self.safe_list(response, 'data', [])
6667
7281
  settlements = self.parse_settlements(data, market)
6668
7282
  sorted = self.sort_by(settlements, 'timestamp')
6669
7283
  return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
@@ -6702,7 +7316,7 @@ class okx(Exchange, ImplicitAPI):
6702
7316
  for i in range(0, len(settlements)):
6703
7317
  entry = settlements[i]
6704
7318
  timestamp = self.safe_integer(entry, 'ts')
6705
- details = self.safe_value(entry, 'details', [])
7319
+ details = self.safe_list(entry, 'details', [])
6706
7320
  for j in range(0, len(details)):
6707
7321
  settlement = self.parse_settlement(details[j], market)
6708
7322
  result.append(self.extend(settlement, {
@@ -6714,7 +7328,9 @@ class okx(Exchange, ImplicitAPI):
6714
7328
  async def fetch_underlying_assets(self, params={}):
6715
7329
  """
6716
7330
  fetches the market ids of underlying assets for a specific contract market type
6717
- :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-underlying
7331
+
7332
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-underlying
7333
+
6718
7334
  :param dict [params]: exchange specific params
6719
7335
  :param str [params.type]: the contract market type, 'option', 'swap' or 'future', the default is 'option'
6720
7336
  :returns dict[]: a list of `underlying assets <https://docs.ccxt.com/#/?id=underlying-assets-structure>`
@@ -6726,7 +7342,7 @@ class okx(Exchange, ImplicitAPI):
6726
7342
  marketType = 'option'
6727
7343
  if (marketType != 'option') and (marketType != 'swap') and (marketType != 'future'):
6728
7344
  raise NotSupported(self.id + ' fetchUnderlyingAssets() supports contract markets only')
6729
- request = {
7345
+ request: dict = {
6730
7346
  'instType': self.convert_to_instrument_type(marketType),
6731
7347
  }
6732
7348
  response = await self.publicGetPublicUnderlying(self.extend(request, params))
@@ -6742,13 +7358,15 @@ class okx(Exchange, ImplicitAPI):
6742
7358
  # "msg": ""
6743
7359
  # }
6744
7360
  #
6745
- underlyings = self.safe_value(response, 'data', [])
7361
+ underlyings = self.safe_list(response, 'data', [])
6746
7362
  return underlyings[0]
6747
7363
 
6748
7364
  async def fetch_greeks(self, symbol: str, params={}) -> Greeks:
6749
7365
  """
6750
7366
  fetches an option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
6751
- :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-option-market-data
7367
+
7368
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-option-market-data
7369
+
6752
7370
  :param str symbol: unified symbol of the market to fetch greeks for
6753
7371
  :param dict [params]: extra parameters specific to the exchange API endpoint
6754
7372
  :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
@@ -6757,7 +7375,7 @@ class okx(Exchange, ImplicitAPI):
6757
7375
  market = self.market(symbol)
6758
7376
  marketId = market['id']
6759
7377
  optionParts = marketId.split('-')
6760
- request = {
7378
+ request: dict = {
6761
7379
  'uly': market['info']['uly'],
6762
7380
  'instFamily': market['info']['instFamily'],
6763
7381
  'expTime': self.safe_string(optionParts, 2),
@@ -6792,7 +7410,7 @@ class okx(Exchange, ImplicitAPI):
6792
7410
  # "msg": ""
6793
7411
  # }
6794
7412
  #
6795
- data = self.safe_value(response, 'data', [])
7413
+ data = self.safe_list(response, 'data', [])
6796
7414
  for i in range(0, len(data)):
6797
7415
  entry = data[i]
6798
7416
  entryMarketId = self.safe_string(entry, 'instId')
@@ -6800,7 +7418,7 @@ class okx(Exchange, ImplicitAPI):
6800
7418
  return self.parse_greeks(entry, market)
6801
7419
  return None
6802
7420
 
6803
- def parse_greeks(self, greeks, market: Market = None):
7421
+ def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
6804
7422
  #
6805
7423
  # {
6806
7424
  # "askVol": "0",
@@ -6852,15 +7470,17 @@ class okx(Exchange, ImplicitAPI):
6852
7470
  async def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
6853
7471
  """
6854
7472
  closes open positions for a market
6855
- :see: https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-close-positions
7473
+
7474
+ https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-close-positions
7475
+
6856
7476
  :param str symbol: Unified CCXT market symbol
6857
7477
  :param str [side]: 'buy' or 'sell', leave in net mode
6858
7478
  :param dict [params]: extra parameters specific to the okx api endpoint
6859
7479
  :param str [params.clientOrderId]: a unique identifier for the order
6860
7480
  :param str [params.marginMode]: 'cross' or 'isolated', default is 'cross
6861
7481
  :param str [params.code]: *required in the case of closing cross MARGIN position for Single-currency margin* margin currency
6862
- *
6863
- * EXCHANGE SPECIFIC PARAMETERS
7482
+
7483
+ EXCHANGE SPECIFIC PARAMETERS
6864
7484
  :param boolean [params.autoCxl]: whether any pending orders for closing out needs to be automatically canceled when close position via a market order. False or True, the default is False
6865
7485
  :param str [params.tag]: order tag a combination of case-sensitive alphanumerics, all numbers, or all letters of up to 16 characters
6866
7486
  :returns dict[]: `A list of position structures <https://docs.ccxt.com/#/?id=position-structure>`
@@ -6871,7 +7491,7 @@ class okx(Exchange, ImplicitAPI):
6871
7491
  code = self.safe_string(params, 'code')
6872
7492
  marginMode = None
6873
7493
  marginMode, params = self.handle_margin_mode_and_params('closePosition', params, 'cross')
6874
- request = {
7494
+ request: dict = {
6875
7495
  'instId': market['id'],
6876
7496
  'mgnMode': marginMode,
6877
7497
  }
@@ -6905,11 +7525,478 @@ class okx(Exchange, ImplicitAPI):
6905
7525
  # "outTime": "1701877077102579"
6906
7526
  # }
6907
7527
  #
6908
- data = self.safe_value(response, 'data')
6909
- order = self.safe_value(data, 0)
7528
+ data = self.safe_list(response, 'data', [])
7529
+ order = self.safe_dict(data, 0)
6910
7530
  return self.parse_order(order, market)
6911
7531
 
6912
- def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
7532
+ async def fetch_option(self, symbol: str, params={}) -> Option:
7533
+ """
7534
+ fetches option data that is commonly found in an option chain
7535
+
7536
+ https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-ticker
7537
+
7538
+ :param str symbol: unified market symbol
7539
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7540
+ :returns dict: an `option chain structure <https://docs.ccxt.com/#/?id=option-chain-structure>`
7541
+ """
7542
+ await self.load_markets()
7543
+ market = self.market(symbol)
7544
+ request: dict = {
7545
+ 'instId': market['id'],
7546
+ }
7547
+ response = await self.publicGetMarketTicker(self.extend(request, params))
7548
+ #
7549
+ # {
7550
+ # "code": "0",
7551
+ # "msg": "",
7552
+ # "data": [
7553
+ # {
7554
+ # "instType": "OPTION",
7555
+ # "instId": "BTC-USD-241227-60000-P",
7556
+ # "last": "",
7557
+ # "lastSz": "0",
7558
+ # "askPx": "",
7559
+ # "askSz": "0",
7560
+ # "bidPx": "",
7561
+ # "bidSz": "0",
7562
+ # "open24h": "",
7563
+ # "high24h": "",
7564
+ # "low24h": "",
7565
+ # "volCcy24h": "0",
7566
+ # "vol24h": "0",
7567
+ # "ts": "1711176035035",
7568
+ # "sodUtc0": "",
7569
+ # "sodUtc8": ""
7570
+ # }
7571
+ # ]
7572
+ # }
7573
+ #
7574
+ result = self.safe_list(response, 'data', [])
7575
+ chain = self.safe_dict(result, 0, {})
7576
+ return self.parse_option(chain, None, market)
7577
+
7578
+ async def fetch_option_chain(self, code: str, params={}) -> OptionChain:
7579
+ """
7580
+ fetches data for an underlying asset that is commonly found in an option chain
7581
+
7582
+ https://www.okx.com/docs-v5/en/#order-book-trading-market-data-get-tickers
7583
+
7584
+ :param str code: base currency to fetch an option chain for
7585
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7586
+ :param str [params.uly]: the underlying asset, can be obtained from fetchUnderlyingAssets()
7587
+ :returns dict: a list of `option chain structures <https://docs.ccxt.com/#/?id=option-chain-structure>`
7588
+ """
7589
+ await self.load_markets()
7590
+ currency = self.currency(code)
7591
+ request: dict = {
7592
+ 'uly': currency['code'] + '-USD',
7593
+ 'instType': 'OPTION',
7594
+ }
7595
+ response = await self.publicGetMarketTickers(self.extend(request, params))
7596
+ #
7597
+ # {
7598
+ # "code": "0",
7599
+ # "msg": "",
7600
+ # "data": [
7601
+ # {
7602
+ # "instType": "OPTION",
7603
+ # "instId": "BTC-USD-240323-52000-C",
7604
+ # "last": "",
7605
+ # "lastSz": "0",
7606
+ # "askPx": "",
7607
+ # "askSz": "0",
7608
+ # "bidPx": "",
7609
+ # "bidSz": "0",
7610
+ # "open24h": "",
7611
+ # "high24h": "",
7612
+ # "low24h": "",
7613
+ # "volCcy24h": "0",
7614
+ # "vol24h": "0",
7615
+ # "ts": "1711176207008",
7616
+ # "sodUtc0": "",
7617
+ # "sodUtc8": ""
7618
+ # },
7619
+ # ]
7620
+ # }
7621
+ #
7622
+ result = self.safe_list(response, 'data', [])
7623
+ return self.parse_option_chain(result, None, 'instId')
7624
+
7625
+ def parse_option(self, chain: dict, currency: Currency = None, market: Market = None) -> Option:
7626
+ #
7627
+ # {
7628
+ # "instType": "OPTION",
7629
+ # "instId": "BTC-USD-241227-60000-P",
7630
+ # "last": "",
7631
+ # "lastSz": "0",
7632
+ # "askPx": "",
7633
+ # "askSz": "0",
7634
+ # "bidPx": "",
7635
+ # "bidSz": "0",
7636
+ # "open24h": "",
7637
+ # "high24h": "",
7638
+ # "low24h": "",
7639
+ # "volCcy24h": "0",
7640
+ # "vol24h": "0",
7641
+ # "ts": "1711176035035",
7642
+ # "sodUtc0": "",
7643
+ # "sodUtc8": ""
7644
+ # }
7645
+ #
7646
+ marketId = self.safe_string(chain, 'instId')
7647
+ market = self.safe_market(marketId, market)
7648
+ timestamp = self.safe_integer(chain, 'ts')
7649
+ return {
7650
+ 'info': chain,
7651
+ 'currency': None,
7652
+ 'symbol': market['symbol'],
7653
+ 'timestamp': timestamp,
7654
+ 'datetime': self.iso8601(timestamp),
7655
+ 'impliedVolatility': None,
7656
+ 'openInterest': None,
7657
+ 'bidPrice': self.safe_number(chain, 'bidPx'),
7658
+ 'askPrice': self.safe_number(chain, 'askPx'),
7659
+ 'midPrice': None,
7660
+ 'markPrice': None,
7661
+ 'lastPrice': self.safe_number(chain, 'last'),
7662
+ 'underlyingPrice': None,
7663
+ 'change': None,
7664
+ 'percentage': None,
7665
+ 'baseVolume': self.safe_number(chain, 'volCcy24h'),
7666
+ 'quoteVolume': None,
7667
+ }
7668
+
7669
+ async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
7670
+ """
7671
+ fetch a quote for converting from one currency to another
7672
+
7673
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-estimate-quote
7674
+
7675
+ :param str fromCode: the currency that you want to sell and convert from
7676
+ :param str toCode: the currency that you want to buy and convert into
7677
+ :param float [amount]: how much you want to trade in units of the from currency
7678
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7679
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7680
+ """
7681
+ await self.load_markets()
7682
+ request: dict = {
7683
+ 'baseCcy': fromCode.upper(),
7684
+ 'quoteCcy': toCode.upper(),
7685
+ 'rfqSzCcy': fromCode.upper(),
7686
+ 'rfqSz': self.number_to_string(amount),
7687
+ 'side': 'sell',
7688
+ }
7689
+ response = await self.privatePostAssetConvertEstimateQuote(self.extend(request, params))
7690
+ #
7691
+ # {
7692
+ # "code": "0",
7693
+ # "data": [
7694
+ # {
7695
+ # "baseCcy": "ETH",
7696
+ # "baseSz": "0.01023052",
7697
+ # "clQReqId": "",
7698
+ # "cnvtPx": "2932.40104429",
7699
+ # "origRfqSz": "30",
7700
+ # "quoteCcy": "USDT",
7701
+ # "quoteId": "quoterETH-USDT16461885104612381",
7702
+ # "quoteSz": "30",
7703
+ # "quoteTime": "1646188510461",
7704
+ # "rfqSz": "30",
7705
+ # "rfqSzCcy": "USDT",
7706
+ # "side": "buy",
7707
+ # "ttlMs": "10000"
7708
+ # }
7709
+ # ],
7710
+ # "msg": ""
7711
+ # }
7712
+ #
7713
+ data = self.safe_list(response, 'data', [])
7714
+ result = self.safe_dict(data, 0, {})
7715
+ fromCurrencyId = self.safe_string(result, 'baseCcy', fromCode)
7716
+ fromCurrency = self.currency(fromCurrencyId)
7717
+ toCurrencyId = self.safe_string(result, 'quoteCcy', toCode)
7718
+ toCurrency = self.currency(toCurrencyId)
7719
+ return self.parse_conversion(result, fromCurrency, toCurrency)
7720
+
7721
+ async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
7722
+ """
7723
+ convert from one currency to another
7724
+
7725
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-convert-trade
7726
+
7727
+ :param str id: the id of the trade that you want to make
7728
+ :param str fromCode: the currency that you want to sell and convert from
7729
+ :param str toCode: the currency that you want to buy and convert into
7730
+ :param float [amount]: how much you want to trade in units of the from currency
7731
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7732
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7733
+ """
7734
+ await self.load_markets()
7735
+ request: dict = {
7736
+ 'quoteId': id,
7737
+ 'baseCcy': fromCode,
7738
+ 'quoteCcy': toCode,
7739
+ 'szCcy': fromCode,
7740
+ 'sz': self.number_to_string(amount),
7741
+ 'side': 'sell',
7742
+ }
7743
+ response = await self.privatePostAssetConvertTrade(self.extend(request, params))
7744
+ #
7745
+ # {
7746
+ # "code": "0",
7747
+ # "data": [
7748
+ # {
7749
+ # "baseCcy": "ETH",
7750
+ # "clTReqId": "",
7751
+ # "fillBaseSz": "0.01023052",
7752
+ # "fillPx": "2932.40104429",
7753
+ # "fillQuoteSz": "30",
7754
+ # "instId": "ETH-USDT",
7755
+ # "quoteCcy": "USDT",
7756
+ # "quoteId": "quoterETH-USDT16461885104612381",
7757
+ # "side": "buy",
7758
+ # "state": "fullyFilled",
7759
+ # "tradeId": "trader16461885203381437",
7760
+ # "ts": "1646188520338"
7761
+ # }
7762
+ # ],
7763
+ # "msg": ""
7764
+ # }
7765
+ #
7766
+ data = self.safe_list(response, 'data', [])
7767
+ result = self.safe_dict(data, 0, {})
7768
+ fromCurrencyId = self.safe_string(result, 'baseCcy', fromCode)
7769
+ fromCurrency = self.currency(fromCurrencyId)
7770
+ toCurrencyId = self.safe_string(result, 'quoteCcy', toCode)
7771
+ toCurrency = self.currency(toCurrencyId)
7772
+ return self.parse_conversion(result, fromCurrency, toCurrency)
7773
+
7774
+ async def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
7775
+ """
7776
+ fetch the data for a conversion trade
7777
+
7778
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-history
7779
+
7780
+ :param str id: the id of the trade that you want to fetch
7781
+ :param str [code]: the unified currency code of the conversion trade
7782
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7783
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7784
+ """
7785
+ await self.load_markets()
7786
+ request: dict = {
7787
+ 'clTReqId': id,
7788
+ }
7789
+ response = await self.privateGetAssetConvertHistory(self.extend(request, params))
7790
+ #
7791
+ # {
7792
+ # "code": "0",
7793
+ # "data": [
7794
+ # {
7795
+ # "clTReqId": "",
7796
+ # "instId": "ETH-USDT",
7797
+ # "side": "buy",
7798
+ # "fillPx": "2932.401044",
7799
+ # "baseCcy": "ETH",
7800
+ # "quoteCcy": "USDT",
7801
+ # "fillBaseSz": "0.01023052",
7802
+ # "state": "fullyFilled",
7803
+ # "tradeId": "trader16461885203381437",
7804
+ # "fillQuoteSz": "30",
7805
+ # "ts": "1646188520000"
7806
+ # }
7807
+ # ],
7808
+ # "msg": ""
7809
+ # }
7810
+ #
7811
+ data = self.safe_list(response, 'data', [])
7812
+ result = self.safe_dict(data, 0, {})
7813
+ fromCurrencyId = self.safe_string(result, 'baseCcy')
7814
+ toCurrencyId = self.safe_string(result, 'quoteCcy')
7815
+ fromCurrency = None
7816
+ toCurrency = None
7817
+ if fromCurrencyId is not None:
7818
+ fromCurrency = self.currency(fromCurrencyId)
7819
+ if toCurrencyId is not None:
7820
+ toCurrency = self.currency(toCurrencyId)
7821
+ return self.parse_conversion(result, fromCurrency, toCurrency)
7822
+
7823
+ async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
7824
+ """
7825
+ fetch the users history of conversion trades
7826
+
7827
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-history
7828
+
7829
+ :param str [code]: the unified currency code
7830
+ :param int [since]: the earliest time in ms to fetch conversions for
7831
+ :param int [limit]: the maximum number of conversion structures to retrieve
7832
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7833
+ :param int [params.until]: timestamp in ms of the latest conversion to fetch
7834
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
7835
+ """
7836
+ await self.load_markets()
7837
+ request: dict = {}
7838
+ request, params = self.handle_until_option('after', request, params)
7839
+ if since is not None:
7840
+ request['before'] = since
7841
+ if limit is not None:
7842
+ request['limit'] = limit
7843
+ response = await self.privateGetAssetConvertHistory(self.extend(request, params))
7844
+ #
7845
+ # {
7846
+ # "code": "0",
7847
+ # "data": [
7848
+ # {
7849
+ # "clTReqId": "",
7850
+ # "instId": "ETH-USDT",
7851
+ # "side": "buy",
7852
+ # "fillPx": "2932.401044",
7853
+ # "baseCcy": "ETH",
7854
+ # "quoteCcy": "USDT",
7855
+ # "fillBaseSz": "0.01023052",
7856
+ # "state": "fullyFilled",
7857
+ # "tradeId": "trader16461885203381437",
7858
+ # "fillQuoteSz": "30",
7859
+ # "ts": "1646188520000"
7860
+ # }
7861
+ # ],
7862
+ # "msg": ""
7863
+ # }
7864
+ #
7865
+ rows = self.safe_list(response, 'data', [])
7866
+ return self.parse_conversions(rows, code, 'baseCcy', 'quoteCcy', since, limit)
7867
+
7868
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
7869
+ #
7870
+ # fetchConvertQuote
7871
+ #
7872
+ # {
7873
+ # "baseCcy": "ETH",
7874
+ # "baseSz": "0.01023052",
7875
+ # "clQReqId": "",
7876
+ # "cnvtPx": "2932.40104429",
7877
+ # "origRfqSz": "30",
7878
+ # "quoteCcy": "USDT",
7879
+ # "quoteId": "quoterETH-USDT16461885104612381",
7880
+ # "quoteSz": "30",
7881
+ # "quoteTime": "1646188510461",
7882
+ # "rfqSz": "30",
7883
+ # "rfqSzCcy": "USDT",
7884
+ # "side": "buy",
7885
+ # "ttlMs": "10000"
7886
+ # }
7887
+ #
7888
+ # createConvertTrade
7889
+ #
7890
+ # {
7891
+ # "baseCcy": "ETH",
7892
+ # "clTReqId": "",
7893
+ # "fillBaseSz": "0.01023052",
7894
+ # "fillPx": "2932.40104429",
7895
+ # "fillQuoteSz": "30",
7896
+ # "instId": "ETH-USDT",
7897
+ # "quoteCcy": "USDT",
7898
+ # "quoteId": "quoterETH-USDT16461885104612381",
7899
+ # "side": "buy",
7900
+ # "state": "fullyFilled",
7901
+ # "tradeId": "trader16461885203381437",
7902
+ # "ts": "1646188520338"
7903
+ # }
7904
+ #
7905
+ # fetchConvertTrade, fetchConvertTradeHistory
7906
+ #
7907
+ # {
7908
+ # "clTReqId": "",
7909
+ # "instId": "ETH-USDT",
7910
+ # "side": "buy",
7911
+ # "fillPx": "2932.401044",
7912
+ # "baseCcy": "ETH",
7913
+ # "quoteCcy": "USDT",
7914
+ # "fillBaseSz": "0.01023052",
7915
+ # "state": "fullyFilled",
7916
+ # "tradeId": "trader16461885203381437",
7917
+ # "fillQuoteSz": "30",
7918
+ # "ts": "1646188520000"
7919
+ # }
7920
+ #
7921
+ timestamp = self.safe_integer_2(conversion, 'quoteTime', 'ts')
7922
+ fromCoin = self.safe_string(conversion, 'baseCcy')
7923
+ fromCode = self.safe_currency_code(fromCoin, fromCurrency)
7924
+ to = self.safe_string(conversion, 'quoteCcy')
7925
+ toCode = self.safe_currency_code(to, toCurrency)
7926
+ return {
7927
+ 'info': conversion,
7928
+ 'timestamp': timestamp,
7929
+ 'datetime': self.iso8601(timestamp),
7930
+ 'id': self.safe_string_n(conversion, ['clQReqId', 'tradeId', 'quoteId']),
7931
+ 'fromCurrency': fromCode,
7932
+ 'fromAmount': self.safe_number_2(conversion, 'baseSz', 'fillBaseSz'),
7933
+ 'toCurrency': toCode,
7934
+ 'toAmount': self.safe_number_2(conversion, 'quoteSz', 'fillQuoteSz'),
7935
+ 'price': self.safe_number_2(conversion, 'cnvtPx', 'fillPx'),
7936
+ 'fee': None,
7937
+ }
7938
+
7939
+ async def fetch_convert_currencies(self, params={}) -> Currencies:
7940
+ """
7941
+ fetches all available currencies that can be converted
7942
+
7943
+ https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-currencies
7944
+
7945
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7946
+ :returns dict: an associative dictionary of currencies
7947
+ """
7948
+ await self.load_markets()
7949
+ response = await self.privateGetAssetConvertCurrencies(params)
7950
+ #
7951
+ # {
7952
+ # "code": "0",
7953
+ # "data": [
7954
+ # {
7955
+ # "ccy": "BTC",
7956
+ # "max": "",
7957
+ # "min": ""
7958
+ # },
7959
+ # ],
7960
+ # "msg": ""
7961
+ # }
7962
+ #
7963
+ result: dict = {}
7964
+ data = self.safe_list(response, 'data', [])
7965
+ for i in range(0, len(data)):
7966
+ entry = data[i]
7967
+ id = self.safe_string(entry, 'ccy')
7968
+ code = self.safe_currency_code(id)
7969
+ result[code] = {
7970
+ 'info': entry,
7971
+ 'id': id,
7972
+ 'code': code,
7973
+ 'networks': None,
7974
+ 'type': None,
7975
+ 'name': None,
7976
+ 'active': None,
7977
+ 'deposit': None,
7978
+ 'withdraw': None,
7979
+ 'fee': None,
7980
+ 'precision': None,
7981
+ 'limits': {
7982
+ 'amount': {
7983
+ 'min': self.safe_number(entry, 'min'),
7984
+ 'max': self.safe_number(entry, 'max'),
7985
+ },
7986
+ 'withdraw': {
7987
+ 'min': None,
7988
+ 'max': None,
7989
+ },
7990
+ 'deposit': {
7991
+ 'min': None,
7992
+ 'max': None,
7993
+ },
7994
+ },
7995
+ 'created': None,
7996
+ }
7997
+ return result
7998
+
7999
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
6913
8000
  if not response:
6914
8001
  return None # fallback to default error handler
6915
8002
  #
@@ -6935,7 +8022,7 @@ class okx(Exchange, ImplicitAPI):
6935
8022
  code = self.safe_string(response, 'code')
6936
8023
  if (code != '0') and (code != '2'): # 2 means that bulk operation partially succeeded
6937
8024
  feedback = self.id + ' ' + body
6938
- data = self.safe_value(response, 'data', [])
8025
+ data = self.safe_list(response, 'data', [])
6939
8026
  for i in range(0, len(data)):
6940
8027
  error = data[i]
6941
8028
  errorCode = self.safe_string(error, 'sCode')
@@ -6945,3 +8032,238 @@ class okx(Exchange, ImplicitAPI):
6945
8032
  self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
6946
8033
  raise ExchangeError(feedback) # unknown message
6947
8034
  return None
8035
+
8036
+ async def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}) -> List[MarginModification]:
8037
+ """
8038
+ fetches the history of margin added or reduced from contract isolated positions
8039
+
8040
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-7-days
8041
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
8042
+
8043
+ :param str [symbol]: not used by okx fetchMarginAdjustmentHistory
8044
+ :param str [type]: "add" or "reduce"
8045
+ :param int [since]: the earliest time in ms to fetch margin adjustment history for
8046
+ :param int [limit]: the maximum number of entries to retrieve
8047
+ :param dict params: extra parameters specific to the exchange api endpoint
8048
+ :param boolean [params.auto]: True if fetching auto margin increases
8049
+ :returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
8050
+ """
8051
+ await self.load_markets()
8052
+ auto = self.safe_bool(params, 'auto')
8053
+ if type is None:
8054
+ raise ArgumentsRequired(self.id + ' fetchMarginAdjustmentHistory() requires a type argument')
8055
+ isAdd = type == 'add'
8056
+ subType = '160' if isAdd else '161'
8057
+ if auto:
8058
+ if isAdd:
8059
+ subType = '162'
8060
+ else:
8061
+ raise BadRequest(self.id + ' cannot fetch margin adjustments for type ' + type)
8062
+ request: dict = {
8063
+ 'subType': subType,
8064
+ 'mgnMode': 'isolated',
8065
+ }
8066
+ until = self.safe_integer(params, 'until')
8067
+ params = self.omit(params, 'until')
8068
+ if since is not None:
8069
+ request['startTime'] = since
8070
+ if limit is not None:
8071
+ request['limit'] = limit
8072
+ if until is not None:
8073
+ request['endTime'] = until
8074
+ response = None
8075
+ now = self.milliseconds()
8076
+ oneWeekAgo = now - 604800000
8077
+ threeMonthsAgo = now - 7776000000
8078
+ if (since is None) or (since > oneWeekAgo):
8079
+ response = await self.privateGetAccountBills(self.extend(request, params))
8080
+ elif since > threeMonthsAgo:
8081
+ response = await self.privateGetAccountBillsArchive(self.extend(request, params))
8082
+ else:
8083
+ raise BadRequest(self.id + ' fetchMarginAdjustmentHistory() cannot fetch margin adjustments older than 3 months')
8084
+ #
8085
+ # {
8086
+ # code: '0',
8087
+ # data: [
8088
+ # {
8089
+ # bal: '67621.4325135010619812',
8090
+ # balChg: '-10.0000000000000000',
8091
+ # billId: '691293628710342659',
8092
+ # ccy: 'USDT',
8093
+ # clOrdId: '',
8094
+ # execType: '',
8095
+ # fee: '0',
8096
+ # fillFwdPx: '',
8097
+ # fillIdxPx: '',
8098
+ # fillMarkPx: '',
8099
+ # fillMarkVol: '',
8100
+ # fillPxUsd: '',
8101
+ # fillPxVol: '',
8102
+ # fillTime: '1711089244850',
8103
+ # from: '',
8104
+ # instId: 'XRP-USDT-SWAP',
8105
+ # instType: 'SWAP',
8106
+ # interest: '0',
8107
+ # mgnMode: 'isolated',
8108
+ # notes: '',
8109
+ # ordId: '',
8110
+ # pnl: '0',
8111
+ # posBal: '73.12',
8112
+ # posBalChg: '10.00',
8113
+ # px: '',
8114
+ # subType: '160',
8115
+ # sz: '10',
8116
+ # tag: '',
8117
+ # to: '',
8118
+ # tradeId: '0',
8119
+ # ts: '1711089244699',
8120
+ # type: '6'
8121
+ # }
8122
+ # ],
8123
+ # msg: ''
8124
+ # }
8125
+ #
8126
+ data = self.safe_list(response, 'data')
8127
+ modifications = self.parse_margin_modifications(data)
8128
+ return self.filter_by_symbol_since_limit(modifications, symbol, since, limit)
8129
+
8130
+ async def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
8131
+ """
8132
+ fetches historical positions
8133
+
8134
+ https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-positions-history
8135
+
8136
+ :param str [symbols]: unified market symbols
8137
+ :param int [since]: timestamp in ms of the earliest position to fetch
8138
+ :param int [limit]: the maximum amount of records to fetch, default=100, max=100
8139
+ :param dict params: extra parameters specific to the exchange api endpoint
8140
+ :param str [params.marginMode]: "cross" or "isolated"
8141
+
8142
+ EXCHANGE SPECIFIC PARAMETERS
8143
+ :param str [params.instType]: margin, swap, futures or option
8144
+ :param str [params.type]: the type of latest close position 1: close position partially, 2:close all, 3:liquidation, 4:partial liquidation; 5:adl, is it is the latest type if there are several types for the same position
8145
+ :param str [params.posId]: position id, there is attribute expiration, the posid will be expired if it is more than 30 days after the last full close position, then position will use new posid
8146
+ :param str [params.before]: timestamp in ms of the earliest position to fetch based on the last update time of the position
8147
+ :param str [params.after]: timestamp in ms of the latest position to fetch based on the last update time of the position
8148
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
8149
+ """
8150
+ await self.load_markets()
8151
+ marginMode = self.safe_string(params, 'marginMode')
8152
+ instType = self.safe_string_upper(params, 'instType')
8153
+ params = self.omit(params, ['until', 'marginMode', 'instType'])
8154
+ if limit is None:
8155
+ limit = 100
8156
+ request: dict = {
8157
+ 'limit': limit,
8158
+ }
8159
+ if symbols is not None:
8160
+ symbolsLength = len(symbols)
8161
+ if symbolsLength == 1:
8162
+ market = self.market(symbols[0])
8163
+ request['instId'] = market['id']
8164
+ if marginMode is not None:
8165
+ request['mgnMode'] = marginMode
8166
+ if instType is not None:
8167
+ request['instType'] = instType
8168
+ response = await self.privateGetAccountPositionsHistory(self.extend(request, params))
8169
+ #
8170
+ # {
8171
+ # code: '0',
8172
+ # data: [
8173
+ # {
8174
+ # cTime: '1708735940395',
8175
+ # ccy: 'USDT',
8176
+ # closeAvgPx: '0.6330444444444444',
8177
+ # closeTotalPos: '27',
8178
+ # direction: 'long',
8179
+ # fee: '-1.69566',
8180
+ # fundingFee: '-11.870404179341788',
8181
+ # instId: 'XRP-USDT-SWAP',
8182
+ # instType: 'SWAP',
8183
+ # lever: '3.0',
8184
+ # liqPenalty: '0',
8185
+ # mgnMode: 'cross',
8186
+ # openAvgPx: '0.623',
8187
+ # openMaxPos: '15',
8188
+ # pnl: '27.11999999999988',
8189
+ # pnlRatio: '0.0241732402722634',
8190
+ # posId: '681423155054862336',
8191
+ # realizedPnl: '13.553935820658092',
8192
+ # triggerPx: '',
8193
+ # type: '2',
8194
+ # uTime: '1711088748170',
8195
+ # uly: 'XRP-USDT'
8196
+ # },
8197
+ # ...
8198
+ # ],
8199
+ # msg: ''
8200
+ # }
8201
+ #
8202
+ data = self.safe_list(response, 'data')
8203
+ positions = self.parse_positions(data, symbols, params)
8204
+ return self.filter_by_since_limit(positions, since, limit)
8205
+
8206
+ async def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LongShortRatio]:
8207
+ """
8208
+ fetches the long short ratio history for a unified market symbol
8209
+
8210
+ https://www.okx.com/docs-v5/en/#trading-statistics-rest-api-get-contract-long-short-ratio
8211
+
8212
+ :param str symbol: unified symbol of the market to fetch the long short ratio for
8213
+ :param str [timeframe]: the period for the ratio
8214
+ :param int [since]: the earliest time in ms to fetch ratios for
8215
+ :param int [limit]: the maximum number of long short ratio structures to retrieve
8216
+ :param dict [params]: extra parameters specific to the exchange API endpoint
8217
+ :param int [params.until]: timestamp in ms of the latest ratio to fetch
8218
+ :returns dict[]: an array of `long short ratio structures <https://docs.ccxt.com/#/?id=long-short-ratio-structure>`
8219
+ """
8220
+ await self.load_markets()
8221
+ market = self.market(symbol)
8222
+ request: dict = {
8223
+ 'instId': market['id'],
8224
+ }
8225
+ until = self.safe_string_2(params, 'until', 'end')
8226
+ params = self.omit(params, 'until')
8227
+ if until is not None:
8228
+ request['end'] = until
8229
+ if timeframe is not None:
8230
+ request['period'] = timeframe
8231
+ if since is not None:
8232
+ request['begin'] = since
8233
+ if limit is not None:
8234
+ request['limit'] = limit
8235
+ response = await self.publicGetRubikStatContractsLongShortAccountRatioContract(self.extend(request, params))
8236
+ #
8237
+ # {
8238
+ # "code": "0",
8239
+ # "data": [
8240
+ # ["1729323600000", "0.9398602814619824"],
8241
+ # ["1729323300000", "0.9398602814619824"],
8242
+ # ["1729323000000", "0.9398602814619824"],
8243
+ # ],
8244
+ # "msg": ""
8245
+ # }
8246
+ #
8247
+ data = self.safe_list(response, 'data', [])
8248
+ result = []
8249
+ for i in range(0, len(data)):
8250
+ entry = data[i]
8251
+ result.append({
8252
+ 'timestamp': self.safe_string(entry, 0),
8253
+ 'longShortRatio': self.safe_string(entry, 1),
8254
+ })
8255
+ return self.parse_long_short_ratio_history(result, market)
8256
+
8257
+ def parse_long_short_ratio(self, info: dict, market: Market = None) -> LongShortRatio:
8258
+ timestamp = self.safe_integer(info, 'timestamp')
8259
+ symbol = None
8260
+ if market is not None:
8261
+ symbol = market['symbol']
8262
+ return {
8263
+ 'info': info,
8264
+ 'symbol': symbol,
8265
+ 'timestamp': timestamp,
8266
+ 'datetime': self.iso8601(timestamp),
8267
+ 'timeframe': None,
8268
+ 'longShortRatio': self.safe_number(info, 'longShortRatio'),
8269
+ }