ccxt 4.2.76__py2.py3-none-any.whl → 4.4.48__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +25 -0
  44. ccxt/abstract/kucoinfutures.py +35 -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 +3513 -1511
  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 +3105 -881
  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 +239 -50
  89. ccxt/async_support/bitget.py +1513 -563
  90. ccxt/async_support/bithumb.py +201 -67
  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 +403 -150
  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 +2326 -1255
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1455 -288
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +206 -89
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +467 -158
  125. ccxt/async_support/deribit.py +558 -324
  126. ccxt/async_support/digifinex.py +340 -223
  127. ccxt/async_support/ellipx.py +1826 -0
  128. ccxt/async_support/exmo.py +259 -128
  129. ccxt/async_support/gate.py +1473 -464
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +334 -178
  133. ccxt/async_support/hollaex.py +134 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +105 -56
  136. ccxt/async_support/hyperliquid.py +1634 -269
  137. ccxt/async_support/idex.py +148 -95
  138. ccxt/async_support/independentreserve.py +236 -31
  139. ccxt/async_support/indodax.py +165 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +1050 -355
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +138 -106
  145. ccxt/async_support/latoken.py +135 -79
  146. ccxt/async_support/lbank.py +290 -113
  147. ccxt/async_support/luno.py +112 -62
  148. ccxt/async_support/lykke.py +104 -55
  149. ccxt/async_support/mercado.py +36 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +43 -0
  152. ccxt/async_support/ndax.py +163 -82
  153. ccxt/async_support/novadax.py +121 -75
  154. ccxt/async_support/oceanex.py +175 -59
  155. ccxt/async_support/okcoin.py +222 -163
  156. ccxt/async_support/okx.py +1777 -455
  157. ccxt/async_support/onetrading.py +132 -414
  158. ccxt/async_support/oxfun.py +2832 -0
  159. ccxt/async_support/p2b.py +79 -51
  160. ccxt/async_support/paradex.py +2017 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1155 -295
  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 +1729 -482
  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 +3513 -1511
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3105 -881
  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 +239 -50
  197. ccxt/bitget.py +1513 -563
  198. ccxt/bithumb.py +200 -67
  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 +403 -150
  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 +2326 -1255
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1455 -288
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +206 -89
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +467 -158
  233. ccxt/deribit.py +558 -324
  234. ccxt/digifinex.py +340 -223
  235. ccxt/ellipx.py +1826 -0
  236. ccxt/exmo.py +259 -128
  237. ccxt/gate.py +1473 -464
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +334 -178
  241. ccxt/hollaex.py +134 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +105 -56
  244. ccxt/hyperliquid.py +1633 -269
  245. ccxt/idex.py +148 -95
  246. ccxt/independentreserve.py +235 -31
  247. ccxt/indodax.py +165 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +1050 -355
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +138 -106
  253. ccxt/latoken.py +135 -79
  254. ccxt/lbank.py +290 -113
  255. ccxt/luno.py +112 -62
  256. ccxt/lykke.py +104 -55
  257. ccxt/mercado.py +36 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +43 -0
  260. ccxt/ndax.py +163 -82
  261. ccxt/novadax.py +121 -75
  262. ccxt/oceanex.py +175 -59
  263. ccxt/okcoin.py +222 -163
  264. ccxt/okx.py +1777 -455
  265. ccxt/onetrading.py +132 -414
  266. ccxt/oxfun.py +2831 -0
  267. ccxt/p2b.py +79 -51
  268. ccxt/paradex.py +2017 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +63 -15
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +138 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +204 -82
  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 +967 -661
  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 +168 -32
  309. ccxt/pro/exmo.py +253 -21
  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 +93 -34
  336. ccxt/pro/poloniex.py +129 -50
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +93 -86
  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 +486 -70
  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} +465 -407
  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} +465 -409
  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 +1155 -295
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.48.dist-info/METADATA +646 -0
  497. ccxt-4.4.48.dist-info/RECORD +669 -0
  498. {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.76.dist-info/METADATA +0 -626
  545. ccxt-4.2.76.dist-info/RECORD +0 -534
  546. {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
ccxt/gate.py CHANGED
@@ -6,16 +6,16 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.gate import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, FundingHistory, Greeks, Int, Leverage, Leverages, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, BorrowInterest, Bool, Currencies, Currency, DepositAddress, FundingHistory, Greeks, Int, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import PermissionDenied
13
14
  from ccxt.base.errors import AccountNotEnabled
14
15
  from ccxt.base.errors import AccountSuspended
15
16
  from ccxt.base.errors import ArgumentsRequired
16
17
  from ccxt.base.errors import BadRequest
17
18
  from ccxt.base.errors import BadSymbol
18
- from ccxt.base.errors import BadResponse
19
19
  from ccxt.base.errors import InsufficientFunds
20
20
  from ccxt.base.errors import InvalidOrder
21
21
  from ccxt.base.errors import OrderNotFound
@@ -23,7 +23,7 @@ from ccxt.base.errors import OrderImmediatelyFillable
23
23
  from ccxt.base.errors import NotSupported
24
24
  from ccxt.base.errors import RateLimitExceeded
25
25
  from ccxt.base.errors import ExchangeNotAvailable
26
- from ccxt.base.errors import AuthenticationError
26
+ from ccxt.base.errors import BadResponse
27
27
  from ccxt.base.decimal_to_precision import TICK_SIZE
28
28
  from ccxt.base.precise import Precise
29
29
 
@@ -40,7 +40,7 @@ class gate(Exchange, ImplicitAPI):
40
40
  'certified': True,
41
41
  'pro': True,
42
42
  'urls': {
43
- 'logo': 'https://user-images.githubusercontent.com/1294454/31784029-0313c702-b509-11e7-9ccc-bc0da6a0e435.jpg',
43
+ 'logo': 'https://github.com/user-attachments/assets/64f988c5-07b6-4652-b5c1-679a6bf67c85',
44
44
  'doc': 'https://www.gate.io/docs/developers/apiv4/en/',
45
45
  'www': 'https://gate.io/',
46
46
  'api': {
@@ -67,6 +67,7 @@ class gate(Exchange, ImplicitAPI):
67
67
  'rebate': 'https://api.gateio.ws/api/v4',
68
68
  'earn': 'https://api.gateio.ws/api/v4',
69
69
  'account': 'https://api.gateio.ws/api/v4',
70
+ 'loan': 'https://api.gateio.ws/api/v4',
70
71
  },
71
72
  },
72
73
  'test': {
@@ -98,6 +99,8 @@ class gate(Exchange, ImplicitAPI):
98
99
  'borrowIsolatedMargin': True,
99
100
  'cancelAllOrders': True,
100
101
  'cancelOrder': True,
102
+ 'cancelOrders': True,
103
+ 'cancelOrdersForSymbols': True,
101
104
  'createMarketBuyOrderWithCost': True,
102
105
  'createMarketOrder': True,
103
106
  'createMarketOrderWithCost': False,
@@ -114,6 +117,7 @@ class gate(Exchange, ImplicitAPI):
114
117
  'createTriggerOrder': True,
115
118
  'editOrder': True,
116
119
  'fetchBalance': True,
120
+ 'fetchBorrowInterest': True,
117
121
  'fetchBorrowRateHistories': False,
118
122
  'fetchBorrowRateHistory': False,
119
123
  'fetchClosedOrders': True,
@@ -121,6 +125,8 @@ class gate(Exchange, ImplicitAPI):
121
125
  'fetchCrossBorrowRates': False,
122
126
  'fetchCurrencies': True,
123
127
  'fetchDepositAddress': True,
128
+ 'fetchDepositAddresses': False,
129
+ 'fetchDepositAddressesByNetwork': False,
124
130
  'fetchDeposits': True,
125
131
  'fetchDepositWithdrawFee': 'emulated',
126
132
  'fetchDepositWithdrawFees': True,
@@ -137,6 +143,7 @@ class gate(Exchange, ImplicitAPI):
137
143
  'fetchLeverages': True,
138
144
  'fetchLeverageTiers': True,
139
145
  'fetchLiquidations': True,
146
+ 'fetchMarginAdjustmentHistory': False,
140
147
  'fetchMarginMode': False,
141
148
  'fetchMarketLeverageTiers': True,
142
149
  'fetchMarkets': True,
@@ -149,16 +156,20 @@ class gate(Exchange, ImplicitAPI):
149
156
  'fetchOpenInterest': False,
150
157
  'fetchOpenInterestHistory': True,
151
158
  'fetchOpenOrders': True,
159
+ 'fetchOption': True,
160
+ 'fetchOptionChain': True,
152
161
  'fetchOrder': True,
153
162
  'fetchOrderBook': True,
154
163
  'fetchPosition': True,
164
+ 'fetchPositionHistory': 'emulated',
155
165
  'fetchPositionMode': False,
156
166
  'fetchPositions': True,
167
+ 'fetchPositionsHistory': True,
157
168
  'fetchPremiumIndexOHLCV': False,
158
169
  'fetchSettlementHistory': True,
159
170
  'fetchTicker': True,
160
171
  'fetchTickers': True,
161
- 'fetchTime': False,
172
+ 'fetchTime': True,
162
173
  'fetchTrades': True,
163
174
  'fetchTradingFee': True,
164
175
  'fetchTradingFees': True,
@@ -169,6 +180,7 @@ class gate(Exchange, ImplicitAPI):
169
180
  'reduceMargin': True,
170
181
  'repayCrossMargin': True,
171
182
  'repayIsolatedMargin': True,
183
+ 'sandbox': True,
172
184
  'setLeverage': True,
173
185
  'setMarginMode': False,
174
186
  'setPositionMode': True,
@@ -227,6 +239,7 @@ class gate(Exchange, ImplicitAPI):
227
239
  '{settle}/contract_stats': 1,
228
240
  '{settle}/index_constituents/{index}': 1,
229
241
  '{settle}/liq_orders': 1,
242
+ '{settle}/risk_limit_tiers': 1,
230
243
  },
231
244
  },
232
245
  'delivery': {
@@ -268,6 +281,7 @@ class gate(Exchange, ImplicitAPI):
268
281
  'withdrawals': {
269
282
  'post': {
270
283
  'withdrawals': 20, # 1r/s cost = 20 / 1 = 20
284
+ 'push': 1,
271
285
  },
272
286
  'delete': {
273
287
  'withdrawals/{withdrawal_id}': 1,
@@ -279,6 +293,7 @@ class gate(Exchange, ImplicitAPI):
279
293
  'withdrawals': 1,
280
294
  'deposits': 1,
281
295
  'sub_account_transfers': 1,
296
+ 'order_status': 1,
282
297
  'withdraw_status': 1,
283
298
  'sub_account_balances': 2.5,
284
299
  'sub_account_margin_balances': 2.5,
@@ -289,6 +304,7 @@ class gate(Exchange, ImplicitAPI):
289
304
  'total_balance': 2.5,
290
305
  'small_balance': 1,
291
306
  'small_balance_history': 1,
307
+ 'push': 1,
292
308
  },
293
309
  'post': {
294
310
  'transfers': 2.5, # 8r/s cost = 20 / 8 = 2.5
@@ -327,10 +343,21 @@ class gate(Exchange, ImplicitAPI):
327
343
  'loan_records': 20 / 15,
328
344
  'interest_records': 20 / 15,
329
345
  'estimate_rate': 20 / 15,
346
+ 'currency_discount_tiers': 20 / 15,
347
+ 'risk_units': 20 / 15,
348
+ 'unified_mode': 20 / 15,
349
+ 'loan_margin_tiers': 20 / 15,
350
+ 'leverage/user_currency_config': 20 / 15,
351
+ 'leverage/user_currency_setting': 20 / 15,
330
352
  },
331
353
  'post': {
332
354
  'account_mode': 20 / 15,
333
355
  'loans': 200 / 15, # 15r/10s cost = 20 / 1.5 = 13.33
356
+ 'portfolio_calculator': 20 / 15,
357
+ 'leverage/user_currency_setting': 20 / 15,
358
+ },
359
+ 'put': {
360
+ 'unified_mode': 20 / 15,
334
361
  },
335
362
  },
336
363
  'spot': {
@@ -507,9 +534,13 @@ class gate(Exchange, ImplicitAPI):
507
534
  'orders': 20 / 15,
508
535
  'orders/{order_id}': 20 / 15,
509
536
  'my_trades': 20 / 15,
537
+ 'mmp': 20 / 15,
510
538
  },
511
539
  'post': {
512
540
  'orders': 20 / 15,
541
+ 'countdown_cancel_all': 20 / 15,
542
+ 'mmp': 20 / 15,
543
+ 'mmp/reset': 20 / 15,
513
544
  },
514
545
  'delete': {
515
546
  'orders': 20 / 15,
@@ -553,6 +584,7 @@ class gate(Exchange, ImplicitAPI):
553
584
  'multi_collateral/currencies': 20 / 15,
554
585
  'multi_collateral/ltv': 20 / 15,
555
586
  'multi_collateral/fixed_rate': 20 / 15,
587
+ 'multi_collateral/current_rate': 20 / 15,
556
588
  },
557
589
  'post': {
558
590
  'collateral/orders': 20 / 15,
@@ -566,8 +598,10 @@ class gate(Exchange, ImplicitAPI):
566
598
  'account': {
567
599
  'get': {
568
600
  'detail': 20 / 15,
601
+ 'rate_limit': 20 / 15,
569
602
  'stp_groups': 20 / 15,
570
603
  'stp_groups/{stp_id}/users': 20 / 15,
604
+ 'stp_groups/debit_fee': 20 / 15,
571
605
  },
572
606
  'post': {
573
607
  'stp_groups': 20 / 15,
@@ -601,22 +635,25 @@ class gate(Exchange, ImplicitAPI):
601
635
  },
602
636
  # copied from gatev2
603
637
  'commonCurrencies': {
638
+ 'ORT': 'XREATORS',
639
+ 'ASS': 'ASSF',
604
640
  '88MPH': 'MPH',
605
- 'AXIS': 'Axis DeFi',
606
- 'BIFI': 'Bitcoin File',
607
- 'BOX': 'DefiBox',
608
- 'BYN': 'BeyondFi',
609
- 'EGG': 'Goose Finance',
610
- 'GTC': 'Game.com', # conflict with Gitcoin and Gastrocoin
611
- 'GTC_HT': 'Game.com HT',
612
- 'GTC_BSC': 'Game.com BSC',
613
- 'HIT': 'HitChain',
614
- 'MM': 'Million', # conflict with MilliMeter
615
- 'MPH': 'Morpher', # conflict with 88MPH
616
- 'POINT': 'GatePoint',
617
- 'RAI': 'Rai Reflex Index', # conflict with RAI Finance
618
- 'SBTC': 'Super Bitcoin',
619
- 'TNC': 'Trinity Network Credit',
641
+ 'AXIS': 'AXISDEFI',
642
+ 'BIFI': 'BITCOINFILE',
643
+ 'BOX': 'DEFIBOX',
644
+ 'BYN': 'BEYONDFI',
645
+ 'EGG': 'GOOSEFINANCE',
646
+ 'GTC': 'GAMECOM', # conflict with Gitcoin and Gastrocoin
647
+ 'GTC_HT': 'GAMECOM_HT',
648
+ 'GTC_BSC': 'GAMECOM_BSC',
649
+ 'HIT': 'HITCHAIN',
650
+ 'MM': 'MILLION', # conflict with MilliMeter
651
+ 'MPH': 'MORPHER', # conflict with 88MPH
652
+ 'POINT': 'GATEPOINT',
653
+ 'RAI': 'RAIREFLEXINDEX', # conflict with RAI Finance
654
+ 'RED': 'RedLang',
655
+ 'SBTC': 'SUPERBITCOIN',
656
+ 'TNC': 'TRINITYNETWORKCREDIT',
620
657
  'VAI': 'VAIOT',
621
658
  'TRAC': 'TRACO', # conflict with OriginTrail(TRAC)
622
659
  },
@@ -628,11 +665,17 @@ class gate(Exchange, ImplicitAPI):
628
665
  'X-Gate-Channel-Id': 'ccxt',
629
666
  },
630
667
  'options': {
668
+ 'timeDifference': 0, # the difference between system clock and exchange clock
669
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
631
670
  'sandboxMode': False,
671
+ 'unifiedAccount': None,
632
672
  'createOrder': {
633
673
  'expiration': 86400, # for conditional orders
634
674
  },
675
+ 'createMarketBuyOrderRequiresPrice': True,
635
676
  'networks': {
677
+ 'LINEA': 'LINEAETH',
678
+ 'KON': 'KONET',
636
679
  'AVAXC': 'AVAX_C',
637
680
  'BEP20': 'BSC',
638
681
  'EOS': 'EOS',
@@ -645,6 +688,9 @@ class gate(Exchange, ImplicitAPI):
645
688
  'OPTIMISM': 'OPETH',
646
689
  'POLKADOT': 'DOTSM',
647
690
  'TRC20': 'TRX',
691
+ 'LUNA': 'LUNC',
692
+ 'BASE': 'BASEEVM',
693
+ 'BRC20': 'BTCBRC',
648
694
  },
649
695
  'timeInForce': {
650
696
  'GTC': 'gtc',
@@ -667,7 +713,6 @@ class gate(Exchange, ImplicitAPI):
667
713
  'option': 'options',
668
714
  'options': 'options',
669
715
  },
670
- 'defaultType': 'spot',
671
716
  'swap': {
672
717
  'fetchMarkets': {
673
718
  'settlementCurrencies': ['usdt', 'btc'],
@@ -679,6 +724,114 @@ class gate(Exchange, ImplicitAPI):
679
724
  },
680
725
  },
681
726
  },
727
+ 'features': {
728
+ 'default': {
729
+ 'sandbox': True,
730
+ 'createOrder': {
731
+ 'marginMode': True,
732
+ 'triggerPrice': True,
733
+ 'triggerDirection': True, # todo: implementation edit needed
734
+ 'triggerPriceType': None,
735
+ 'stopLossPrice': True,
736
+ 'takeProfitPrice': True,
737
+ 'attachedStopLossTakeProfit': None,
738
+ 'timeInForce': {
739
+ 'IOC': True,
740
+ 'FOK': True,
741
+ 'PO': True,
742
+ 'GTD': False,
743
+ },
744
+ 'hedged': False,
745
+ 'trailing': False,
746
+ 'iceberg': True, # todo implement
747
+ 'selfTradePrevention': True, # todo implement
748
+ 'leverage': False,
749
+ 'marketBuyByCost': True,
750
+ 'marketBuyRequiresPrice': True,
751
+ },
752
+ 'createOrders': {
753
+ 'max': 40, # NOTE! max 10 per symbol
754
+ },
755
+ 'fetchMyTrades': {
756
+ 'marginMode': True,
757
+ 'limit': 1000,
758
+ 'daysBack': None,
759
+ 'untilDays': 30,
760
+ },
761
+ 'fetchOrder': {
762
+ 'marginMode': False,
763
+ 'trigger': True,
764
+ 'trailing': False,
765
+ },
766
+ 'fetchOpenOrders': {
767
+ 'marginMode': True,
768
+ 'trigger': True,
769
+ 'trailing': False,
770
+ 'limit': 100,
771
+ },
772
+ 'fetchOrders': None,
773
+ 'fetchClosedOrders': {
774
+ 'marginMode': True,
775
+ 'trigger': True,
776
+ 'trailing': False,
777
+ 'limit': 100,
778
+ 'untilDays': 30,
779
+ 'daysBack': None,
780
+ 'daysBackCanceled': None,
781
+ },
782
+ 'fetchOHLCV': {
783
+ 'limit': 1000,
784
+ },
785
+ },
786
+ 'spot': {
787
+ 'extends': 'default',
788
+ },
789
+ 'forDerivatives': {
790
+ 'extends': 'spot',
791
+ 'createOrder': {
792
+ 'marginMode': False,
793
+ 'triggerPriceType': {
794
+ 'last': True,
795
+ 'mark': True,
796
+ 'index': True,
797
+ },
798
+ },
799
+ 'createOrders': {
800
+ 'max': 10,
801
+ },
802
+ 'fetchMyTrades': {
803
+ 'marginMode': False,
804
+ 'untilDays': None,
805
+ },
806
+ 'fetchOpenOrders': {
807
+ 'marginMode': False,
808
+ },
809
+ 'fetchClosedOrders': {
810
+ 'marginMode': False,
811
+ 'untilDays': None,
812
+ 'limit': 1000,
813
+ },
814
+ 'fetchOHLCV': {
815
+ 'limit': 1999,
816
+ },
817
+ },
818
+ 'swap': {
819
+ 'linear': {
820
+ 'extends': 'forDerivatives',
821
+ },
822
+ 'inverse': {
823
+ 'extends': 'forDerivatives',
824
+ },
825
+ },
826
+ 'future': {
827
+ 'linear': {
828
+ 'extends': 'forDerivatives',
829
+ },
830
+ 'inverse': {
831
+ 'extends': 'forDerivatives',
832
+ },
833
+ },
834
+ },
682
835
  'precisionMode': TICK_SIZE,
683
836
  'fees': {
684
837
  'trading': {
@@ -790,6 +943,7 @@ class gate(Exchange, ImplicitAPI):
790
943
  'NOT_ACCEPTABLE': BadRequest,
791
944
  'METHOD_NOT_ALLOWED': BadRequest,
792
945
  'NOT_FOUND': ExchangeError,
946
+ 'AUTHENTICATION_FAILED': AuthenticationError,
793
947
  'INVALID_CREDENTIALS': AuthenticationError,
794
948
  'INVALID_KEY': AuthenticationError,
795
949
  'IP_FORBIDDEN': AuthenticationError,
@@ -884,13 +1038,58 @@ class gate(Exchange, ImplicitAPI):
884
1038
  super(gate, self).set_sandbox_mode(enable)
885
1039
  self.options['sandboxMode'] = enable
886
1040
 
887
- def convert_expire_date(self, date):
888
- # parse YYMMDD to timestamp
889
- year = date[0:2]
890
- month = date[2:4]
891
- day = date[4:6]
892
- reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z'
893
- return reconstructedDate
1041
+ def load_unified_status(self, params={}):
1042
+ """
1043
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1044
+ returns unifiedAccount so the user can check if the unified account is enabled
1045
+
1046
+ https://www.gate.io/docs/developers/apiv4/#get-account-detail
1047
+
1048
+ :returns boolean: True or False if the enabled unified account is enabled or not and sets the unifiedAccount option if it is None
1049
+ """
1050
+ unifiedAccount = self.safe_bool(self.options, 'unifiedAccount')
1051
+ if unifiedAccount is None:
1052
+ try:
1053
+ #
1054
+ # {
1055
+ # "user_id": 10406147,
1056
+ # "ip_whitelist": [],
1057
+ # "currency_pairs": [],
1058
+ # "key": {
1059
+ # "mode": 1
1060
+ # },
1061
+ # "tier": 0,
1062
+ # "tier_expire_time": "0001-01-01T00:00:00Z",
1063
+ # "copy_trading_role": 0
1064
+ # }
1065
+ #
1066
+ response = self.privateAccountGetDetail(params)
1067
+ result = self.safe_dict(response, 'key', {})
1068
+ self.options['unifiedAccount'] = self.safe_integer(result, 'mode') == 2
1069
+ except Exception as e:
1070
+ # if the request fails, the unifiedAccount is disabled
1071
+ self.options['unifiedAccount'] = False
1072
+ return self.options['unifiedAccount']
1073
+
1074
+ def upgrade_unified_trade_account(self, params={}):
1075
+ return self.privateUnifiedPutUnifiedMode(params)
1076
+
1077
+ def fetch_time(self, params={}):
1078
+ """
1079
+ fetches the current integer timestamp in milliseconds from the exchange server
1080
+
1081
+ https://www.gate.io/docs/developers/apiv4/en/#get-server-current-time
1082
+
1083
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1084
+ :returns int: the current integer timestamp in milliseconds from the exchange server
1085
+ """
1086
+ response = self.publicSpotGetTime(params)
1087
+ #
1088
+ # {
1089
+ # "server_time": 1731447921098
1090
+ # }
1091
+ #
1092
+ return self.safe_integer(response, 'server_time')
894
1093
 
895
1094
  def create_expired_option_market(self, symbol: str):
896
1095
  # support expired option contracts
@@ -955,24 +1154,28 @@ class gate(Exchange, ImplicitAPI):
955
1154
  'info': None,
956
1155
  }
957
1156
 
958
- def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
1157
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
959
1158
  isOption = (marketId is not None) and ((marketId.find('-C') > -1) or (marketId.find('-P') > -1))
960
1159
  if isOption and not (marketId in self.markets_by_id):
961
1160
  # handle expired option contracts
962
1161
  return self.create_expired_option_market(marketId)
963
1162
  return super(gate, self).safe_market(marketId, market, delimiter, marketType)
964
1163
 
965
- def fetch_markets(self, params={}):
1164
+ def fetch_markets(self, params={}) -> List[Market]:
966
1165
  """
967
1166
  retrieves data on all markets for gate
968
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-currency-pairs-supported # spot
969
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading # margin
970
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts # swap
971
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2 # future
972
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-the-contracts-with-specified-underlying-and-expiration-time # option
1167
+
1168
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-currency-pairs-supported # spot
1169
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading # margin
1170
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts # swap
1171
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2 # future
1172
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-the-contracts-with-specified-underlying-and-expiration-time # option
1173
+
973
1174
  :param dict [params]: extra parameters specific to the exchange API endpoint
974
1175
  :returns dict[]: an array of objects representing market data
975
1176
  """
1177
+ if self.options['adjustForTimeDifference']:
1178
+ self.load_time_difference()
976
1179
  sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
977
1180
  rawPromises = [
978
1181
  self.fetch_contract_markets(params),
@@ -990,8 +1193,9 @@ class gate(Exchange, ImplicitAPI):
990
1193
  return self.array_concat(markets, optionMarkets)
991
1194
 
992
1195
  def fetch_spot_markets(self, params={}):
993
- marginResponse = self.publicMarginGetCurrencyPairs(params)
994
- spotMarketsResponse = self.publicSpotGetCurrencyPairs(params)
1196
+ marginPromise = self.publicMarginGetCurrencyPairs(params)
1197
+ spotMarketsPromise = self.publicSpotGetCurrencyPairs(params)
1198
+ marginResponse, spotMarketsResponse = [marginPromise, spotMarketsPromise]
995
1199
  marginMarkets = self.index_by(marginResponse, 'id')
996
1200
  #
997
1201
  # Spot
@@ -1101,7 +1305,7 @@ class gate(Exchange, ImplicitAPI):
1101
1305
  futureSettlementCurrencies = self.get_settlement_currencies('future', 'fetchMarkets')
1102
1306
  for c in range(0, len(swapSettlementCurrencies)):
1103
1307
  settleId = swapSettlementCurrencies[c]
1104
- request = {
1308
+ request: dict = {
1105
1309
  'settle': settleId,
1106
1310
  }
1107
1311
  response = self.publicFuturesGetSettleContracts(self.extend(request, params))
@@ -1110,7 +1314,7 @@ class gate(Exchange, ImplicitAPI):
1110
1314
  result.append(parsedMarket)
1111
1315
  for c in range(0, len(futureSettlementCurrencies)):
1112
1316
  settleId = futureSettlementCurrencies[c]
1113
- request = {
1317
+ request: dict = {
1114
1318
  'settle': settleId,
1115
1319
  }
1116
1320
  response = self.publicDeliveryGetSettleContracts(self.extend(request, params))
@@ -1428,7 +1632,7 @@ class gate(Exchange, ImplicitAPI):
1428
1632
 
1429
1633
  def prepare_request(self, market=None, type=None, params={}):
1430
1634
  """
1431
- * @ignore
1635
+ @ignore
1432
1636
  Fills request params contract, settle, currency_pair, market and account where applicable
1433
1637
  :param dict market: CCXT market, required when type is None
1434
1638
  :param str type: 'spot', 'swap', or 'future', required when market is None
@@ -1436,7 +1640,7 @@ class gate(Exchange, ImplicitAPI):
1436
1640
  :returns: the api request object, and the new params object with non-needed parameters removed
1437
1641
  """
1438
1642
  # * Do not call for multi spot order methods like cancelAllOrders and fetchOpenOrders. Use multiOrderSpotPrepareRequest instead
1439
- request = {}
1643
+ request: dict = {}
1440
1644
  if market is not None:
1441
1645
  if market['contract']:
1442
1646
  request['contract'] = market['id']
@@ -1454,50 +1658,50 @@ class gate(Exchange, ImplicitAPI):
1454
1658
  request['settle'] = settle
1455
1659
  return [request, params]
1456
1660
 
1457
- def spot_order_prepare_request(self, market=None, stop=False, params={}):
1661
+ def spot_order_prepare_request(self, market=None, trigger=False, params={}):
1458
1662
  """
1459
- * @ignore
1663
+ @ignore
1460
1664
  Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
1461
1665
  :param dict market: CCXT market
1462
- :param bool stop: True if for a stop order
1666
+ :param bool trigger: True if for a trigger order
1463
1667
  :param dict [params]: request parameters
1464
1668
  :returns: the api request object, and the new params object with non-needed parameters removed
1465
1669
  """
1466
- marginMode, query = self.get_margin_mode(stop, params)
1467
- request = {}
1468
- if not stop:
1670
+ marginMode, query = self.get_margin_mode(trigger, params)
1671
+ request: dict = {}
1672
+ if not trigger:
1469
1673
  if market is None:
1470
- raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-stop orders')
1674
+ raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-trigger orders')
1471
1675
  request['account'] = marginMode
1472
- request['currency_pair'] = market['id'] # Should always be set for non-stop
1676
+ request['currency_pair'] = market['id'] # Should always be set for non-trigger
1473
1677
  return [request, query]
1474
1678
 
1475
- def multi_order_spot_prepare_request(self, market=None, stop=False, params={}):
1679
+ def multi_order_spot_prepare_request(self, market=None, trigger=False, params={}):
1476
1680
  """
1477
- * @ignore
1681
+ @ignore
1478
1682
  Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
1479
1683
  :param dict market: CCXT market
1480
- :param bool stop: True if for a stop order
1684
+ :param bool trigger: True if for a trigger order
1481
1685
  :param dict [params]: request parameters
1482
1686
  :returns: the api request object, and the new params object with non-needed parameters removed
1483
1687
  """
1484
- marginMode, query = self.get_margin_mode(stop, params)
1485
- request = {
1688
+ marginMode, query = self.get_margin_mode(trigger, params)
1689
+ request: dict = {
1486
1690
  'account': marginMode,
1487
1691
  }
1488
1692
  if market is not None:
1489
- if stop:
1490
- # gate spot and margin stop orders use the term market instead of currency_pair, and normal instead of spot. Neither parameter is used when fetching/cancelling a single order. They are used for creating a single stop order, but createOrder does not call self method
1693
+ if trigger:
1694
+ # gate spot and margin trigger orders use the term market instead of currency_pair, and normal instead of spot. Neither parameter is used when fetching/cancelling a single order. They are used for creating a single trigger order, but createOrder does not call self method
1491
1695
  request['market'] = market['id']
1492
1696
  else:
1493
1697
  request['currency_pair'] = market['id']
1494
1698
  return [request, query]
1495
1699
 
1496
- def get_margin_mode(self, stop, params):
1700
+ def get_margin_mode(self, trigger, params):
1497
1701
  """
1498
- * @ignore
1702
+ @ignore
1499
1703
  Gets the margin type for self api call
1500
- :param bool stop: True if for a stop order
1704
+ :param bool trigger: True if for a trigger order
1501
1705
  :param dict [params]: Request params
1502
1706
  :returns: The marginMode and the updated request params with marginMode removed, marginMode value is the value that can be read by the "account" property specified in gates api docs
1503
1707
  """
@@ -1510,12 +1714,16 @@ class gate(Exchange, ImplicitAPI):
1510
1714
  marginMode = 'margin'
1511
1715
  elif marginMode == '':
1512
1716
  marginMode = 'spot'
1513
- if stop:
1717
+ if trigger:
1514
1718
  if marginMode == 'spot':
1515
- # gate spot stop orders use the term normal instead of spot
1719
+ # gate spot trigger orders use the term normal instead of spot
1516
1720
  marginMode = 'normal'
1517
1721
  if marginMode == 'cross_margin':
1518
- raise BadRequest(self.id + ' getMarginMode() does not support stop orders for cross margin')
1722
+ raise BadRequest(self.id + ' getMarginMode() does not support trigger orders for cross margin')
1723
+ isUnifiedAccount = False
1724
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'getMarginMode', 'unifiedAccount')
1725
+ if isUnifiedAccount:
1726
+ marginMode = 'unified'
1519
1727
  return [marginMode, params]
1520
1728
 
1521
1729
  def get_settlement_currencies(self, type, method):
@@ -1524,10 +1732,12 @@ class gate(Exchange, ImplicitAPI):
1524
1732
  defaultSettle = ['usdt'] if (type == 'swap') else ['btc']
1525
1733
  return self.safe_value(fetchMarketsContractOptions, 'settlementCurrencies', defaultSettle)
1526
1734
 
1527
- def fetch_currencies(self, params={}):
1735
+ def fetch_currencies(self, params={}) -> Currencies:
1528
1736
  """
1529
1737
  fetches all available currencies on an exchange
1530
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-currencies-details
1738
+
1739
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-currencies-details
1740
+
1531
1741
  :param dict [params]: extra parameters specific to the exchange API endpoint
1532
1742
  :returns dict: an associative dictionary of currencies
1533
1743
  """
@@ -1535,6 +1745,8 @@ class gate(Exchange, ImplicitAPI):
1535
1745
  apiBackup = self.safe_value(self.urls, 'apiBackup')
1536
1746
  if apiBackup is not None:
1537
1747
  return None
1748
+ if self.check_required_credentials(False):
1749
+ self.load_unified_status()
1538
1750
  response = self.publicSpotGetCurrencies(params)
1539
1751
  #
1540
1752
  # {
@@ -1556,7 +1768,7 @@ class gate(Exchange, ImplicitAPI):
1556
1768
  # "chain":"ETH"
1557
1769
  # }
1558
1770
  #
1559
- result = {}
1771
+ result: dict = {}
1560
1772
  for i in range(0, len(response)):
1561
1773
  entry = response[i]
1562
1774
  currencyId = self.safe_string(entry, 'currency')
@@ -1633,10 +1845,12 @@ class gate(Exchange, ImplicitAPI):
1633
1845
  result[code]['withdraw'] = withdrawAvailable
1634
1846
  return result
1635
1847
 
1636
- def fetch_funding_rate(self, symbol: str, params={}):
1848
+ def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1637
1849
  """
1638
1850
  fetch the current funding rate
1639
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-contract
1851
+
1852
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-contract
1853
+
1640
1854
  :param str symbol: unified market symbol
1641
1855
  :param dict [params]: extra parameters specific to the exchange API endpoint
1642
1856
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
@@ -1693,13 +1907,15 @@ class gate(Exchange, ImplicitAPI):
1693
1907
  #
1694
1908
  return self.parse_funding_rate(response)
1695
1909
 
1696
- def fetch_funding_rates(self, symbols: Strings = None, params={}):
1910
+ def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
1697
1911
  """
1698
1912
  fetch the funding rate for multiple markets
1699
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
1913
+
1914
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
1915
+
1700
1916
  :param str[]|None symbols: list of unified market symbols
1701
1917
  :param dict [params]: extra parameters specific to the exchange API endpoint
1702
- :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
1918
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexed by market symbols
1703
1919
  """
1704
1920
  self.load_markets()
1705
1921
  symbols = self.market_symbols(symbols)
@@ -1749,10 +1965,9 @@ class gate(Exchange, ImplicitAPI):
1749
1965
  # }
1750
1966
  # ]
1751
1967
  #
1752
- result = self.parse_funding_rates(response)
1753
- return self.filter_by_array(result, 'symbol', symbols)
1968
+ return self.parse_funding_rates(response, symbols)
1754
1969
 
1755
- def parse_funding_rate(self, contract, market: Market = None):
1970
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
1756
1971
  #
1757
1972
  # {
1758
1973
  # "name": "BTC_USDT",
@@ -1803,6 +2018,7 @@ class gate(Exchange, ImplicitAPI):
1803
2018
  fundingRate = self.safe_number(contract, 'funding_rate')
1804
2019
  fundingTime = self.safe_timestamp(contract, 'funding_next_apply')
1805
2020
  fundingRateIndicative = self.safe_number(contract, 'funding_rate_indicative')
2021
+ fundingInterval = Precise.string_mul('1000', self.safe_string(contract, 'funding_interval'))
1806
2022
  return {
1807
2023
  'info': contract,
1808
2024
  'symbol': symbol,
@@ -1821,19 +2037,30 @@ class gate(Exchange, ImplicitAPI):
1821
2037
  'previousFundingRate': None,
1822
2038
  'previousFundingTimestamp': None,
1823
2039
  'previousFundingDatetime': None,
2040
+ 'interval': self.parse_funding_interval(fundingInterval),
2041
+ }
2042
+
2043
+ def parse_funding_interval(self, interval):
2044
+ intervals: dict = {
2045
+ '3600000': '1h',
2046
+ '14400000': '4h',
2047
+ '28800000': '8h',
2048
+ '57600000': '16h',
2049
+ '86400000': '24h',
1824
2050
  }
2051
+ return self.safe_string(intervals, interval, interval)
1825
2052
 
1826
2053
  def fetch_network_deposit_address(self, code: str, params={}):
1827
2054
  self.load_markets()
1828
2055
  currency = self.currency(code)
1829
- request = {
1830
- 'currency': currency['id'],
2056
+ request: dict = {
2057
+ 'currency': currency['id'], # todo: currencies have network-junctions
1831
2058
  }
1832
2059
  response = self.privateWalletGetDepositAddress(self.extend(request, params))
1833
2060
  addresses = self.safe_value(response, 'multichain_addresses')
1834
2061
  currencyId = self.safe_string(response, 'currency')
1835
2062
  code = self.safe_currency_code(currencyId)
1836
- result = {}
2063
+ result: dict = {}
1837
2064
  for i in range(0, len(addresses)):
1838
2065
  entry = addresses[i]
1839
2066
  #
@@ -1860,10 +2087,12 @@ class gate(Exchange, ImplicitAPI):
1860
2087
  }
1861
2088
  return result
1862
2089
 
1863
- def fetch_deposit_address(self, code: str, params={}):
2090
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1864
2091
  """
1865
2092
  fetch the deposit address for a currency associated with self account
1866
- :see: https://www.gate.io/docs/developers/apiv4/en/#generate-currency-deposit-address
2093
+
2094
+ https://www.gate.io/docs/developers/apiv4/en/#generate-currency-deposit-address
2095
+
1867
2096
  :param str code: unified currency code
1868
2097
  :param dict [params]: extra parameters specific to the exchange API endpoint
1869
2098
  :param str [params.network]: unified network code(not used directly by gate.io but used by ccxt to filter the response)
@@ -1873,8 +2102,8 @@ class gate(Exchange, ImplicitAPI):
1873
2102
  currency = self.currency(code)
1874
2103
  rawNetwork = self.safe_string_upper(params, 'network')
1875
2104
  params = self.omit(params, 'network')
1876
- request = {
1877
- 'currency': currency['id'],
2105
+ request: dict = {
2106
+ 'currency': currency['id'], # todo: currencies have network-junctions
1878
2107
  }
1879
2108
  response = self.privateWalletGetDepositAddress(self.extend(request, params))
1880
2109
  #
@@ -1925,24 +2154,25 @@ class gate(Exchange, ImplicitAPI):
1925
2154
  self.check_address(address)
1926
2155
  return {
1927
2156
  'info': response,
1928
- 'code': code, # kept here for backward-compatibility, but will be removed soon
1929
2157
  'currency': code,
2158
+ 'network': network,
1930
2159
  'address': address,
1931
2160
  'tag': tag,
1932
- 'network': network,
1933
2161
  }
1934
2162
 
1935
- def fetch_trading_fee(self, symbol: str, params={}):
2163
+ def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
1936
2164
  """
1937
2165
  fetch the trading fees for a market
1938
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-personal-trading-fee
2166
+
2167
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-personal-trading-fee
2168
+
1939
2169
  :param str symbol: unified market symbol
1940
2170
  :param dict [params]: extra parameters specific to the exchange API endpoint
1941
2171
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
1942
2172
  """
1943
2173
  self.load_markets()
1944
2174
  market = self.market(symbol)
1945
- request = {
2175
+ request: dict = {
1946
2176
  'currency_pair': market['id'],
1947
2177
  }
1948
2178
  response = self.privateWalletGetFee(self.extend(request, params))
@@ -1962,10 +2192,12 @@ class gate(Exchange, ImplicitAPI):
1962
2192
  #
1963
2193
  return self.parse_trading_fee(response, market)
1964
2194
 
1965
- def fetch_trading_fees(self, params={}):
2195
+ def fetch_trading_fees(self, params={}) -> TradingFees:
1966
2196
  """
1967
2197
  fetch the trading fees for multiple markets
1968
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-personal-trading-fee
2198
+
2199
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-personal-trading-fee
2200
+
1969
2201
  :param dict [params]: extra parameters specific to the exchange API endpoint
1970
2202
  :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1971
2203
  """
@@ -1988,7 +2220,7 @@ class gate(Exchange, ImplicitAPI):
1988
2220
  return self.parse_trading_fees(response)
1989
2221
 
1990
2222
  def parse_trading_fees(self, response):
1991
- result = {}
2223
+ result: dict = {}
1992
2224
  for i in range(0, len(self.symbols)):
1993
2225
  symbol = self.symbols[i]
1994
2226
  market = self.market(symbol)
@@ -2021,13 +2253,17 @@ class gate(Exchange, ImplicitAPI):
2021
2253
  'symbol': self.safe_string(market, 'symbol'),
2022
2254
  'maker': self.safe_number(info, makerKey),
2023
2255
  'taker': self.safe_number(info, takerKey),
2256
+ 'percentage': None,
2257
+ 'tierBased': None,
2024
2258
  }
2025
2259
 
2026
- def fetch_transaction_fees(self, codes: List[str] = None, params={}):
2260
+ def fetch_transaction_fees(self, codes: Strings = None, params={}):
2027
2261
  """
2028
- * @deprecated
2262
+ @deprecated
2029
2263
  please use fetchDepositWithdrawFees instead
2030
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-status
2264
+
2265
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-status
2266
+
2031
2267
  :param str[]|None codes: list of unified currency codes
2032
2268
  :param dict [params]: extra parameters specific to the exchange API endpoint
2033
2269
  :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -2051,7 +2287,7 @@ class gate(Exchange, ImplicitAPI):
2051
2287
  # }
2052
2288
  # }
2053
2289
  #
2054
- result = {}
2290
+ result: dict = {}
2055
2291
  withdrawFees = {}
2056
2292
  for i in range(0, len(response)):
2057
2293
  withdrawFees = {}
@@ -2078,7 +2314,9 @@ class gate(Exchange, ImplicitAPI):
2078
2314
  def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
2079
2315
  """
2080
2316
  fetch deposit and withdraw fees
2081
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-status
2317
+
2318
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-status
2319
+
2082
2320
  :param str[]|None codes: list of unified currency codes
2083
2321
  :param dict [params]: extra parameters specific to the exchange API endpoint
2084
2322
  :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -2125,7 +2363,7 @@ class gate(Exchange, ImplicitAPI):
2125
2363
  # }
2126
2364
  #
2127
2365
  withdrawFixOnChains = self.safe_value(fee, 'withdraw_fix_on_chains')
2128
- result = {
2366
+ result: dict = {
2129
2367
  'info': fee,
2130
2368
  'withdraw': {
2131
2369
  'fee': self.safe_number(fee, 'withdraw_fix'),
@@ -2141,7 +2379,8 @@ class gate(Exchange, ImplicitAPI):
2141
2379
  chainKeys = list(withdrawFixOnChains.keys())
2142
2380
  for i in range(0, len(chainKeys)):
2143
2381
  chainKey = chainKeys[i]
2144
- result['networks'][chainKey] = {
2382
+ networkCode = self.network_id_to_code(chainKey, self.safe_string(fee, 'currency'))
2383
+ result['networks'][networkCode] = {
2145
2384
  'withdraw': {
2146
2385
  'fee': self.parse_number(withdrawFixOnChains[chainKey]),
2147
2386
  'percentage': False,
@@ -2156,8 +2395,10 @@ class gate(Exchange, ImplicitAPI):
2156
2395
  def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2157
2396
  """
2158
2397
  fetch the history of funding payments paid and received on self account
2159
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-account-book-2
2160
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-account-book-3
2398
+
2399
+ https://www.gate.io/docs/developers/apiv4/en/#query-account-book-2
2400
+ https://www.gate.io/docs/developers/apiv4/en/#query-account-book-3
2401
+
2161
2402
  :param str symbol: unified market symbol
2162
2403
  :param int [since]: the earliest time in ms to fetch funding history for
2163
2404
  :param int [limit]: the maximum number of funding history structures to retrieve
@@ -2234,10 +2475,12 @@ class gate(Exchange, ImplicitAPI):
2234
2475
  def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
2235
2476
  """
2236
2477
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
2237
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-order-book
2238
- :see: https://www.gate.io/docs/developers/apiv4/en/#futures-order-book
2239
- :see: https://www.gate.io/docs/developers/apiv4/en/#futures-order-book-2
2240
- :see: https://www.gate.io/docs/developers/apiv4/en/#options-order-book
2478
+
2479
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-order-book
2480
+ https://www.gate.io/docs/developers/apiv4/en/#futures-order-book
2481
+ https://www.gate.io/docs/developers/apiv4/en/#futures-order-book-2
2482
+ https://www.gate.io/docs/developers/apiv4/en/#options-order-book
2483
+
2241
2484
  :param str symbol: unified symbol of the market to fetch the order book for
2242
2485
  :param int [limit]: the maximum amount of order book entries to return
2243
2486
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2246,7 +2489,7 @@ class gate(Exchange, ImplicitAPI):
2246
2489
  self.load_markets()
2247
2490
  market = self.market(symbol)
2248
2491
  #
2249
- # request = {
2492
+ # request: Dict = {
2250
2493
  # 'currency_pair': market['id'],
2251
2494
  # 'interval': '0', # depth, 0 means no aggregation is applied, default to 0
2252
2495
  # 'limit': limit, # maximum number of order depth data in asks or bids
@@ -2345,10 +2588,12 @@ class gate(Exchange, ImplicitAPI):
2345
2588
  def fetch_ticker(self, symbol: str, params={}) -> Ticker:
2346
2589
  """
2347
2590
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
2348
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-details-of-a-specifc-order
2349
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers
2350
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers-2
2351
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
2591
+
2592
+ https://www.gate.io/docs/developers/apiv4/en/#get-details-of-a-specifc-order
2593
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers
2594
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers-2
2595
+ https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
2596
+
2352
2597
  :param str symbol: unified symbol of the market to fetch the ticker for
2353
2598
  :param dict [params]: extra parameters specific to the exchange API endpoint
2354
2599
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -2381,7 +2626,7 @@ class gate(Exchange, ImplicitAPI):
2381
2626
  ticker = self.safe_value(response, 0)
2382
2627
  return self.parse_ticker(ticker, market)
2383
2628
 
2384
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
2629
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
2385
2630
  #
2386
2631
  # SPOT
2387
2632
  #
@@ -2488,16 +2733,20 @@ class gate(Exchange, ImplicitAPI):
2488
2733
  'average': None,
2489
2734
  'baseVolume': baseVolume,
2490
2735
  'quoteVolume': quoteVolume,
2736
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
2737
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
2491
2738
  'info': ticker,
2492
2739
  }, market)
2493
2740
 
2494
2741
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
2495
2742
  """
2496
2743
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
2497
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-details-of-a-specifc-order
2498
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers
2499
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers-2
2500
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
2744
+
2745
+ https://www.gate.io/docs/developers/apiv4/en/#get-details-of-a-specifc-order
2746
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers
2747
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-tickers-2
2748
+ https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
2749
+
2501
2750
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
2502
2751
  :param dict [params]: extra parameters specific to the exchange API endpoint
2503
2752
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -2544,10 +2793,15 @@ class gate(Exchange, ImplicitAPI):
2544
2793
  :param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
2545
2794
  :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
2546
2795
  :param str [params.symbol]: margin only - unified ccxt symbol
2796
+ :param boolean [params.unifiedAccount]: default False, set to True for fetching the unified account balance
2797
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
2547
2798
  """
2548
2799
  self.load_markets()
2800
+ self.load_unified_status()
2549
2801
  symbol = self.safe_string(params, 'symbol')
2550
2802
  params = self.omit(params, 'symbol')
2803
+ isUnifiedAccount = False
2804
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'fetchBalance', 'unifiedAccount')
2551
2805
  type, query = self.handle_market_type_and_params('fetchBalance', None, params)
2552
2806
  request, requestParams = self.prepare_request(None, type, query)
2553
2807
  marginMode, requestQuery = self.get_margin_mode(False, requestParams)
@@ -2555,7 +2809,9 @@ class gate(Exchange, ImplicitAPI):
2555
2809
  market = self.market(symbol)
2556
2810
  request['currency_pair'] = market['id']
2557
2811
  response = None
2558
- if type == 'spot':
2812
+ if isUnifiedAccount:
2813
+ response = self.privateUnifiedGetAccounts(self.extend(request, params))
2814
+ elif type == 'spot':
2559
2815
  if marginMode == 'spot':
2560
2816
  response = self.privateSpotGetAccounts(self.extend(request, requestQuery))
2561
2817
  elif marginMode == 'margin':
@@ -2718,12 +2974,63 @@ class gate(Exchange, ImplicitAPI):
2718
2974
  # "orders_limit": 10
2719
2975
  # }
2720
2976
  #
2721
- result = {
2977
+ # unified
2978
+ #
2979
+ # {
2980
+ # "user_id": 10001,
2981
+ # "locked": False,
2982
+ # "balances": {
2983
+ # "ETH": {
2984
+ # "available": "0",
2985
+ # "freeze": "0",
2986
+ # "borrowed": "0.075393666654",
2987
+ # "negative_liab": "0",
2988
+ # "futures_pos_liab": "0",
2989
+ # "equity": "1016.1",
2990
+ # "total_freeze": "0",
2991
+ # "total_liab": "0"
2992
+ # },
2993
+ # "POINT": {
2994
+ # "available": "9999999999.017023138734",
2995
+ # "freeze": "0",
2996
+ # "borrowed": "0",
2997
+ # "negative_liab": "0",
2998
+ # "futures_pos_liab": "0",
2999
+ # "equity": "12016.1",
3000
+ # "total_freeze": "0",
3001
+ # "total_liab": "0"
3002
+ # },
3003
+ # "USDT": {
3004
+ # "available": "0.00000062023",
3005
+ # "freeze": "0",
3006
+ # "borrowed": "0",
3007
+ # "negative_liab": "0",
3008
+ # "futures_pos_liab": "0",
3009
+ # "equity": "16.1",
3010
+ # "total_freeze": "0",
3011
+ # "total_liab": "0"
3012
+ # }
3013
+ # },
3014
+ # "total": "230.94621713",
3015
+ # "borrowed": "161.66395521",
3016
+ # "total_initial_margin": "1025.0524665088",
3017
+ # "total_margin_balance": "3382495.944473949183",
3018
+ # "total_maintenance_margin": "205.01049330176",
3019
+ # "total_initial_margin_rate": "3299.827135672679",
3020
+ # "total_maintenance_margin_rate": "16499.135678363399",
3021
+ # "total_available_margin": "3381470.892007440383",
3022
+ # "unified_account_total": "3381470.892007440383",
3023
+ # "unified_account_total_liab": "0",
3024
+ # "unified_account_total_equity": "100016.1",
3025
+ # "leverage": "2"
3026
+ # }
3027
+ #
3028
+ result: dict = {
2722
3029
  'info': response,
2723
3030
  }
2724
3031
  isolated = marginMode == 'margin'
2725
3032
  data = response
2726
- if 'balances' in data: # True for cross_margin
3033
+ if 'balances' in data: # True for cross_margin and unified
2727
3034
  flatBalances = []
2728
3035
  balances = self.safe_value(data, 'balances', [])
2729
3036
  # inject currency and create an artificial balance object
@@ -2744,7 +3051,7 @@ class gate(Exchange, ImplicitAPI):
2744
3051
  quote = self.safe_value(entry, 'quote', {})
2745
3052
  baseCode = self.safe_currency_code(self.safe_string(base, 'currency'))
2746
3053
  quoteCode = self.safe_currency_code(self.safe_string(quote, 'currency'))
2747
- subResult = {}
3054
+ subResult: dict = {}
2748
3055
  subResult[baseCode] = self.parse_balance_helper(base)
2749
3056
  subResult[quoteCode] = self.parse_balance_helper(quote)
2750
3057
  result[symbolInner] = self.safe_balance(subResult)
@@ -2757,10 +3064,12 @@ class gate(Exchange, ImplicitAPI):
2757
3064
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
2758
3065
  """
2759
3066
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
2760
- :see: https://www.gate.io/docs/developers/apiv4/en/#market-candlesticks # spot
2761
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-futures-candlesticks # swap
2762
- :see: https://www.gate.io/docs/developers/apiv4/en/#market-candlesticks # future
2763
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-options-candlesticks # option
3067
+
3068
+ https://www.gate.io/docs/developers/apiv4/en/#market-candlesticks # spot
3069
+ https://www.gate.io/docs/developers/apiv4/en/#get-futures-candlesticks # swap
3070
+ https://www.gate.io/docs/developers/apiv4/en/#market-candlesticks # future
3071
+ https://www.gate.io/docs/developers/apiv4/en/#get-options-candlesticks # option
3072
+
2764
3073
  :param str symbol: unified symbol of the market to fetch OHLCV data for
2765
3074
  :param str timeframe: the length of time each candle represents
2766
3075
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -2780,7 +3089,7 @@ class gate(Exchange, ImplicitAPI):
2780
3089
  if market['option']:
2781
3090
  return self.fetch_option_ohlcv(symbol, timeframe, since, limit, params)
2782
3091
  price = self.safe_string(params, 'price')
2783
- request = {}
3092
+ request: dict = {}
2784
3093
  request, params = self.prepare_request(market, None, params)
2785
3094
  request['interval'] = self.safe_string(self.timeframes, timeframe, timeframe)
2786
3095
  maxLimit = 1999 if market['contract'] else 1000
@@ -2806,7 +3115,6 @@ class gate(Exchange, ImplicitAPI):
2806
3115
  request['limit'] = limit
2807
3116
  response = None
2808
3117
  if market['contract']:
2809
- maxLimit = 1999
2810
3118
  isMark = (price == 'mark')
2811
3119
  isIndex = (price == 'index')
2812
3120
  if isMark or isIndex:
@@ -2824,7 +3132,7 @@ class gate(Exchange, ImplicitAPI):
2824
3132
  # separated option logic because the from, to and limit parameters weren't functioning
2825
3133
  self.load_markets()
2826
3134
  market = self.market(symbol)
2827
- request = {}
3135
+ request: dict = {}
2828
3136
  request, params = self.prepare_request(market, None, params)
2829
3137
  request['interval'] = self.safe_string(self.timeframes, timeframe, timeframe)
2830
3138
  response = self.publicOptionsGetCandlesticks(self.extend(request, params))
@@ -2833,23 +3141,38 @@ class gate(Exchange, ImplicitAPI):
2833
3141
  def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2834
3142
  """
2835
3143
  fetches historical funding rate prices
2836
- :see: https://www.gate.io/docs/developers/apiv4/en/#funding-rate-history
3144
+
3145
+ https://www.gate.io/docs/developers/apiv4/en/#funding-rate-history
3146
+
2837
3147
  :param str symbol: unified symbol of the market to fetch the funding rate history for
2838
3148
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
2839
3149
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
2840
3150
  :param dict [params]: extra parameters specific to the exchange API endpoint
3151
+ :param int [params.until]: timestamp in ms of the latest funding rate to fetch
3152
+ :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)
2841
3153
  :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2842
3154
  """
2843
3155
  if symbol is None:
2844
3156
  raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
2845
3157
  self.load_markets()
3158
+ paginate = False
3159
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
3160
+ if paginate:
3161
+ return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params)
2846
3162
  market = self.market(symbol)
2847
3163
  if not market['swap']:
2848
3164
  raise BadSymbol(self.id + ' fetchFundingRateHistory() supports swap contracts only')
2849
- request, query = self.prepare_request(market, None, params)
3165
+ request: dict = {}
3166
+ request, params = self.prepare_request(market, None, params)
2850
3167
  if limit is not None:
2851
3168
  request['limit'] = limit
2852
- response = self.publicFuturesGetSettleFundingRate(self.extend(request, query))
3169
+ if since is not None:
3170
+ request['from'] = self.parse_to_int(since / 1000)
3171
+ until = self.safe_integer(params, 'until')
3172
+ if until is not None:
3173
+ params = self.omit(params, 'until')
3174
+ request['to'] = self.parse_to_int(until / 1000)
3175
+ response = self.publicFuturesGetSettleFundingRate(self.extend(request, params))
2853
3176
  #
2854
3177
  # {
2855
3178
  # "r": "0.00063521",
@@ -2918,10 +3241,12 @@ class gate(Exchange, ImplicitAPI):
2918
3241
  def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
2919
3242
  """
2920
3243
  get the list of most recent trades for a particular symbol
2921
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-market-trades
2922
- :see: https://www.gate.io/docs/developers/apiv4/en/#futures-trading-history
2923
- :see: https://www.gate.io/docs/developers/apiv4/en/#futures-trading-history-2
2924
- :see: https://www.gate.io/docs/developers/apiv4/en/#options-trade-history
3244
+
3245
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-market-trades
3246
+ https://www.gate.io/docs/developers/apiv4/en/#futures-trading-history
3247
+ https://www.gate.io/docs/developers/apiv4/en/#futures-trading-history-2
3248
+ https://www.gate.io/docs/developers/apiv4/en/#options-trade-history
3249
+
2925
3250
  :param str symbol: unified symbol of the market to fetch trades for
2926
3251
  :param int [since]: timestamp in ms of the earliest trade to fetch
2927
3252
  :param int [limit]: the maximum amount of trades to fetch
@@ -2939,7 +3264,7 @@ class gate(Exchange, ImplicitAPI):
2939
3264
  #
2940
3265
  # spot
2941
3266
  #
2942
- # request = {
3267
+ # request: Dict = {
2943
3268
  # 'currency_pair': market['id'],
2944
3269
  # 'limit': limit, # maximum number of records to be returned in a single list
2945
3270
  # 'last_id': 'id', # specify list staring point using the id of last record in previous list-query results
@@ -2948,7 +3273,7 @@ class gate(Exchange, ImplicitAPI):
2948
3273
  #
2949
3274
  # swap, future
2950
3275
  #
2951
- # request = {
3276
+ # request: Dict = {
2952
3277
  # 'settle': market['settleId'],
2953
3278
  # 'contract': market['id'],
2954
3279
  # 'limit': limit, # maximum number of records to be returned in a single list
@@ -3022,10 +3347,12 @@ class gate(Exchange, ImplicitAPI):
3022
3347
  def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3023
3348
  """
3024
3349
  fetch all the trades made from a single order
3025
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history
3026
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-2
3027
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-3
3028
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-4
3350
+
3351
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history
3352
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-2
3353
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-3
3354
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-4
3355
+
3029
3356
  :param str id: order id
3030
3357
  :param str symbol: unified market symbol
3031
3358
  :param int [since]: the earliest time in ms to fetch trades for
@@ -3061,10 +3388,12 @@ class gate(Exchange, ImplicitAPI):
3061
3388
  def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
3062
3389
  """
3063
3390
  Fetch personal trading history
3064
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history
3065
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-2
3066
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-3
3067
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-4
3391
+
3392
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history
3393
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-2
3394
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-3
3395
+ https://www.gate.io/docs/developers/apiv4/en/#list-personal-trading-history-4
3396
+
3068
3397
  :param str symbol: unified market symbol
3069
3398
  :param int [since]: the earliest time in ms to fetch trades for
3070
3399
  :param int [limit]: the maximum number of trades structures to retrieve
@@ -3078,20 +3407,22 @@ class gate(Exchange, ImplicitAPI):
3078
3407
  :param int [params.offset]: *contract only* list offset, starting from 0
3079
3408
  :param str [params.last_id]: *contract only* specify list staring point using the id of last record in previous list-query results
3080
3409
  :param int [params.count_total]: *contract only* whether to return total number matched, default to 0(no return)
3081
- :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)
3410
+ :param bool [params.unifiedAccount]: set to True for fetching trades in a unified account
3411
+ :param bool [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)
3082
3412
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
3083
3413
  """
3084
3414
  self.load_markets()
3415
+ self.load_unified_status()
3085
3416
  paginate = False
3086
3417
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
3087
3418
  if paginate:
3088
3419
  return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
3089
3420
  type = None
3090
3421
  marginMode = None
3091
- request = {}
3422
+ request: dict = {}
3092
3423
  market = self.market(symbol) if (symbol is not None) else None
3093
- until = self.safe_integer_2(params, 'until', 'till')
3094
- params = self.omit(params, ['until', 'till'])
3424
+ until = self.safe_integer(params, 'until')
3425
+ params = self.omit(params, ['until'])
3095
3426
  type, params = self.handle_market_type_and_params('fetchMyTrades', market, params)
3096
3427
  contract = (type == 'swap') or (type == 'future') or (type == 'option')
3097
3428
  if contract:
@@ -3100,7 +3431,7 @@ class gate(Exchange, ImplicitAPI):
3100
3431
  params = self.omit(params, 'order_id')
3101
3432
  else:
3102
3433
  if market is not None:
3103
- request['currency_pair'] = market['id'] # Should always be set for non-stop
3434
+ request['currency_pair'] = market['id'] # Should always be set for non-trigger
3104
3435
  marginMode, params = self.get_margin_mode(False, params)
3105
3436
  request['account'] = marginMode
3106
3437
  if limit is not None:
@@ -3186,7 +3517,7 @@ class gate(Exchange, ImplicitAPI):
3186
3517
  #
3187
3518
  return self.parse_trades(response, market, since, limit)
3188
3519
 
3189
- def parse_trade(self, trade, market: Market = None) -> Trade:
3520
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
3190
3521
  #
3191
3522
  # public
3192
3523
  #
@@ -3288,8 +3619,8 @@ class gate(Exchange, ImplicitAPI):
3288
3619
  side = self.safe_string_2(trade, 'side', 'type', contractSide)
3289
3620
  orderId = self.safe_string(trade, 'order_id')
3290
3621
  feeAmount = self.safe_string(trade, 'fee')
3291
- gtFee = self.safe_string(trade, 'gt_fee')
3292
- pointFee = self.safe_string(trade, 'point_fee')
3622
+ gtFee = self.omit_zero(self.safe_string(trade, 'gt_fee'))
3623
+ pointFee = self.omit_zero(self.safe_string(trade, 'point_fee'))
3293
3624
  fees = []
3294
3625
  if feeAmount is not None:
3295
3626
  feeCurrencyId = self.safe_string(trade, 'fee_currency')
@@ -3331,12 +3662,14 @@ class gate(Exchange, ImplicitAPI):
3331
3662
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3332
3663
  """
3333
3664
  fetch all deposits made to an account
3334
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-deposit-records
3665
+
3666
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-deposit-records
3667
+
3335
3668
  :param str code: unified currency code
3336
3669
  :param int [since]: the earliest time in ms to fetch deposits for
3337
3670
  :param int [limit]: the maximum number of deposits structures to retrieve
3338
- :param int [params.until]: end time in ms
3339
3671
  :param dict [params]: extra parameters specific to the exchange API endpoint
3672
+ :param int [params.until]: end time in ms
3340
3673
  :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)
3341
3674
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3342
3675
  """
@@ -3345,11 +3678,11 @@ class gate(Exchange, ImplicitAPI):
3345
3678
  paginate, params = self.handle_option_and_params(params, 'fetchDeposits', 'paginate')
3346
3679
  if paginate:
3347
3680
  return self.fetch_paginated_call_dynamic('fetchDeposits', code, since, limit, params)
3348
- request = {}
3681
+ request: dict = {}
3349
3682
  currency = None
3350
3683
  if code is not None:
3351
3684
  currency = self.currency(code)
3352
- request['currency'] = currency['id']
3685
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
3353
3686
  if limit is not None:
3354
3687
  request['limit'] = limit
3355
3688
  if since is not None:
@@ -3363,7 +3696,9 @@ class gate(Exchange, ImplicitAPI):
3363
3696
  def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3364
3697
  """
3365
3698
  fetch all withdrawals made from an account
3366
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-records
3699
+
3700
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-withdrawal-records
3701
+
3367
3702
  :param str code: unified currency code
3368
3703
  :param int [since]: the earliest time in ms to fetch withdrawals for
3369
3704
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -3377,11 +3712,11 @@ class gate(Exchange, ImplicitAPI):
3377
3712
  paginate, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'paginate')
3378
3713
  if paginate:
3379
3714
  return self.fetch_paginated_call_dynamic('fetchWithdrawals', code, since, limit, params)
3380
- request = {}
3715
+ request: dict = {}
3381
3716
  currency = None
3382
3717
  if code is not None:
3383
3718
  currency = self.currency(code)
3384
- request['currency'] = currency['id']
3719
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
3385
3720
  if limit is not None:
3386
3721
  request['limit'] = limit
3387
3722
  if since is not None:
@@ -3392,10 +3727,12 @@ class gate(Exchange, ImplicitAPI):
3392
3727
  response = self.privateWalletGetWithdrawals(self.extend(request, params))
3393
3728
  return self.parse_transactions(response, currency)
3394
3729
 
3395
- def withdraw(self, code: str, amount: float, address, tag=None, params={}):
3730
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
3396
3731
  """
3397
3732
  make a withdrawal
3398
- :see: https://www.gate.io/docs/developers/apiv4/en/#withdraw
3733
+
3734
+ https://www.gate.io/docs/developers/apiv4/en/#withdraw
3735
+
3399
3736
  :param str code: unified currency code
3400
3737
  :param float amount: the amount to withdraw
3401
3738
  :param str address: the address to withdraw to
@@ -3407,8 +3744,8 @@ class gate(Exchange, ImplicitAPI):
3407
3744
  self.check_address(address)
3408
3745
  self.load_markets()
3409
3746
  currency = self.currency(code)
3410
- request = {
3411
- 'currency': currency['id'],
3747
+ request: dict = {
3748
+ 'currency': currency['id'], # todo: currencies have network-junctions
3412
3749
  'address': address,
3413
3750
  'amount': self.currency_to_precision(code, amount),
3414
3751
  }
@@ -3421,7 +3758,7 @@ class gate(Exchange, ImplicitAPI):
3421
3758
  request['chain'] = network
3422
3759
  params = self.omit(params, 'network')
3423
3760
  else:
3424
- request['chain'] = currency['id']
3761
+ request['chain'] = currency['id'] # todo: currencies have network-junctions
3425
3762
  response = self.privateWithdrawalsPostWithdrawals(self.extend(request, params))
3426
3763
  #
3427
3764
  # {
@@ -3434,8 +3771,8 @@ class gate(Exchange, ImplicitAPI):
3434
3771
  #
3435
3772
  return self.parse_transaction(response, currency)
3436
3773
 
3437
- def parse_transaction_status(self, status):
3438
- statuses = {
3774
+ def parse_transaction_status(self, status: Str):
3775
+ statuses: dict = {
3439
3776
  'PEND': 'pending',
3440
3777
  'REQUEST': 'pending',
3441
3778
  'DMOVE': 'pending',
@@ -3453,40 +3790,69 @@ class gate(Exchange, ImplicitAPI):
3453
3790
  return self.safe_string(statuses, status, status)
3454
3791
 
3455
3792
  def parse_transaction_type(self, type):
3456
- types = {
3793
+ types: dict = {
3457
3794
  'd': 'deposit',
3458
3795
  'w': 'withdrawal',
3459
3796
  }
3460
3797
  return self.safe_string(types, type, type)
3461
3798
 
3462
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
3799
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
3463
3800
  #
3464
- # deposits
3801
+ # fetchDeposits
3465
3802
  #
3466
- # {
3467
- # "id": "d33361395",
3468
- # "currency": "USDT_TRX",
3469
- # "address": "TErdnxenuLtXfnMafLbfappYdHtnXQ5U4z",
3470
- # "amount": "100",
3471
- # "txid": "ae9374de34e558562fe18cbb1bf9ab4d9eb8aa7669d65541c9fa2a532c1474a0",
3472
- # "timestamp": "1626345819",
3473
- # "status": "DONE",
3474
- # "memo": ""
3475
- # }
3803
+ # {
3804
+ # "id": "d33361395",
3805
+ # "currency": "USDT_TRX",
3806
+ # "address": "TErdnxenuLtXfnMafLbfappYdHtnXQ5U4z",
3807
+ # "amount": "100",
3808
+ # "txid": "ae9374de34e558562fe18cbb1bf9ab4d9eb8aa7669d65541c9fa2a532c1474a0",
3809
+ # "timestamp": "1626345819",
3810
+ # "status": "DONE",
3811
+ # "memo": ""
3812
+ # }
3476
3813
  #
3477
3814
  # withdraw
3478
3815
  #
3479
- # {
3480
- # "id": "w13389675",
3481
- # "currency": "USDT",
3482
- # "amount": "50",
3483
- # "address": "TUu2rLFrmzUodiWfYki7QCNtv1akL682p1",
3484
- # "memo": null
3485
- # }
3816
+ # {
3817
+ # "id":"w64413318",
3818
+ # "currency":"usdt",
3819
+ # "amount":"10150",
3820
+ # "address":"0x0ab891497116f7f5532a4c2f4f7b1784488628e1",
3821
+ # "memo":null,
3822
+ # "status":"REQUEST",
3823
+ # "chain":"eth",
3824
+ # "withdraw_order_id":"",
3825
+ # "fee_amount":"4.15000000"
3826
+ # }
3827
+ #
3828
+ # fetchWithdrawals
3829
+ #
3830
+ # {
3831
+ # "id": "210496",
3832
+ # "timestamp": "1542000000",
3833
+ # "withdraw_order_id": "order_123456",
3834
+ # "currency": "USDT",
3835
+ # "address": "1HkxtBAMrA3tP5ENnYY2CZortjZvFDH5Cs",
3836
+ # "txid": "128988928203223323290",
3837
+ # "block_number": "41575382",
3838
+ # "amount": "222.61",
3839
+ # "fee": "0.01",
3840
+ # "memo": "",
3841
+ # "status": "DONE",
3842
+ # "chain": "TRX"
3843
+ # }
3844
+ #
3845
+ # {
3846
+ # "id": "w13389675",
3847
+ # "currency": "USDT",
3848
+ # "amount": "50",
3849
+ # "address": "TUu2rLFrmzUodiWfYki7QCNtv1akL682p1",
3850
+ # "memo": null
3851
+ # }
3486
3852
  #
3487
3853
  # {
3488
3854
  # "currency":"usdt",
3489
- # "address":"0x01b0A9b7b4CdE774AF0f3E47CB4f1c2CCdBa0806",
3855
+ # "address":"0x01c0A9b7b4CdE774AF0f3E47CB4f1c2CCdBa0806",
3490
3856
  # "amount":"1880",
3491
3857
  # "chain":"eth"
3492
3858
  # }
@@ -3501,7 +3867,7 @@ class gate(Exchange, ImplicitAPI):
3501
3867
  amountString = Precise.string_abs(amountString)
3502
3868
  else:
3503
3869
  type = self.parse_transaction_type(id[0])
3504
- feeCostString = self.safe_string(transaction, 'fee')
3870
+ feeCostString = self.safe_string_2(transaction, 'fee', 'fee_amount')
3505
3871
  if type == 'withdrawal':
3506
3872
  amountString = Precise.string_sub(amountString, feeCostString)
3507
3873
  networkId = self.safe_string_upper(transaction, 'chain')
@@ -3542,20 +3908,22 @@ class gate(Exchange, ImplicitAPI):
3542
3908
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3543
3909
  """
3544
3910
  Create an order on the exchange
3545
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-an-order
3546
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order
3547
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order
3548
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order-2
3549
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order-2
3550
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order-3
3551
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-an-options-order
3911
+
3912
+ https://www.gate.io/docs/developers/apiv4/en/#create-an-order
3913
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order
3914
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order
3915
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order-2
3916
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order-2
3917
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-price-triggered-order-3
3918
+ https://www.gate.io/docs/developers/apiv4/en/#create-an-options-order
3919
+
3552
3920
  :param str symbol: Unified CCXT market symbol
3553
3921
  :param str type: 'limit' or 'market' *"market" is contract only*
3554
3922
  :param str side: 'buy' or 'sell'
3555
3923
  :param float amount: the amount of currency to trade
3556
- :param float [price]: *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
3924
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
3557
3925
  :param dict [params]: extra parameters specific to the exchange API endpoint
3558
- :param float [params.stopPrice]: The price at which a trigger order is triggered at
3926
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
3559
3927
  :param str [params.timeInForce]: "GTC", "IOC", or "PO"
3560
3928
  :param float [params.stopLossPrice]: The price at which a stop loss order is triggered at
3561
3929
  :param float [params.takeProfitPrice]: The price at which a take profit order is triggered at
@@ -3570,9 +3938,11 @@ class gate(Exchange, ImplicitAPI):
3570
3938
  :param bool [params.auto_size]: *contract only* Set side to close dual-mode position, close_long closes the long side, while close_short the short one, size also needs to be set to 0
3571
3939
  :param int [params.price_type]: *contract only* 0 latest deal price, 1 mark price, 2 index price
3572
3940
  :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
3941
+ :param bool [params.unifiedAccount]: set to True for creating an order in the unified account
3573
3942
  :returns dict|None: `An order structure <https://docs.ccxt.com/#/?id=order-structure>`
3574
3943
  """
3575
3944
  self.load_markets()
3945
+ self.load_unified_status()
3576
3946
  market = self.market(symbol)
3577
3947
  trigger = self.safe_value(params, 'trigger')
3578
3948
  triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
@@ -3580,8 +3950,8 @@ class gate(Exchange, ImplicitAPI):
3580
3950
  takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
3581
3951
  isStopLossOrder = stopLossPrice is not None
3582
3952
  isTakeProfitOrder = takeProfitPrice is not None
3583
- isStopOrder = isStopLossOrder or isTakeProfitOrder
3584
- nonTriggerOrder = not isStopOrder and (trigger is None)
3953
+ isTpsl = isStopLossOrder or isTakeProfitOrder
3954
+ nonTriggerOrder = not isTpsl and (trigger is None)
3585
3955
  orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
3586
3956
  response = None
3587
3957
  if market['spot'] or market['margin']:
@@ -3667,17 +4037,14 @@ class gate(Exchange, ImplicitAPI):
3667
4037
  #
3668
4038
  return self.parse_order(response, market)
3669
4039
 
3670
- def create_orders(self, orders: List[OrderRequest], params={}):
3671
- """
3672
- create a list of trade orders
3673
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
3674
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-batch-of-orders
3675
- :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
3676
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3677
- """
3678
- self.load_markets()
4040
+ def create_orders_request(self, orders: List[OrderRequest], params={}):
3679
4041
  ordersRequests = []
3680
4042
  orderSymbols = []
4043
+ ordersLength = len(orders)
4044
+ if ordersLength == 0:
4045
+ raise BadRequest(self.id + ' createOrders() requires at least one order')
4046
+ if ordersLength > 10:
4047
+ raise BadRequest(self.id + ' createOrders() accepts a maximum of 10 orders at a time')
3681
4048
  for i in range(0, len(orders)):
3682
4049
  rawOrder = orders[i]
3683
4050
  marketId = self.safe_string(rawOrder, 'symbol')
@@ -3698,6 +4065,25 @@ class gate(Exchange, ImplicitAPI):
3698
4065
  market = self.market(symbols[0])
3699
4066
  if market['future'] or market['option']:
3700
4067
  raise NotSupported(self.id + ' createOrders() does not support futures or options markets')
4068
+ return ordersRequests
4069
+
4070
+ def create_orders(self, orders: List[OrderRequest], params={}):
4071
+ """
4072
+ create a list of trade orders
4073
+
4074
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
4075
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-batch-of-orders
4076
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-batch-of-futures-orders
4077
+
4078
+ :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
4079
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4080
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4081
+ """
4082
+ self.load_markets()
4083
+ self.load_unified_status()
4084
+ ordersRequests = self.create_orders_request(orders, params)
4085
+ firstOrder = orders[0]
4086
+ market = self.market(firstOrder['symbol'])
3701
4087
  response = None
3702
4088
  if market['spot']:
3703
4089
  response = self.privateSpotPostBatchOrders(ordersRequests)
@@ -3714,7 +4100,7 @@ class gate(Exchange, ImplicitAPI):
3714
4100
  takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
3715
4101
  isStopLossOrder = stopLossPrice is not None
3716
4102
  isTakeProfitOrder = takeProfitPrice is not None
3717
- isStopOrder = isStopLossOrder or isTakeProfitOrder
4103
+ isTpsl = isStopLossOrder or isTakeProfitOrder
3718
4104
  if isStopLossOrder and isTakeProfitOrder:
3719
4105
  raise ExchangeError(self.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined')
3720
4106
  reduceOnly = self.safe_value(params, 'reduceOnly')
@@ -3750,7 +4136,7 @@ class gate(Exchange, ImplicitAPI):
3750
4136
  signedAmount = Precise.string_neg(amountToPrecision) if (side == 'sell') else amountToPrecision
3751
4137
  amount = int(signedAmount)
3752
4138
  request = None
3753
- nonTriggerOrder = not isStopOrder and (trigger is None)
4139
+ nonTriggerOrder = not isTpsl and (trigger is None)
3754
4140
  if nonTriggerOrder:
3755
4141
  if contract:
3756
4142
  # contract order
@@ -3767,9 +4153,9 @@ class gate(Exchange, ImplicitAPI):
3767
4153
  if not market['option']:
3768
4154
  request['settle'] = market['settleId'] # filled in prepareRequest above
3769
4155
  if isMarketOrder:
3770
- request['price'] = price # set to 0 for market orders
4156
+ request['price'] = '0' # set to 0 for market orders
3771
4157
  else:
3772
- request['price'] = self.price_to_precision(symbol, price)
4158
+ request['price'] = '0' if (price == 0) else self.price_to_precision(symbol, price)
3773
4159
  if reduceOnly is not None:
3774
4160
  request['reduce_only'] = reduceOnly
3775
4161
  if timeInForce is not None:
@@ -3782,7 +4168,7 @@ class gate(Exchange, ImplicitAPI):
3782
4168
  # 'text': clientOrderId, # 't-abcdef1234567890',
3783
4169
  'currency_pair': market['id'], # filled in prepareRequest above
3784
4170
  'type': type,
3785
- 'account': marginMode, # 'spot', 'margin', 'cross_margin'
4171
+ 'account': marginMode, # spot, margin, cross_margin, unified
3786
4172
  'side': side,
3787
4173
  # 'time_in_force': 'gtc', # gtc, ioc, poc PendingOrCancelled == postOnly order
3788
4174
  # 'iceberg': 0, # amount to display for the iceberg order, null or 0 for normal orders, set to -1 to hide the order completely
@@ -3840,7 +4226,7 @@ class gate(Exchange, ImplicitAPI):
3840
4226
  'initial': {
3841
4227
  'contract': market['id'],
3842
4228
  'size': amount, # positive = buy, negative = sell, set to 0 to close the position
3843
- 'price': self.price_to_precision(symbol, price), # set to 0 to use market price
4229
+ # 'price': '0' if (price == 0) else self.price_to_precision(symbol, price), # set to 0 to use market price
3844
4230
  # 'close': False, # set to True if trying to close the position
3845
4231
  # 'tif': 'gtc', # gtc, ioc, if using market price, only ioc is supported
3846
4232
  # 'text': clientOrderId, # web, api, app
@@ -3848,6 +4234,10 @@ class gate(Exchange, ImplicitAPI):
3848
4234
  },
3849
4235
  'settle': market['settleId'],
3850
4236
  }
4237
+ if type == 'market':
4238
+ request['initial']['price'] = '0'
4239
+ else:
4240
+ request['initial']['price'] = '0' if (price == 0) else self.price_to_precision(symbol, price)
3851
4241
  if trigger is None:
3852
4242
  rule = None
3853
4243
  triggerOrderPrice = None
@@ -3915,57 +4305,82 @@ class gate(Exchange, ImplicitAPI):
3915
4305
  def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
3916
4306
  """
3917
4307
  create a market buy order by providing the symbol and cost
3918
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-an-order
4308
+
4309
+ https://www.gate.io/docs/developers/apiv4/en/#create-an-order
4310
+
3919
4311
  :param str symbol: unified symbol of the market to create an order in
3920
4312
  :param float cost: how much you want to trade in units of the quote currency
3921
4313
  :param dict [params]: extra parameters specific to the exchange API endpoint
4314
+ :param bool [params.unifiedAccount]: set to True for creating a unified account order
3922
4315
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3923
4316
  """
3924
4317
  self.load_markets()
4318
+ self.load_unified_status()
3925
4319
  market = self.market(symbol)
3926
4320
  if not market['spot']:
3927
4321
  raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
3928
4322
  params['createMarketBuyOrderRequiresPrice'] = False
3929
4323
  return self.create_order(symbol, 'market', 'buy', cost, None, params)
3930
4324
 
3931
- def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
3932
- """
3933
- edit a trade order, gate currently only supports the modification of the price or amount fields
3934
- :see: https://www.gate.io/docs/developers/apiv4/en/#amend-an-order
3935
- :see: https://www.gate.io/docs/developers/apiv4/en/#amend-an-order-2
3936
- :param str id: order id
3937
- :param str symbol: unified symbol of the market to create an order in
3938
- :param str type: 'market' or 'limit'
3939
- :param str side: 'buy' or 'sell'
3940
- :param float amount: how much of the currency you want to trade in units of the base currency
3941
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
3942
- :param dict [params]: extra parameters specific to the exchange API endpoint
3943
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3944
- """
3945
- self.load_markets()
4325
+ def edit_order_request(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
3946
4326
  market = self.market(symbol)
3947
- marketType, query = self.handle_market_type_and_params('editOrder', market, params)
4327
+ marketType = None
4328
+ marketType, params = self.handle_market_type_and_params('editOrder', market, params)
3948
4329
  account = self.convert_type_to_account(marketType)
4330
+ isUnifiedAccount = False
4331
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'editOrder', 'unifiedAccount')
4332
+ if isUnifiedAccount:
4333
+ account = 'unified'
3949
4334
  isLimitOrder = (type == 'limit')
3950
4335
  if account == 'spot':
3951
4336
  if not isLimitOrder:
3952
4337
  # exchange doesn't have market orders for spot
3953
4338
  raise InvalidOrder(self.id + ' editOrder() does not support ' + type + ' orders for ' + marketType + ' markets')
3954
- request = {
3955
- 'order_id': id,
4339
+ request: dict = {
4340
+ 'order_id': str(id),
3956
4341
  'currency_pair': market['id'],
3957
4342
  'account': account,
3958
4343
  }
3959
4344
  if amount is not None:
3960
- request['amount'] = self.amount_to_precision(symbol, amount)
4345
+ if market['spot']:
4346
+ request['amount'] = self.amount_to_precision(symbol, amount)
4347
+ else:
4348
+ if side == 'sell':
4349
+ request['size'] = self.parse_to_numeric(Precise.string_neg(self.amount_to_precision(symbol, amount)))
4350
+ else:
4351
+ request['size'] = self.parse_to_numeric(self.amount_to_precision(symbol, amount))
3961
4352
  if price is not None:
3962
4353
  request['price'] = self.price_to_precision(symbol, price)
4354
+ if not market['spot']:
4355
+ request['settle'] = market['settleId']
4356
+ return self.extend(request, params)
4357
+
4358
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
4359
+ """
4360
+ edit a trade order, gate currently only supports the modification of the price or amount fields
4361
+
4362
+ https://www.gate.io/docs/developers/apiv4/en/#amend-an-order
4363
+ https://www.gate.io/docs/developers/apiv4/en/#amend-an-order-2
4364
+
4365
+ :param str id: order id
4366
+ :param str symbol: unified symbol of the market to create an order in
4367
+ :param str type: 'market' or 'limit'
4368
+ :param str side: 'buy' or 'sell'
4369
+ :param float amount: how much of the currency you want to trade in units of the base currency
4370
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
4371
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4372
+ :param bool [params.unifiedAccount]: set to True for editing an order in a unified account
4373
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4374
+ """
4375
+ self.load_markets()
4376
+ self.load_unified_status()
4377
+ market = self.market(symbol)
4378
+ extendedRequest = self.edit_order_request(id, symbol, type, side, amount, price, params)
3963
4379
  response = None
3964
4380
  if market['spot']:
3965
- response = self.privateSpotPatchOrdersOrderId(self.extend(request, query))
4381
+ response = self.privateSpotPatchOrdersOrderId(extendedRequest)
3966
4382
  else:
3967
- request['settle'] = market['settleId']
3968
- response = self.privateFuturesPutSettleOrdersOrderId(self.extend(request, query))
4383
+ response = self.privateFuturesPutSettleOrdersOrderId(extendedRequest)
3969
4384
  #
3970
4385
  # {
3971
4386
  # "id": "243233276443",
@@ -3999,8 +4414,8 @@ class gate(Exchange, ImplicitAPI):
3999
4414
  #
4000
4415
  return self.parse_order(response, market)
4001
4416
 
4002
- def parse_order_status(self, status):
4003
- statuses = {
4417
+ def parse_order_status(self, status: Str):
4418
+ statuses: dict = {
4004
4419
  'open': 'open',
4005
4420
  '_new': 'open',
4006
4421
  'filled': 'closed',
@@ -4015,7 +4430,7 @@ class gate(Exchange, ImplicitAPI):
4015
4430
  }
4016
4431
  return self.safe_string(statuses, status, status)
4017
4432
 
4018
- def parse_order(self, order, market: Market = None) -> Order:
4433
+ def parse_order(self, order: dict, market: Market = None) -> Order:
4019
4434
  #
4020
4435
  # SPOT
4021
4436
  # createOrder/cancelOrder/fetchOrder/editOrder
@@ -4157,6 +4572,8 @@ class gate(Exchange, ImplicitAPI):
4157
4572
  # "message": "Not enough balance"
4158
4573
  # }
4159
4574
  #
4575
+ # {"user_id":10406147,"id":"id","succeeded":false,"message":"INVALID_PROTOCOL","label":"INVALID_PROTOCOL"}
4576
+ #
4160
4577
  succeeded = self.safe_bool(order, 'succeeded', True)
4161
4578
  if not succeeded:
4162
4579
  # cancelOrders response
@@ -4164,6 +4581,7 @@ class gate(Exchange, ImplicitAPI):
4164
4581
  'clientOrderId': self.safe_string(order, 'text'),
4165
4582
  'info': order,
4166
4583
  'status': 'rejected',
4584
+ 'id': self.safe_string(order, 'id'),
4167
4585
  })
4168
4586
  put = self.safe_value_2(order, 'put', 'initial', {})
4169
4587
  trigger = self.safe_value(order, 'trigger', {})
@@ -4208,19 +4626,19 @@ class gate(Exchange, ImplicitAPI):
4208
4626
  # Everything below self(above return) is related to fees
4209
4627
  fees = []
4210
4628
  gtFee = self.safe_string(order, 'gt_fee')
4211
- if gtFee:
4629
+ if gtFee is not None:
4212
4630
  fees.append({
4213
4631
  'currency': 'GT',
4214
4632
  'cost': gtFee,
4215
4633
  })
4216
4634
  fee = self.safe_string(order, 'fee')
4217
- if fee:
4635
+ if fee is not None:
4218
4636
  fees.append({
4219
4637
  'currency': self.safe_currency_code(self.safe_string(order, 'fee_currency')),
4220
4638
  'cost': fee,
4221
4639
  })
4222
4640
  rebate = self.safe_string(order, 'rebated_fee')
4223
- if rebate:
4641
+ if rebate is not None:
4224
4642
  fees.append({
4225
4643
  'currency': self.safe_currency_code(self.safe_string(order, 'rebated_fee_currency')),
4226
4644
  'cost': Precise.string_neg(rebate),
@@ -4253,7 +4671,6 @@ class gate(Exchange, ImplicitAPI):
4253
4671
  'reduceOnly': self.safe_value(order, 'is_reduce_only'),
4254
4672
  'side': side,
4255
4673
  'price': price,
4256
- 'stopPrice': triggerPrice,
4257
4674
  'triggerPrice': triggerPrice,
4258
4675
  'average': average,
4259
4676
  'amount': Precise.string_abs(amount),
@@ -4266,50 +4683,62 @@ class gate(Exchange, ImplicitAPI):
4266
4683
  'info': order,
4267
4684
  }, market)
4268
4685
 
4686
+ def fetch_order_request(self, id: str, symbol: Str = None, params={}):
4687
+ market = None if (symbol is None) else self.market(symbol)
4688
+ trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
4689
+ params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
4690
+ clientOrderId = self.safe_string_2(params, 'text', 'clientOrderId')
4691
+ orderId = id
4692
+ if clientOrderId is not None:
4693
+ params = self.omit(params, ['text', 'clientOrderId'])
4694
+ if clientOrderId[0] != 't':
4695
+ clientOrderId = 't-' + clientOrderId
4696
+ orderId = clientOrderId
4697
+ type, query = self.handle_market_type_and_params('fetchOrder', market, params)
4698
+ contract = (type == 'swap') or (type == 'future') or (type == 'option')
4699
+ request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market, trigger, query)
4700
+ request['order_id'] = str(orderId)
4701
+ return [request, requestParams]
4702
+
4269
4703
  def fetch_order(self, id: str, symbol: Str = None, params={}):
4270
4704
  """
4271
4705
  Retrieves information on an order
4272
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order
4273
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
4274
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-3
4275
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-4
4706
+
4707
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order
4708
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
4709
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-3
4710
+ https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-4
4711
+
4276
4712
  :param str id: Order id
4277
4713
  :param str symbol: Unified market symbol, *required for spot and margin*
4278
4714
  :param dict [params]: Parameters specified by the exchange api
4279
- :param bool [params.stop]: True if the order being fetched is a trigger order
4715
+ :param bool [params.trigger]: True if the order being fetched is a trigger order
4280
4716
  :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
4281
4717
  :param str [params.type]: 'spot', 'swap', or 'future', if not provided self.options['defaultMarginMode'] is used
4282
4718
  :param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - market settle currency is used if symbol is not None, default="usdt" for swap and "btc" for future
4719
+ :param bool [params.unifiedAccount]: set to True for fetching a unified account order
4283
4720
  :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4284
4721
  """
4285
4722
  self.load_markets()
4286
- stop = self.safe_value_2(params, 'is_stop_order', 'stop', False)
4287
- params = self.omit(params, ['is_stop_order', 'stop'])
4288
- clientOrderId = self.safe_string_2(params, 'text', 'clientOrderId')
4289
- orderId = id
4290
- if clientOrderId is not None:
4291
- params = self.omit(params, ['text', 'clientOrderId'])
4292
- if clientOrderId[0] != 't':
4293
- clientOrderId = 't-' + clientOrderId
4294
- orderId = clientOrderId
4723
+ self.load_unified_status()
4295
4724
  market = None if (symbol is None) else self.market(symbol)
4296
- type, query = self.handle_market_type_and_params('fetchOrder', market, params)
4297
- contract = (type == 'swap') or (type == 'future') or (type == 'option')
4298
- request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market, stop, query)
4299
- request['order_id'] = orderId
4725
+ result = self.handle_market_type_and_params('fetchOrder', market, params)
4726
+ type = self.safe_string(result, 0)
4727
+ trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
4728
+ request, requestParams = self.fetch_order_request(id, symbol, params)
4300
4729
  response = None
4301
4730
  if type == 'spot' or type == 'margin':
4302
- if stop:
4731
+ if trigger:
4303
4732
  response = self.privateSpotGetPriceOrdersOrderId(self.extend(request, requestParams))
4304
4733
  else:
4305
4734
  response = self.privateSpotGetOrdersOrderId(self.extend(request, requestParams))
4306
4735
  elif type == 'swap':
4307
- if stop:
4736
+ if trigger:
4308
4737
  response = self.privateFuturesGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
4309
4738
  else:
4310
4739
  response = self.privateFuturesGetSettleOrdersOrderId(self.extend(request, requestParams))
4311
4740
  elif type == 'future':
4312
- if stop:
4741
+ if trigger:
4313
4742
  response = self.privateDeliveryGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
4314
4743
  else:
4315
4744
  response = self.privateDeliveryGetSettleOrdersOrderId(self.extend(request, requestParams))
@@ -4322,14 +4751,18 @@ class gate(Exchange, ImplicitAPI):
4322
4751
  def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
4323
4752
  """
4324
4753
  fetch all unfilled currently open orders
4325
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-open-orders
4754
+
4755
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-open-orders
4756
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-running-auto-order-list
4757
+
4326
4758
  :param str symbol: unified market symbol
4327
4759
  :param int [since]: the earliest time in ms to fetch open orders for
4328
4760
  :param int [limit]: the maximum number of open orders structures to retrieve
4329
4761
  :param dict [params]: extra parameters specific to the exchange API endpoint
4330
- :param bool [params.stop]: True for fetching stop orders
4762
+ :param bool [params.trigger]: True for fetching trigger orders
4331
4763
  :param str [params.type]: spot, margin, swap or future, if not provided self.options['defaultType'] is used
4332
4764
  :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for type='margin', if not provided self.options['defaultMarginMode'] is used
4765
+ :param bool [params.unifiedAccount]: set to True for fetching unified account orders
4333
4766
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4334
4767
  """
4335
4768
  return self.fetch_orders_by_status('open', symbol, since, limit, params)
@@ -4337,58 +4770,115 @@ class gate(Exchange, ImplicitAPI):
4337
4770
  def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
4338
4771
  """
4339
4772
  fetches information on multiple closed orders made by the user
4340
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-orders
4341
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-running-auto-order-list
4342
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-orders
4343
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-auto-orders
4344
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-futures-orders-2
4345
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-auto-orders-2
4346
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-options-orders
4773
+
4774
+ https://www.gate.io/docs/developers/apiv4/en/#list-orders
4775
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-running-auto-order-list
4776
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-orders
4777
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-auto-orders
4778
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-orders-2
4779
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-auto-orders-2
4780
+ https://www.gate.io/docs/developers/apiv4/en/#list-options-orders
4781
+ https://www.gate.io/docs/developers/apiv4/en/#list-futures-orders-by-time-range
4782
+
4347
4783
  :param str symbol: unified market symbol of the market orders were made in
4348
4784
  :param int [since]: the earliest time in ms to fetch orders for
4349
4785
  :param int [limit]: the maximum number of order structures to retrieve
4350
4786
  :param dict [params]: extra parameters specific to the exchange API endpoint
4351
- :param bool [params.stop]: True for fetching stop orders
4787
+ :param bool [params.trigger]: True for fetching trigger orders
4352
4788
  :param str [params.type]: spot, swap or future, if not provided self.options['defaultType'] is used
4353
4789
  :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
4790
+ :param boolean [params.historical]: *swap only* True for using historical endpoint
4791
+ :param bool [params.unifiedAccount]: set to True for fetching unified account orders
4354
4792
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4355
4793
  """
4356
- return self.fetch_orders_by_status('finished', symbol, since, limit, params)
4357
-
4358
- def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4359
4794
  self.load_markets()
4795
+ self.load_unified_status()
4796
+ until = self.safe_integer(params, 'until')
4360
4797
  market = None
4361
4798
  if symbol is not None:
4362
4799
  market = self.market(symbol)
4363
4800
  symbol = market['symbol']
4364
- stop = self.safe_value(params, 'stop')
4365
- params = self.omit(params, 'stop')
4366
- type, query = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
4367
- spot = (type == 'spot') or (type == 'margin')
4368
- request, requestParams = self.multi_order_spot_prepare_request(market, stop, query) if spot else self.prepare_request(market, type, query)
4369
- if status == 'closed':
4370
- status = 'finished'
4371
- request['status'] = status
4372
- if limit is not None:
4373
- request['limit'] = limit
4374
- if since is not None and spot:
4801
+ res = self.handle_market_type_and_params('fetchClosedOrders', market, params)
4802
+ type = self.safe_string(res, 0)
4803
+ useHistorical = False
4804
+ useHistorical, params = self.handle_option_and_params(params, 'fetchClosedOrders', 'historical', False)
4805
+ if not useHistorical and ((since is None and until is None) or (type != 'swap')):
4806
+ return self.fetch_orders_by_status('finished', symbol, since, limit, params)
4807
+ params = self.omit(params, 'type')
4808
+ request = {}
4809
+ request, params = self.prepare_request(market, type, params)
4810
+ if since is not None:
4375
4811
  request['from'] = self.parse_to_int(since / 1000)
4376
- openSpotOrders = spot and (status == 'open') and not stop
4812
+ if until is not None:
4813
+ params = self.omit(params, 'until')
4814
+ request['to'] = self.parse_to_int(until / 1000)
4815
+ if limit is not None:
4816
+ request['limit'] = limit
4817
+ response = self.privateFuturesGetSettleOrdersTimerange(self.extend(request, params))
4818
+ return self.parse_orders(response, market, since, limit)
4819
+
4820
+ def prepare_orders_by_status_request(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4821
+ market = None
4822
+ if symbol is not None:
4823
+ market = self.market(symbol)
4824
+ symbol = market['symbol']
4825
+ trigger: Bool = None
4826
+ trigger, params = self.handle_param_bool_2(params, 'trigger', 'stop')
4827
+ type: Str = None
4828
+ type, params = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
4829
+ spot = (type == 'spot') or (type == 'margin')
4830
+ request: dict = {}
4831
+ request, params = self.multi_order_spot_prepare_request(market, trigger, params) if spot else self.prepare_request(market, type, params)
4832
+ if spot and trigger:
4833
+ request = self.omit(request, 'account')
4834
+ if status == 'closed':
4835
+ status = 'finished'
4836
+ request['status'] = status
4837
+ if limit is not None:
4838
+ request['limit'] = limit
4839
+ if spot:
4840
+ if since is not None:
4841
+ request['from'] = self.parse_to_int(since / 1000)
4842
+ until = self.safe_integer(params, 'until')
4843
+ if until is not None:
4844
+ params = self.omit(params, 'until')
4845
+ request['to'] = self.parse_to_int(until / 1000)
4846
+ lastId, finalParams = self.handle_param_string_2(params, 'lastId', 'last_id')
4847
+ if lastId is not None:
4848
+ request['last_id'] = lastId
4849
+ return [request, finalParams]
4850
+
4851
+ def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4852
+ self.load_markets()
4853
+ self.load_unified_status()
4854
+ market = None
4855
+ if symbol is not None:
4856
+ market = self.market(symbol)
4857
+ symbol = market['symbol']
4858
+ # don't omit here, omits done in prepareOrdersByStatusRequest
4859
+ trigger: Bool = self.safe_bool_2(params, 'trigger', 'stop')
4860
+ res = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
4861
+ type = self.safe_string(res, 0)
4862
+ request, requestParams = self.prepare_orders_by_status_request(status, symbol, since, limit, params)
4863
+ spot = (type == 'spot') or (type == 'margin')
4864
+ openStatus = (status == 'open')
4865
+ openSpotOrders = spot and openStatus and not trigger
4377
4866
  response = None
4378
- if type == 'spot' or type == 'margin':
4379
- if openSpotOrders:
4380
- response = self.privateSpotGetOpenOrders(self.extend(request, requestParams))
4381
- elif stop:
4382
- response = self.privateSpotGetPriceOrders(self.extend(request, requestParams))
4867
+ if spot:
4868
+ if not trigger:
4869
+ if openStatus:
4870
+ response = self.privateSpotGetOpenOrders(self.extend(request, requestParams))
4871
+ else:
4872
+ response = self.privateSpotGetOrders(self.extend(request, requestParams))
4383
4873
  else:
4384
- response = self.privateSpotGetOrders(self.extend(request, requestParams))
4874
+ response = self.privateSpotGetPriceOrders(self.extend(request, requestParams))
4385
4875
  elif type == 'swap':
4386
- if stop:
4876
+ if trigger:
4387
4877
  response = self.privateFuturesGetSettlePriceOrders(self.extend(request, requestParams))
4388
4878
  else:
4389
4879
  response = self.privateFuturesGetSettleOrders(self.extend(request, requestParams))
4390
4880
  elif type == 'future':
4391
- if stop:
4881
+ if trigger:
4392
4882
  response = self.privateDeliveryGetSettlePriceOrders(self.extend(request, requestParams))
4393
4883
  else:
4394
4884
  response = self.privateDeliveryGetSettleOrders(self.extend(request, requestParams))
@@ -4468,7 +4958,7 @@ class gate(Exchange, ImplicitAPI):
4468
4958
  # }
4469
4959
  # ]
4470
4960
  #
4471
- # spot stop
4961
+ # spot trigger
4472
4962
  #
4473
4963
  # [
4474
4964
  # {
@@ -4554,36 +5044,40 @@ class gate(Exchange, ImplicitAPI):
4554
5044
  def cancel_order(self, id: str, symbol: Str = None, params={}):
4555
5045
  """
4556
5046
  Cancels an open order
4557
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order
4558
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-2
4559
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-3
4560
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-4
5047
+
5048
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order
5049
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-2
5050
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-3
5051
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-single-order-4
5052
+
4561
5053
  :param str id: Order id
4562
5054
  :param str symbol: Unified market symbol
4563
5055
  :param dict [params]: Parameters specified by the exchange api
4564
- :param bool [params.stop]: True if the order to be cancelled is a trigger order
5056
+ :param bool [params.trigger]: True if the order to be cancelled is a trigger order
5057
+ :param bool [params.unifiedAccount]: set to True for canceling unified account orders
4565
5058
  :returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4566
5059
  """
4567
5060
  self.load_markets()
5061
+ self.load_unified_status()
4568
5062
  market = None if (symbol is None) else self.market(symbol)
4569
- stop = self.safe_value_2(params, 'is_stop_order', 'stop', False)
4570
- params = self.omit(params, ['is_stop_order', 'stop'])
5063
+ trigger = self.safe_bool_n(params, ['is_stop_order', 'stop', 'trigger'], False)
5064
+ params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
4571
5065
  type, query = self.handle_market_type_and_params('cancelOrder', market, params)
4572
- request, requestParams = self.spot_order_prepare_request(market, stop, query) if (type == 'spot' or type == 'margin') else self.prepare_request(market, type, query)
5066
+ request, requestParams = self.spot_order_prepare_request(market, trigger, query) if (type == 'spot' or type == 'margin') else self.prepare_request(market, type, query)
4573
5067
  request['order_id'] = id
4574
5068
  response = None
4575
5069
  if type == 'spot' or type == 'margin':
4576
- if stop:
5070
+ if trigger:
4577
5071
  response = self.privateSpotDeletePriceOrdersOrderId(self.extend(request, requestParams))
4578
5072
  else:
4579
5073
  response = self.privateSpotDeleteOrdersOrderId(self.extend(request, requestParams))
4580
5074
  elif type == 'swap':
4581
- if stop:
5075
+ if trigger:
4582
5076
  response = self.privateFuturesDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
4583
5077
  else:
4584
5078
  response = self.privateFuturesDeleteSettleOrdersOrderId(self.extend(request, requestParams))
4585
5079
  elif type == 'future':
4586
- if stop:
5080
+ if trigger:
4587
5081
  response = self.privateDeliveryDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
4588
5082
  else:
4589
5083
  response = self.privateDeliveryDeleteSettleOrdersOrderId(self.extend(request, requestParams))
@@ -4674,36 +5168,122 @@ class gate(Exchange, ImplicitAPI):
4674
5168
  #
4675
5169
  return self.parse_order(response, market)
4676
5170
 
5171
+ def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
5172
+ """
5173
+ cancel multiple orders
5174
+
5175
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-batch-of-orders-with-an-id-list
5176
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-batch-of-orders-with-an-id-list-2
5177
+
5178
+ :param str[] ids: order ids
5179
+ :param str symbol: unified symbol of the market the order was made in
5180
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5181
+ :param bool [params.unifiedAccount]: set to True for canceling unified account orders
5182
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5183
+ """
5184
+ self.load_markets()
5185
+ self.load_unified_status()
5186
+ market = None
5187
+ if symbol is not None:
5188
+ market = self.market(symbol)
5189
+ type = None
5190
+ defaultSettle = 'usdt' if (market is None) else market['settle']
5191
+ settle = self.safe_string_lower(params, 'settle', defaultSettle)
5192
+ type, params = self.handle_market_type_and_params('cancelOrders', market, params)
5193
+ isSpot = (type == 'spot')
5194
+ if isSpot and (symbol is None):
5195
+ raise ArgumentsRequired(self.id + ' cancelOrders requires a symbol argument for spot markets')
5196
+ if isSpot:
5197
+ ordersRequests = []
5198
+ for i in range(0, len(ids)):
5199
+ id = ids[i]
5200
+ orderItem: dict = {
5201
+ 'id': id,
5202
+ 'symbol': symbol,
5203
+ }
5204
+ ordersRequests.append(orderItem)
5205
+ return self.cancel_orders_for_symbols(ordersRequests, params)
5206
+ request = {
5207
+ 'settle': settle,
5208
+ }
5209
+ finalList = [request] # hacky but needs to be done here
5210
+ for i in range(0, len(ids)):
5211
+ finalList.append(ids[i])
5212
+ response = self.privateFuturesPostSettleBatchCancelOrders(finalList)
5213
+ return self.parse_orders(response)
5214
+
5215
+ def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
5216
+ """
5217
+ cancel multiple orders for multiple symbols
5218
+
5219
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-a-batch-of-orders-with-an-id-list
5220
+
5221
+ :param CancellationRequest[] orders: list of order ids with symbol, example [{"id": "a", "symbol": "BTC/USDT"}, {"id": "b", "symbol": "ETH/USDT"}]
5222
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5223
+ :param str[] [params.clientOrderIds]: client order ids
5224
+ :param bool [params.unifiedAccount]: set to True for canceling unified account orders
5225
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5226
+ """
5227
+ self.load_markets()
5228
+ self.load_unified_status()
5229
+ ordersRequests = []
5230
+ for i in range(0, len(orders)):
5231
+ order = orders[i]
5232
+ symbol = self.safe_string(order, 'symbol')
5233
+ market = self.market(symbol)
5234
+ if not market['spot']:
5235
+ raise NotSupported(self.id + ' cancelOrdersForSymbols() supports only spot markets')
5236
+ id = self.safe_string(order, 'id')
5237
+ orderItem: dict = {
5238
+ 'id': id,
5239
+ 'currency_pair': market['id'],
5240
+ }
5241
+ ordersRequests.append(orderItem)
5242
+ response = self.privateSpotPostCancelBatchOrders(ordersRequests)
5243
+ #
5244
+ # [
5245
+ # {
5246
+ # "currency_pair": "BTC_USDT",
5247
+ # "id": "123456"
5248
+ # }
5249
+ # ]
5250
+ #
5251
+ return self.parse_orders(response)
5252
+
4677
5253
  def cancel_all_orders(self, symbol: Str = None, params={}):
4678
5254
  """
4679
5255
  cancel all open orders
4680
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-in-specified-currency-pair
4681
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched
4682
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched-2
4683
- :see: https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched-3
5256
+
5257
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-in-specified-currency-pair
5258
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched
5259
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched-2
5260
+ https://www.gate.io/docs/developers/apiv4/en/#cancel-all-open-orders-matched-3
5261
+
4684
5262
  :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
4685
5263
  :param dict [params]: extra parameters specific to the exchange API endpoint
5264
+ :param bool [params.unifiedAccount]: set to True for canceling unified account orders
4686
5265
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4687
5266
  """
4688
5267
  self.load_markets()
5268
+ self.load_unified_status()
4689
5269
  market = None if (symbol is None) else self.market(symbol)
4690
- stop = self.safe_value(params, 'stop')
4691
- params = self.omit(params, 'stop')
5270
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
5271
+ params = self.omit(params, ['stop', 'trigger'])
4692
5272
  type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
4693
- request, requestParams = self.multi_order_spot_prepare_request(market, stop, query) if (type == 'spot') else self.prepare_request(market, type, query)
5273
+ request, requestParams = self.multi_order_spot_prepare_request(market, trigger, query) if (type == 'spot') else self.prepare_request(market, type, query)
4694
5274
  response = None
4695
5275
  if type == 'spot' or type == 'margin':
4696
- if stop:
5276
+ if trigger:
4697
5277
  response = self.privateSpotDeletePriceOrders(self.extend(request, requestParams))
4698
5278
  else:
4699
5279
  response = self.privateSpotDeleteOrders(self.extend(request, requestParams))
4700
5280
  elif type == 'swap':
4701
- if stop:
5281
+ if trigger:
4702
5282
  response = self.privateFuturesDeleteSettlePriceOrders(self.extend(request, requestParams))
4703
5283
  else:
4704
5284
  response = self.privateFuturesDeleteSettleOrders(self.extend(request, requestParams))
4705
5285
  elif type == 'future':
4706
- if stop:
5286
+ if trigger:
4707
5287
  response = self.privateDeliveryDeleteSettlePriceOrders(self.extend(request, requestParams))
4708
5288
  else:
4709
5289
  response = self.privateDeliveryDeleteSettleOrders(self.extend(request, requestParams))
@@ -4744,7 +5324,9 @@ class gate(Exchange, ImplicitAPI):
4744
5324
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4745
5325
  """
4746
5326
  transfer currency internally between wallets on the same account
4747
- :see: https://www.gate.io/docs/developers/apiv4/en/#transfer-between-trading-accounts
5327
+
5328
+ https://www.gate.io/docs/developers/apiv4/en/#transfer-between-trading-accounts
5329
+
4748
5330
  :param str code: unified currency code for currency being transferred
4749
5331
  :param float amount: the amount of currency to transfer
4750
5332
  :param str fromAccount: the account to transfer currency from
@@ -4758,8 +5340,8 @@ class gate(Exchange, ImplicitAPI):
4758
5340
  fromId = self.convert_type_to_account(fromAccount)
4759
5341
  toId = self.convert_type_to_account(toAccount)
4760
5342
  truncated = self.currency_to_precision(code, amount)
4761
- request = {
4762
- 'currency': currency['id'],
5343
+ request: dict = {
5344
+ 'currency': currency['id'], # todo: currencies have network-junctions
4763
5345
  'amount': truncated,
4764
5346
  }
4765
5347
  if not (fromId in self.options['accountsByType']):
@@ -4780,7 +5362,7 @@ class gate(Exchange, ImplicitAPI):
4780
5362
  request['currency_pair'] = market['id']
4781
5363
  params = self.omit(params, 'symbol')
4782
5364
  if (toId == 'futures') or (toId == 'delivery') or (fromId == 'futures') or (fromId == 'delivery'):
4783
- request['settle'] = currency['id']
5365
+ request['settle'] = currency['id'] # todo: currencies have network-junctions
4784
5366
  response = self.privateWalletPostTransfers(self.extend(request, params))
4785
5367
  #
4786
5368
  # according to the docs(however actual response seems to be an empty string '')
@@ -4795,7 +5377,7 @@ class gate(Exchange, ImplicitAPI):
4795
5377
  #
4796
5378
  return self.parse_transfer(response, currency)
4797
5379
 
4798
- def parse_transfer(self, transfer, currency: Currency = None):
5380
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
4799
5381
  #
4800
5382
  # {
4801
5383
  # "currency": "BTC",
@@ -4820,8 +5402,10 @@ class gate(Exchange, ImplicitAPI):
4820
5402
  def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
4821
5403
  """
4822
5404
  set the level of leverage for a market
4823
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-leverage
4824
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-leverage-2
5405
+
5406
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-leverage
5407
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-leverage-2
5408
+
4825
5409
  :param float leverage: the rate of leverage
4826
5410
  :param str symbol: unified market symbol
4827
5411
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4884,7 +5468,7 @@ class gate(Exchange, ImplicitAPI):
4884
5468
  #
4885
5469
  return response
4886
5470
 
4887
- def parse_position(self, position, market: Market = None):
5471
+ def parse_position(self, position: dict, market: Market = None):
4888
5472
  #
4889
5473
  # swap and future
4890
5474
  #
@@ -4941,37 +5525,61 @@ class gate(Exchange, ImplicitAPI):
4941
5525
  # "pending_orders": 0
4942
5526
  # }
4943
5527
  #
5528
+ # fetchPositionsHistory(swap and future)
5529
+ #
5530
+ # {
5531
+ # "contract": "SLERF_USDT", # Futures contract
5532
+ # "text": "web", # Text of close order
5533
+ # "long_price": "0.766306", # When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price.
5534
+ # "pnl": "-23.41702352", # PNL
5535
+ # "pnl_pnl": "-22.7187", # Position P/L
5536
+ # "pnl_fee": "-0.06527125", # Transaction Fees
5537
+ # "pnl_fund": "-0.63305227", # Funding Fees
5538
+ # "accum_size": "100",
5539
+ # "time": 1711279263, # Position close time
5540
+ # "short_price": "0.539119", # When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price
5541
+ # "side": "long", # Position side, long or short
5542
+ # "max_size": "100", # Max Trade Size
5543
+ # "first_open_time": 1711037985 # First Open Time
5544
+ # }
5545
+ #
4944
5546
  contract = self.safe_string(position, 'contract')
4945
5547
  market = self.safe_market(contract, market, '_', 'contract')
4946
- size = self.safe_string(position, 'size')
4947
- side = None
4948
- if Precise.string_gt(size, '0'):
4949
- side = 'long'
4950
- elif Precise.string_lt(size, '0'):
4951
- side = 'short'
5548
+ size = self.safe_string_2(position, 'size', 'accum_size')
5549
+ side = self.safe_string(position, 'side')
5550
+ if side is None:
5551
+ if Precise.string_gt(size, '0'):
5552
+ side = 'long'
5553
+ elif Precise.string_lt(size, '0'):
5554
+ side = 'short'
4952
5555
  maintenanceRate = self.safe_string(position, 'maintenance_rate')
4953
5556
  notional = self.safe_string(position, 'value')
4954
5557
  leverage = self.safe_string(position, 'leverage')
4955
5558
  marginMode = None
4956
- if leverage == '0':
4957
- marginMode = 'cross'
4958
- else:
4959
- marginMode = 'isolated'
4960
- unrealisedPnl = self.safe_string(position, 'unrealised_pnl')
5559
+ if leverage is not None:
5560
+ if leverage == '0':
5561
+ marginMode = 'cross'
5562
+ else:
5563
+ marginMode = 'isolated'
4961
5564
  # Initial Position Margin = ( Position Value / Leverage ) + Close Position Fee
4962
5565
  # *The default leverage under the full position is the highest leverage in the market.
4963
5566
  # *Trading fee is charged Fee Rate(0.075%).
4964
- takerFee = '0.00075'
4965
- feePaid = Precise.string_mul(takerFee, notional)
4966
- initialMarginString = Precise.string_add(Precise.string_div(notional, leverage), feePaid)
4967
- timestamp = self.safe_timestamp(position, 'open_time')
5567
+ feePaid = self.safe_string(position, 'pnl_fee')
5568
+ initialMarginString = None
5569
+ if feePaid is None:
5570
+ takerFee = '0.00075'
5571
+ feePaid = Precise.string_mul(takerFee, notional)
5572
+ initialMarginString = Precise.string_add(Precise.string_div(notional, leverage), feePaid)
5573
+ timestamp = self.safe_timestamp_2(position, 'open_time', 'first_open_time')
5574
+ if timestamp == 0:
5575
+ timestamp = None
4968
5576
  return self.safe_position({
4969
5577
  'info': position,
4970
5578
  'id': None,
4971
5579
  'symbol': self.safe_string(market, 'symbol'),
4972
5580
  'timestamp': timestamp,
4973
5581
  'datetime': self.iso8601(timestamp),
4974
- 'lastUpdateTimestamp': self.safe_timestamp(position, 'update_time'),
5582
+ 'lastUpdateTimestamp': self.safe_timestamp_2(position, 'update_time', 'time'),
4975
5583
  'initialMargin': self.parse_number(initialMarginString),
4976
5584
  'initialMarginPercentage': self.parse_number(Precise.string_div(initialMarginString, notional)),
4977
5585
  'maintenanceMargin': self.parse_number(Precise.string_mul(maintenanceRate, notional)),
@@ -4979,11 +5587,10 @@ class gate(Exchange, ImplicitAPI):
4979
5587
  'entryPrice': self.safe_number(position, 'entry_price'),
4980
5588
  'notional': self.parse_number(notional),
4981
5589
  'leverage': self.safe_number(position, 'leverage'),
4982
- 'unrealizedPnl': self.parse_number(unrealisedPnl),
4983
- 'realizedPnl': self.safe_number(position, 'realised_pnl'),
5590
+ 'unrealizedPnl': self.safe_number(position, 'unrealised_pnl'),
5591
+ 'realizedPnl': self.safe_number_2(position, 'realised_pnl', 'pnl'),
4984
5592
  'contracts': self.parse_number(Precise.string_abs(size)),
4985
- 'contractSize': self.safe_value(market, 'contractSize'),
4986
- # 'realisedPnl': position['realised_pnl'],
5593
+ 'contractSize': self.safe_number(market, 'contractSize'),
4987
5594
  'marginRatio': None,
4988
5595
  'liquidationPrice': self.safe_number(position, 'liq_price'),
4989
5596
  'markPrice': self.safe_number(position, 'mark_price'),
@@ -4999,9 +5606,11 @@ class gate(Exchange, ImplicitAPI):
4999
5606
  def fetch_position(self, symbol: str, params={}):
5000
5607
  """
5001
5608
  fetch data on an open contract position
5002
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-single-position
5003
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-single-position-2
5004
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-specified-contract-position
5609
+
5610
+ https://www.gate.io/docs/developers/apiv4/en/#get-single-position
5611
+ https://www.gate.io/docs/developers/apiv4/en/#get-single-position-2
5612
+ https://www.gate.io/docs/developers/apiv4/en/#get-specified-contract-position
5613
+
5005
5614
  :param str symbol: unified market symbol of the market the position is held in
5006
5615
  :param dict [params]: extra parameters specific to the exchange API endpoint
5007
5616
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
@@ -5010,7 +5619,7 @@ class gate(Exchange, ImplicitAPI):
5010
5619
  market = self.market(symbol)
5011
5620
  if not market['contract']:
5012
5621
  raise BadRequest(self.id + ' fetchPosition() supports contract markets only')
5013
- request = {}
5622
+ request: dict = {}
5014
5623
  request, params = self.prepare_request(market, market['type'], params)
5015
5624
  extendedRequest = self.extend(request, params)
5016
5625
  response = None
@@ -5081,9 +5690,11 @@ class gate(Exchange, ImplicitAPI):
5081
5690
  def fetch_positions(self, symbols: Strings = None, params={}):
5082
5691
  """
5083
5692
  fetch all open positions
5084
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-positions-of-a-user
5085
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-positions-of-a-user-2
5086
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-user-s-positions-of-specified-underlying
5693
+
5694
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-positions-of-a-user
5695
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-positions-of-a-user-2
5696
+ https://www.gate.io/docs/developers/apiv4/en/#list-user-s-positions-of-specified-underlying
5697
+
5087
5698
  :param str[]|None symbols: Not used by gate, but parsed internally by CCXT
5088
5699
  :param dict [params]: extra parameters specific to the exchange API endpoint
5089
5700
  :param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
@@ -5098,7 +5709,7 @@ class gate(Exchange, ImplicitAPI):
5098
5709
  if symbolsLength > 0:
5099
5710
  market = self.market(symbols[0])
5100
5711
  type = None
5101
- request = {}
5712
+ request: dict = {}
5102
5713
  type, params = self.handle_market_type_and_params('fetchPositions', market, params)
5103
5714
  if (type is None) or (type == 'spot'):
5104
5715
  type = 'swap' # default to swap
@@ -5178,11 +5789,13 @@ class gate(Exchange, ImplicitAPI):
5178
5789
  #
5179
5790
  return self.parse_positions(response, symbols)
5180
5791
 
5181
- def fetch_leverage_tiers(self, symbols: Strings = None, params={}):
5792
+ def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
5182
5793
  """
5183
5794
  retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
5184
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
5185
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2
5795
+
5796
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
5797
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2
5798
+
5186
5799
  :param str[] [symbols]: list of unified market symbols
5187
5800
  :param dict [params]: extra parameters specific to the exchange API endpoint
5188
5801
  :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
@@ -5293,10 +5906,12 @@ class gate(Exchange, ImplicitAPI):
5293
5906
  #
5294
5907
  return self.parse_leverage_tiers(response, symbols, 'name')
5295
5908
 
5296
- def fetch_market_leverage_tiers(self, symbol: str, params={}):
5909
+ def fetch_market_leverage_tiers(self, symbol: str, params={}) -> List[LeverageTier]:
5297
5910
  """
5298
5911
  retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes for a single market
5299
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-risk-limit-tiers
5912
+
5913
+ https://www.gate.io/docs/developers/apiv4/en/#list-risk-limit-tiers
5914
+
5300
5915
  :param str symbol: unified market symbol
5301
5916
  :param dict [params]: extra parameters specific to the exchange API endpoint
5302
5917
  :returns dict: a `leverage tiers structure <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
@@ -5321,7 +5936,8 @@ class gate(Exchange, ImplicitAPI):
5321
5936
  #
5322
5937
  return self.parse_market_leverage_tiers(response, market)
5323
5938
 
5324
- def parse_emulated_leverage_tiers(self, info, market=None):
5939
+ def parse_emulated_leverage_tiers(self, info, market=None) -> List[LeverageTier]:
5940
+ marketId = self.safe_string(info, 'name')
5325
5941
  maintenanceMarginUnit = self.safe_string(info, 'maintenance_rate') # '0.005',
5326
5942
  leverageMax = self.safe_string(info, 'leverage_max') # '100',
5327
5943
  riskLimitStep = self.safe_string(info, 'risk_limit_step') # '1000000',
@@ -5335,6 +5951,7 @@ class gate(Exchange, ImplicitAPI):
5335
5951
  cap = Precise.string_add(floor, riskLimitStep)
5336
5952
  tiers.append({
5337
5953
  'tier': self.parse_number(Precise.string_div(cap, riskLimitStep)),
5954
+ 'symbol': self.safe_symbol(marketId, market, None, 'contract'),
5338
5955
  'currency': self.safe_string(market, 'settle'),
5339
5956
  'minNotional': self.parse_number(floor),
5340
5957
  'maxNotional': self.parse_number(cap),
@@ -5347,7 +5964,7 @@ class gate(Exchange, ImplicitAPI):
5347
5964
  floor = cap
5348
5965
  return tiers
5349
5966
 
5350
- def parse_market_leverage_tiers(self, info, market: Market = None):
5967
+ def parse_market_leverage_tiers(self, info, market: Market = None) -> List[LeverageTier]:
5351
5968
  #
5352
5969
  # [
5353
5970
  # {
@@ -5368,6 +5985,7 @@ class gate(Exchange, ImplicitAPI):
5368
5985
  maxNotional = self.safe_number(item, 'risk_limit')
5369
5986
  tiers.append({
5370
5987
  'tier': self.sum(i, 1),
5988
+ 'symbol': market['symbol'],
5371
5989
  'currency': market['base'],
5372
5990
  'minNotional': minNotional,
5373
5991
  'maxNotional': maxNotional,
@@ -5381,7 +5999,9 @@ class gate(Exchange, ImplicitAPI):
5381
5999
  def repay_isolated_margin(self, symbol: str, code: str, amount, params={}):
5382
6000
  """
5383
6001
  repay borrowed margin and interest
5384
- :see: https://www.gate.io/docs/apiv4/en/#repay-a-loan
6002
+
6003
+ https://www.gate.io/docs/apiv4/en/#repay-a-loan
6004
+
5385
6005
  :param str symbol: unified market symbol
5386
6006
  :param str code: unified currency code of the currency to repay
5387
6007
  :param float amount: the amount to repay
@@ -5392,8 +6012,8 @@ class gate(Exchange, ImplicitAPI):
5392
6012
  """
5393
6013
  self.load_markets()
5394
6014
  currency = self.currency(code)
5395
- request = {
5396
- 'currency': currency['id'].upper(),
6015
+ request: dict = {
6016
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5397
6017
  'amount': self.currency_to_precision(code, amount),
5398
6018
  }
5399
6019
  market = self.market(symbol)
@@ -5408,56 +6028,69 @@ class gate(Exchange, ImplicitAPI):
5408
6028
  def repay_cross_margin(self, code: str, amount, params={}):
5409
6029
  """
5410
6030
  repay cross margin borrowed margin and interest
5411
- :see: https://www.gate.io/docs/developers/apiv4/en/#cross-margin-repayments
6031
+
6032
+ https://www.gate.io/docs/developers/apiv4/en/#cross-margin-repayments
6033
+ https://www.gate.io/docs/developers/apiv4/en/#borrow-or-repay
6034
+
5412
6035
  :param str code: unified currency code of the currency to repay
5413
6036
  :param float amount: the amount to repay
5414
- :param str symbol: unified market symbol, required for isolated margin
5415
6037
  :param dict [params]: extra parameters specific to the exchange API endpoint
5416
6038
  :param str [params.mode]: 'all' or 'partial' payment mode, extra parameter required for isolated margin
5417
6039
  :param str [params.id]: '34267567' loan id, extra parameter required for isolated margin
6040
+ :param boolean [params.unifiedAccount]: set to True for repaying in the unified account
5418
6041
  :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
5419
6042
  """
5420
6043
  self.load_markets()
6044
+ self.load_unified_status()
5421
6045
  currency = self.currency(code)
5422
- request = {
5423
- 'currency': currency['id'].upper(),
6046
+ request: dict = {
6047
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5424
6048
  'amount': self.currency_to_precision(code, amount),
5425
6049
  }
5426
- response = self.privateMarginPostCrossRepayments(self.extend(request, params))
5427
- #
5428
- # [
5429
- # {
5430
- # "id": "17",
5431
- # "create_time": 1620381696159,
5432
- # "update_time": 1620381696159,
5433
- # "currency": "EOS",
5434
- # "amount": "110.553635",
5435
- # "text": "web",
5436
- # "status": 2,
5437
- # "repaid": "110.506649705159",
5438
- # "repaid_interest": "0.046985294841",
5439
- # "unpaid_interest": "0.0000074393366667"
5440
- # }
5441
- # ]
5442
- #
5443
- response = self.safe_value(response, 0)
6050
+ isUnifiedAccount = False
6051
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'repayCrossMargin', 'unifiedAccount')
6052
+ response = None
6053
+ if isUnifiedAccount:
6054
+ request['type'] = 'repay'
6055
+ response = self.privateUnifiedPostLoans(self.extend(request, params))
6056
+ else:
6057
+ response = self.privateMarginPostCrossRepayments(self.extend(request, params))
6058
+ response = self.safe_dict(response, 0)
6059
+ #
6060
+ # [
6061
+ # {
6062
+ # "id": "17",
6063
+ # "create_time": 1620381696159,
6064
+ # "update_time": 1620381696159,
6065
+ # "currency": "EOS",
6066
+ # "amount": "110.553635",
6067
+ # "text": "web",
6068
+ # "status": 2,
6069
+ # "repaid": "110.506649705159",
6070
+ # "repaid_interest": "0.046985294841",
6071
+ # "unpaid_interest": "0.0000074393366667"
6072
+ # }
6073
+ # ]
6074
+ #
5444
6075
  return self.parse_margin_loan(response, currency)
5445
6076
 
5446
6077
  def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
5447
6078
  """
5448
6079
  create a loan to borrow margin
5449
- :see: https://www.gate.io/docs/developers/apiv4/en/#marginuni
6080
+
6081
+ https://www.gate.io/docs/developers/apiv4/en/#marginuni
6082
+
6083
+ :param str symbol: unified market symbol, required for isolated margin
5450
6084
  :param str code: unified currency code of the currency to borrow
5451
6085
  :param float amount: the amount to borrow
5452
- :param str symbol: unified market symbol, required for isolated margin
5453
6086
  :param dict [params]: extra parameters specific to the exchange API endpoint
5454
6087
  :param str [params.rate]: '0.0002' or '0.002' extra parameter required for isolated margin
5455
6088
  :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
5456
6089
  """
5457
6090
  self.load_markets()
5458
6091
  currency = self.currency(code)
5459
- request = {
5460
- 'currency': currency['id'].upper(),
6092
+ request: dict = {
6093
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5461
6094
  'amount': self.currency_to_precision(code, amount),
5462
6095
  }
5463
6096
  response = None
@@ -5489,35 +6122,46 @@ class gate(Exchange, ImplicitAPI):
5489
6122
  def borrow_cross_margin(self, code: str, amount: float, params={}):
5490
6123
  """
5491
6124
  create a loan to borrow margin
5492
- :see: https://www.gate.io/docs/apiv4/en/#create-a-cross-margin-borrow-loan
6125
+
6126
+ https://www.gate.io/docs/apiv4/en/#create-a-cross-margin-borrow-loan
6127
+ https://www.gate.io/docs/developers/apiv4/en/#borrow-or-repay
6128
+
5493
6129
  :param str code: unified currency code of the currency to borrow
5494
6130
  :param float amount: the amount to borrow
5495
- :param str symbol: unified market symbol, required for isolated margin
5496
6131
  :param dict [params]: extra parameters specific to the exchange API endpoint
5497
6132
  :param str [params.rate]: '0.0002' or '0.002' extra parameter required for isolated margin
6133
+ :param boolean [params.unifiedAccount]: set to True for borrowing in the unified account
5498
6134
  :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
5499
6135
  """
5500
6136
  self.load_markets()
6137
+ self.load_unified_status()
5501
6138
  currency = self.currency(code)
5502
- request = {
5503
- 'currency': currency['id'].upper(),
6139
+ request: dict = {
6140
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5504
6141
  'amount': self.currency_to_precision(code, amount),
5505
6142
  }
5506
- response = self.privateMarginPostCrossLoans(self.extend(request, params))
5507
- #
5508
- # {
5509
- # "id": "17",
5510
- # "create_time": 1620381696159,
5511
- # "update_time": 1620381696159,
5512
- # "currency": "EOS",
5513
- # "amount": "110.553635",
5514
- # "text": "web",
5515
- # "status": 2,
5516
- # "repaid": "110.506649705159",
5517
- # "repaid_interest": "0.046985294841",
5518
- # "unpaid_interest": "0.0000074393366667"
5519
- # }
5520
- #
6143
+ isUnifiedAccount = False
6144
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'borrowCrossMargin', 'unifiedAccount')
6145
+ response = None
6146
+ if isUnifiedAccount:
6147
+ request['type'] = 'borrow'
6148
+ response = self.privateUnifiedPostLoans(self.extend(request, params))
6149
+ else:
6150
+ response = self.privateMarginPostCrossLoans(self.extend(request, params))
6151
+ #
6152
+ # {
6153
+ # "id": "17",
6154
+ # "create_time": 1620381696159,
6155
+ # "update_time": 1620381696159,
6156
+ # "currency": "EOS",
6157
+ # "amount": "110.553635",
6158
+ # "text": "web",
6159
+ # "status": 2,
6160
+ # "repaid": "110.506649705159",
6161
+ # "repaid_interest": "0.046985294841",
6162
+ # "unpaid_interest": "0.0000074393366667"
6163
+ # }
6164
+ #
5521
6165
  return self.parse_margin_loan(response, currency)
5522
6166
 
5523
6167
  def parse_margin_loan(self, info, currency: Currency = None):
@@ -5573,11 +6217,91 @@ class gate(Exchange, ImplicitAPI):
5573
6217
  'info': info,
5574
6218
  }
5575
6219
 
6220
+ def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6221
+ """
6222
+ fetch the interest owed by the user for borrowing currency for margin trading
6223
+
6224
+ https://www.gate.io/docs/developers/apiv4/en/#list-interest-records
6225
+ https://www.gate.io/docs/developers/apiv4/en/#interest-records-for-the-cross-margin-account
6226
+ https://www.gate.io/docs/developers/apiv4/en/#list-interest-records-2
6227
+
6228
+ :param str [code]: unified currency code
6229
+ :param str [symbol]: unified market symbol when fetching interest in isolated markets
6230
+ :param int [since]: the earliest time in ms to fetch borrow interest for
6231
+ :param int [limit]: the maximum number of structures to retrieve
6232
+ :param dict [params]: extra parameters specific to the exchange API endpoint
6233
+ :param boolean [params.unifiedAccount]: set to True for fetching borrow interest in the unified account
6234
+ :returns dict[]: a list of `borrow interest structures <https://docs.ccxt.com/#/?id=borrow-interest-structure>`
6235
+ """
6236
+ self.load_markets()
6237
+ self.load_unified_status()
6238
+ isUnifiedAccount = False
6239
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'fetchBorrowInterest', 'unifiedAccount')
6240
+ request: dict = {}
6241
+ request, params = self.handle_until_option('to', request, params)
6242
+ currency = None
6243
+ if code is not None:
6244
+ currency = self.currency(code)
6245
+ request['currency'] = currency['id']
6246
+ market = None
6247
+ if symbol is not None:
6248
+ market = self.market(symbol)
6249
+ if since is not None:
6250
+ request['from'] = since
6251
+ if limit is not None:
6252
+ request['limit'] = limit
6253
+ response = None
6254
+ marginMode = None
6255
+ marginMode, params = self.handle_margin_mode_and_params('fetchBorrowInterest', params, 'cross')
6256
+ if isUnifiedAccount:
6257
+ response = self.privateUnifiedGetInterestRecords(self.extend(request, params))
6258
+ elif marginMode == 'isolated':
6259
+ if market is not None:
6260
+ request['currency_pair'] = market['id']
6261
+ response = self.privateMarginGetUniInterestRecords(self.extend(request, params))
6262
+ elif marginMode == 'cross':
6263
+ response = self.privateMarginGetCrossInterestRecords(self.extend(request, params))
6264
+ interest = self.parse_borrow_interests(response, market)
6265
+ return self.filter_by_currency_since_limit(interest, code, since, limit)
6266
+
6267
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
6268
+ marketId = self.safe_string(info, 'currency_pair')
6269
+ market = self.safe_market(marketId, market)
6270
+ marginMode = 'isolated' if (marketId is not None) else 'cross'
6271
+ timestamp = self.safe_integer(info, 'create_time')
6272
+ return {
6273
+ 'info': info,
6274
+ 'symbol': self.safe_string(market, 'symbol'),
6275
+ 'currency': self.safe_currency_code(self.safe_string(info, 'currency')),
6276
+ 'interest': self.safe_number(info, 'interest'),
6277
+ 'interestRate': self.safe_number(info, 'actual_rate'),
6278
+ 'amountBorrowed': None,
6279
+ 'marginMode': marginMode,
6280
+ 'timestamp': timestamp,
6281
+ 'datetime': self.iso8601(timestamp),
6282
+ }
6283
+
6284
+ def nonce(self):
6285
+ return self.milliseconds() - self.options['timeDifference']
6286
+
5576
6287
  def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
5577
6288
  authentication = api[0] # public, private
5578
6289
  type = api[1] # spot, margin, future, delivery
5579
6290
  query = self.omit(params, self.extract_params(path))
5580
- if isinstance(params, list):
6291
+ containsSettle = path.find('settle') > -1
6292
+ if containsSettle and path.endswith('batch_cancel_orders'): # weird check to prevent $settle in php and converting {settle} to array(settle)
6293
+ # special case where we need to extract the settle from the path
6294
+ # but the body is an array of strings
6295
+ settle = self.safe_dict(params, 0)
6296
+ path = self.implode_params(path, settle)
6297
+ # remove the first element from params
6298
+ newParams = []
6299
+ anyParams = params
6300
+ for i in range(1, len(anyParams)):
6301
+ newParams.append(params[i])
6302
+ params = newParams
6303
+ query = newParams
6304
+ elif isinstance(params, list):
5581
6305
  # endpoints like createOrders use an array instead of an object
5582
6306
  # so we infer the settle from one of the elements
5583
6307
  # they have to be all the same so relying on the first one is fine
@@ -5619,7 +6343,8 @@ class gate(Exchange, ImplicitAPI):
5619
6343
  body = self.json(query)
5620
6344
  bodyPayload = '' if (body is None) else body
5621
6345
  bodySignature = self.hash(self.encode(bodyPayload), 'sha512')
5622
- timestamp = self.seconds()
6346
+ nonce = self.nonce()
6347
+ timestamp = self.parse_to_int(nonce / 1000)
5623
6348
  timestampString = str(timestamp)
5624
6349
  signaturePath = '/api/' + self.version + entirePath
5625
6350
  payloadArray = [method.upper(), signaturePath, queryString, bodySignature, timestampString]
@@ -5648,7 +6373,7 @@ class gate(Exchange, ImplicitAPI):
5648
6373
  raise NotSupported(self.id + ' modifyMarginHelper() not support self market type')
5649
6374
  return self.parse_margin_modification(response, market)
5650
6375
 
5651
- def parse_margin_modification(self, data, market: Market = None):
6376
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
5652
6377
  #
5653
6378
  # {
5654
6379
  # "value": "11.9257",
@@ -5681,18 +6406,24 @@ class gate(Exchange, ImplicitAPI):
5681
6406
  total = self.safe_number(data, 'margin')
5682
6407
  return {
5683
6408
  'info': data,
5684
- 'amount': None,
5685
- 'code': self.safe_value(market, 'quote'),
5686
6409
  'symbol': market['symbol'],
6410
+ 'type': None,
6411
+ 'marginMode': 'isolated',
6412
+ 'amount': None,
5687
6413
  'total': total,
6414
+ 'code': self.safe_value(market, 'quote'),
5688
6415
  'status': 'ok',
6416
+ 'timestamp': None,
6417
+ 'datetime': None,
5689
6418
  }
5690
6419
 
5691
- def reduce_margin(self, symbol: str, amount, params={}):
6420
+ def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
5692
6421
  """
5693
6422
  remove margin from a position
5694
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
5695
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin-2
6423
+
6424
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
6425
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-margin-2
6426
+
5696
6427
  :param str symbol: unified market symbol
5697
6428
  :param float amount: the amount of margin to remove
5698
6429
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -5700,11 +6431,13 @@ class gate(Exchange, ImplicitAPI):
5700
6431
  """
5701
6432
  return self.modify_margin_helper(symbol, -amount, params)
5702
6433
 
5703
- def add_margin(self, symbol: str, amount, params={}):
6434
+ def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
5704
6435
  """
5705
6436
  add margin
5706
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
5707
- :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin-2
6437
+
6438
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
6439
+ https://www.gate.io/docs/developers/apiv4/en/#update-position-margin-2
6440
+
5708
6441
  :param str symbol: unified market symbol
5709
6442
  :param float amount: amount of margin to add
5710
6443
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -5715,7 +6448,9 @@ class gate(Exchange, ImplicitAPI):
5715
6448
  def fetch_open_interest_history(self, symbol: str, timeframe='5m', since: Int = None, limit: Int = None, params={}):
5716
6449
  """
5717
6450
  Retrieves the open interest of a currency
5718
- :see: https://www.gate.io/docs/developers/apiv4/en/#futures-stats
6451
+
6452
+ https://www.gate.io/docs/developers/apiv4/en/#futures-stats
6453
+
5719
6454
  :param str symbol: Unified CCXT market symbol
5720
6455
  :param str timeframe: "5m", "15m", "30m", "1h", "4h", "1d"
5721
6456
  :param int [since]: the time(ms) of the earliest record to retrieve unix timestamp
@@ -5732,7 +6467,7 @@ class gate(Exchange, ImplicitAPI):
5732
6467
  market = self.market(symbol)
5733
6468
  if not market['swap']:
5734
6469
  raise BadRequest(self.id + ' fetchOpenInterest() supports swap markets only')
5735
- request = {
6470
+ request: dict = {
5736
6471
  'contract': market['id'],
5737
6472
  'settle': market['settleId'],
5738
6473
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
@@ -5763,7 +6498,7 @@ class gate(Exchange, ImplicitAPI):
5763
6498
  # ...
5764
6499
  # ]
5765
6500
  #
5766
- return self.parse_open_interests(response, market, since, limit)
6501
+ return self.parse_open_interests_history(response, market, since, limit)
5767
6502
 
5768
6503
  def parse_open_interest(self, interest, market: Market = None):
5769
6504
  #
@@ -5797,7 +6532,9 @@ class gate(Exchange, ImplicitAPI):
5797
6532
  def fetch_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5798
6533
  """
5799
6534
  fetches historical settlement records
5800
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-settlement-history-2
6535
+
6536
+ https://www.gate.io/docs/developers/apiv4/en/#list-settlement-history-2
6537
+
5801
6538
  :param str symbol: unified market symbol of the settlement history, required on gate
5802
6539
  :param int [since]: timestamp in ms
5803
6540
  :param int [limit]: number of records
@@ -5814,7 +6551,7 @@ class gate(Exchange, ImplicitAPI):
5814
6551
  raise NotSupported(self.id + ' fetchSettlementHistory() supports option markets only')
5815
6552
  marketId = market['id']
5816
6553
  optionParts = marketId.split('-')
5817
- request = {
6554
+ request: dict = {
5818
6555
  'underlying': self.safe_string(optionParts, 0),
5819
6556
  }
5820
6557
  if since is not None:
@@ -5841,7 +6578,9 @@ class gate(Exchange, ImplicitAPI):
5841
6578
  def fetch_my_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5842
6579
  """
5843
6580
  fetches historical settlement records of the user
5844
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-my-options-settlements
6581
+
6582
+ https://www.gate.io/docs/developers/apiv4/en/#list-my-options-settlements
6583
+
5845
6584
  :param str symbol: unified market symbol of the settlement history
5846
6585
  :param int [since]: timestamp in ms
5847
6586
  :param int [limit]: number of records
@@ -5858,7 +6597,7 @@ class gate(Exchange, ImplicitAPI):
5858
6597
  raise NotSupported(self.id + ' fetchMySettlementHistory() supports option markets only')
5859
6598
  marketId = market['id']
5860
6599
  optionParts = marketId.split('-')
5861
- request = {
6600
+ request: dict = {
5862
6601
  'underlying': self.safe_string(optionParts, 0),
5863
6602
  'contract': marketId,
5864
6603
  }
@@ -5961,21 +6700,23 @@ class gate(Exchange, ImplicitAPI):
5961
6700
  result.append(self.parse_settlement(settlements[i], market))
5962
6701
  return result
5963
6702
 
5964
- def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
6703
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
5965
6704
  """
5966
6705
  fetch the history of changes, actions done by the user or operations that altered the balance of the user
5967
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-account-book
5968
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-margin-account-balance-change-history
5969
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-account-book-2
5970
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-account-book-3
5971
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-account-changing-history
5972
- :param str code: unified currency code
6706
+
6707
+ https://www.gate.io/docs/developers/apiv4/en/#query-account-book
6708
+ https://www.gate.io/docs/developers/apiv4/en/#list-margin-account-balance-change-history
6709
+ https://www.gate.io/docs/developers/apiv4/en/#query-account-book-2
6710
+ https://www.gate.io/docs/developers/apiv4/en/#query-account-book-3
6711
+ https://www.gate.io/docs/developers/apiv4/en/#list-account-changing-history
6712
+
6713
+ :param str [code]: unified currency code
5973
6714
  :param int [since]: timestamp in ms of the earliest ledger entry
5974
6715
  :param int [limit]: max number of ledger entries to return
5975
6716
  :param dict [params]: extra parameters specific to the exchange API endpoint
5976
6717
  :param int [params.until]: end time in ms
5977
- :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)
5978
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
6718
+ :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)
6719
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
5979
6720
  """
5980
6721
  self.load_markets()
5981
6722
  paginate = False
@@ -5985,12 +6726,12 @@ class gate(Exchange, ImplicitAPI):
5985
6726
  type = None
5986
6727
  currency = None
5987
6728
  response = None
5988
- request = {}
6729
+ request: dict = {}
5989
6730
  type, params = self.handle_market_type_and_params('fetchLedger', None, params)
5990
6731
  if (type == 'spot') or (type == 'margin'):
5991
6732
  if code is not None:
5992
6733
  currency = self.currency(code)
5993
- request['currency'] = currency['id']
6734
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
5994
6735
  if (type == 'swap') or (type == 'future'):
5995
6736
  defaultSettle = 'usdt' if (type == 'swap') else 'btc'
5996
6737
  settle = self.safe_string_lower(params, 'settle', defaultSettle)
@@ -6065,7 +6806,7 @@ class gate(Exchange, ImplicitAPI):
6065
6806
  #
6066
6807
  return self.parse_ledger(response, currency, since, limit)
6067
6808
 
6068
- def parse_ledger_entry(self, item, currency: Currency = None):
6809
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
6069
6810
  #
6070
6811
  # spot
6071
6812
  #
@@ -6118,6 +6859,7 @@ class gate(Exchange, ImplicitAPI):
6118
6859
  else:
6119
6860
  direction = 'in'
6120
6861
  currencyId = self.safe_string(item, 'currency')
6862
+ currency = self.safe_currency(currencyId, currency)
6121
6863
  type = self.safe_string(item, 'type')
6122
6864
  rawTimestamp = self.safe_string(item, 'time')
6123
6865
  timestamp = None
@@ -6128,7 +6870,8 @@ class gate(Exchange, ImplicitAPI):
6128
6870
  balanceString = self.safe_string(item, 'balance')
6129
6871
  changeString = self.safe_string(item, 'change')
6130
6872
  before = self.parse_number(Precise.string_sub(balanceString, changeString))
6131
- return {
6873
+ return self.safe_ledger_entry({
6874
+ 'info': item,
6132
6875
  'id': self.safe_string(item, 'id'),
6133
6876
  'direction': direction,
6134
6877
  'account': None,
@@ -6143,11 +6886,10 @@ class gate(Exchange, ImplicitAPI):
6143
6886
  'after': self.safe_number(item, 'balance'),
6144
6887
  'status': None,
6145
6888
  'fee': None,
6146
- 'info': item,
6147
- }
6889
+ }, currency)
6148
6890
 
6149
6891
  def parse_ledger_entry_type(self, type):
6150
- ledgerType = {
6892
+ ledgerType: dict = {
6151
6893
  'deposit': 'deposit',
6152
6894
  'withdraw': 'withdrawal',
6153
6895
  'sub_account_transfer': 'transfer',
@@ -6192,7 +6934,9 @@ class gate(Exchange, ImplicitAPI):
6192
6934
  def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
6193
6935
  """
6194
6936
  set dual/hedged mode to True or False for a swap market, make sure all positions are closed and no orders are open before setting dual mode
6195
- :see: https://www.gate.io/docs/developers/apiv4/en/#enable-or-disable-dual-mode
6937
+
6938
+ https://www.gate.io/docs/developers/apiv4/en/#enable-or-disable-dual-mode
6939
+
6196
6940
  :param bool hedged: set to True to enable dual mode
6197
6941
  :param str|None symbol: if passed, dual mode is set for all markets with the same settle currency
6198
6942
  :param dict params: extra parameters specific to the exchange API endpoint
@@ -6207,7 +6951,9 @@ class gate(Exchange, ImplicitAPI):
6207
6951
  def fetch_underlying_assets(self, params={}):
6208
6952
  """
6209
6953
  fetches the market ids of underlying assets for a specific contract market type
6210
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-underlyings
6954
+
6955
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-underlyings
6956
+
6211
6957
  :param dict [params]: exchange specific params
6212
6958
  :param str [params.type]: the contract market type, 'option', 'swap' or 'future', the default is 'option'
6213
6959
  :returns dict[]: a list of `underlying assets <https://docs.ccxt.com/#/?id=underlying-assets-structure>`
@@ -6240,7 +6986,9 @@ class gate(Exchange, ImplicitAPI):
6240
6986
  def fetch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
6241
6987
  """
6242
6988
  retrieves the public liquidations of a trading pair
6243
- :see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-liquidation-history
6989
+
6990
+ https://www.gate.io/docs/developers/apiv4/en/#retrieve-liquidation-history
6991
+
6244
6992
  :param str symbol: unified CCXT market symbol
6245
6993
  :param int [since]: the earliest time in ms to fetch liquidations for
6246
6994
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -6252,7 +7000,7 @@ class gate(Exchange, ImplicitAPI):
6252
7000
  market = self.market(symbol)
6253
7001
  if not market['swap']:
6254
7002
  raise NotSupported(self.id + ' fetchLiquidations() supports swap markets only')
6255
- request = {
7003
+ request: dict = {
6256
7004
  'settle': market['settleId'],
6257
7005
  'contract': market['id'],
6258
7006
  }
@@ -6279,9 +7027,11 @@ class gate(Exchange, ImplicitAPI):
6279
7027
  def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
6280
7028
  """
6281
7029
  retrieves the users liquidated positions
6282
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-liquidation-history
6283
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-liquidation-history-2
6284
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-user-s-liquidation-history-of-specified-underlying
7030
+
7031
+ https://www.gate.io/docs/developers/apiv4/en/#list-liquidation-history
7032
+ https://www.gate.io/docs/developers/apiv4/en/#list-liquidation-history-2
7033
+ https://www.gate.io/docs/developers/apiv4/en/#list-user-s-liquidation-history-of-specified-underlying
7034
+
6285
7035
  :param str symbol: unified CCXT market symbol
6286
7036
  :param int [since]: the earliest time in ms to fetch liquidations for
6287
7037
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -6292,7 +7042,7 @@ class gate(Exchange, ImplicitAPI):
6292
7042
  raise ArgumentsRequired(self.id + ' fetchMyLiquidations() requires a symbol argument')
6293
7043
  self.load_markets()
6294
7044
  market = self.market(symbol)
6295
- request = {
7045
+ request: dict = {
6296
7046
  'contract': market['id'],
6297
7047
  }
6298
7048
  response = None
@@ -6414,14 +7164,16 @@ class gate(Exchange, ImplicitAPI):
6414
7164
  def fetch_greeks(self, symbol: str, params={}) -> Greeks:
6415
7165
  """
6416
7166
  fetches an option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
6417
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
7167
+
7168
+ https://www.gate.io/docs/developers/apiv4/en/#list-tickers-of-options-contracts
7169
+
6418
7170
  :param str symbol: unified symbol of the market to fetch greeks for
6419
7171
  :param dict [params]: extra parameters specific to the exchange API endpoint
6420
7172
  :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
6421
7173
  """
6422
7174
  self.load_markets()
6423
7175
  market = self.market(symbol)
6424
- request = {
7176
+ request: dict = {
6425
7177
  'underlying': market['info']['underlying'],
6426
7178
  }
6427
7179
  response = self.publicOptionsGetTickers(self.extend(request, params))
@@ -6455,7 +7207,7 @@ class gate(Exchange, ImplicitAPI):
6455
7207
  return self.parse_greeks(entry, market)
6456
7208
  return None
6457
7209
 
6458
- def parse_greeks(self, greeks, market: Market = None):
7210
+ def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
6459
7211
  #
6460
7212
  # {
6461
7213
  # "vega": "1.78992",
@@ -6503,15 +7255,17 @@ class gate(Exchange, ImplicitAPI):
6503
7255
  def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
6504
7256
  """
6505
7257
  closes open positions for a market
6506
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order
6507
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order-2
6508
- :see: https://www.gate.io/docs/developers/apiv4/en/#create-an-options-order
7258
+
7259
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order
7260
+ https://www.gate.io/docs/developers/apiv4/en/#create-a-futures-order-2
7261
+ https://www.gate.io/docs/developers/apiv4/en/#create-an-options-order
7262
+
6509
7263
  :param str symbol: Unified CCXT market symbol
6510
7264
  :param str side: 'buy' or 'sell'
6511
7265
  :param dict [params]: extra parameters specific to the okx api endpoint
6512
7266
  :returns dict[]: `A list of position structures <https://docs.ccxt.com/#/?id=position-structure>`
6513
7267
  """
6514
- request = {
7268
+ request: dict = {
6515
7269
  'close': True,
6516
7270
  }
6517
7271
  params = self.extend(request, params)
@@ -6522,9 +7276,11 @@ class gate(Exchange, ImplicitAPI):
6522
7276
  def fetch_leverage(self, symbol: str, params={}) -> Leverage:
6523
7277
  """
6524
7278
  fetch the set leverage for a market
6525
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-unified-account-information
6526
- :see: https://www.gate.io/docs/developers/apiv4/en/#get-detail-of-lending-market
6527
- :see: https://www.gate.io/docs/developers/apiv4/en/#query-one-single-margin-currency-pair-deprecated
7279
+
7280
+ https://www.gate.io/docs/developers/apiv4/en/#get-unified-account-information
7281
+ https://www.gate.io/docs/developers/apiv4/en/#get-detail-of-lending-market
7282
+ https://www.gate.io/docs/developers/apiv4/en/#query-one-single-margin-currency-pair-deprecated
7283
+
6528
7284
  :param str symbol: unified market symbol
6529
7285
  :param dict [params]: extra parameters specific to the exchange API endpoint
6530
7286
  :param boolean [params.unified]: default False, set to True for fetching the unified accounts leverage
@@ -6535,7 +7291,7 @@ class gate(Exchange, ImplicitAPI):
6535
7291
  if symbol is not None:
6536
7292
  # unified account does not require a symbol
6537
7293
  market = self.market(symbol)
6538
- request = {}
7294
+ request: dict = {}
6539
7295
  response = None
6540
7296
  isUnified = self.safe_bool(params, 'unified')
6541
7297
  params = self.omit(params, 'unified')
@@ -6621,11 +7377,13 @@ class gate(Exchange, ImplicitAPI):
6621
7377
  raise NotSupported(self.id + ' fetchLeverage() does not support ' + market['type'] + ' markets')
6622
7378
  return self.parse_leverage(response, market)
6623
7379
 
6624
- def fetch_leverages(self, symbols: List[str] = None, params={}) -> Leverages:
7380
+ def fetch_leverages(self, symbols: Strings = None, params={}) -> Leverages:
6625
7381
  """
6626
7382
  fetch the set leverage for all leverage markets, only spot margin is supported on gate
6627
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-lending-markets
6628
- :see: https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading-deprecated
7383
+
7384
+ https://www.gate.io/docs/developers/apiv4/en/#list-lending-markets
7385
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading-deprecated
7386
+
6629
7387
  :param str[] symbols: a list of unified market symbols
6630
7388
  :param dict [params]: extra parameters specific to the exchange API endpoint
6631
7389
  :param boolean [params.unified]: default False, set to True for fetching unified account leverages
@@ -6668,7 +7426,7 @@ class gate(Exchange, ImplicitAPI):
6668
7426
  #
6669
7427
  return self.parse_leverages(response, symbols, marketIdRequest, 'spot')
6670
7428
 
6671
- def parse_leverage(self, leverage, market=None) -> Leverage:
7429
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
6672
7430
  marketId = self.safe_string_2(leverage, 'currency_pair', 'id')
6673
7431
  leverageValue = self.safe_integer(leverage, 'leverage')
6674
7432
  return {
@@ -6679,7 +7437,257 @@ class gate(Exchange, ImplicitAPI):
6679
7437
  'shortLeverage': leverageValue,
6680
7438
  }
6681
7439
 
6682
- def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
7440
+ def fetch_option(self, symbol: str, params={}) -> Option:
7441
+ """
7442
+ fetches option data that is commonly found in an option chain
7443
+
7444
+ https://www.gate.io/docs/developers/apiv4/en/#query-specified-contract-detail
7445
+
7446
+ :param str symbol: unified market symbol
7447
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7448
+ :returns dict: an `option chain structure <https://docs.ccxt.com/#/?id=option-chain-structure>`
7449
+ """
7450
+ self.load_markets()
7451
+ market = self.market(symbol)
7452
+ request: dict = {
7453
+ 'contract': market['id'],
7454
+ }
7455
+ response = self.publicOptionsGetContractsContract(self.extend(request, params))
7456
+ #
7457
+ # {
7458
+ # "is_active": True,
7459
+ # "mark_price_round": "0.01",
7460
+ # "settle_fee_rate": "0.00015",
7461
+ # "bid1_size": 30,
7462
+ # "taker_fee_rate": "0.0003",
7463
+ # "price_limit_fee_rate": "0.1",
7464
+ # "order_price_round": "0.1",
7465
+ # "tag": "month",
7466
+ # "ref_rebate_rate": "0",
7467
+ # "name": "ETH_USDT-20240628-4500-C",
7468
+ # "strike_price": "4500",
7469
+ # "ask1_price": "280.5",
7470
+ # "ref_discount_rate": "0",
7471
+ # "order_price_deviate": "0.2",
7472
+ # "ask1_size": -19,
7473
+ # "mark_price_down": "155.45",
7474
+ # "orderbook_id": 11724695,
7475
+ # "is_call": True,
7476
+ # "last_price": "188.7",
7477
+ # "mark_price": "274.26",
7478
+ # "underlying": "ETH_USDT",
7479
+ # "create_time": 1688024882,
7480
+ # "settle_limit_fee_rate": "0.1",
7481
+ # "orders_limit": 10,
7482
+ # "mark_price_up": "403.83",
7483
+ # "position_size": 80,
7484
+ # "order_size_max": 10000,
7485
+ # "position_limit": 100000,
7486
+ # "multiplier": "0.01",
7487
+ # "order_size_min": 1,
7488
+ # "trade_size": 229,
7489
+ # "underlying_price": "3326.6",
7490
+ # "maker_fee_rate": "0.0003",
7491
+ # "expiration_time": 1719561600,
7492
+ # "trade_id": 15,
7493
+ # "bid1_price": "269.3"
7494
+ # }
7495
+ #
7496
+ return self.parse_option(response, None, market)
7497
+
7498
+ def fetch_option_chain(self, code: str, params={}) -> OptionChain:
7499
+ """
7500
+ fetches data for an underlying asset that is commonly found in an option chain
7501
+
7502
+ https://www.gate.io/docs/developers/apiv4/en/#list-all-the-contracts-with-specified-underlying-and-expiration-time
7503
+
7504
+ :param str code: base currency to fetch an option chain for
7505
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7506
+ :param str [params.underlying]: the underlying asset, can be obtained from fetchUnderlyingAssets()
7507
+ :param int [params.expiration]: unix timestamp of the expiration time
7508
+ :returns dict: a list of `option chain structures <https://docs.ccxt.com/#/?id=option-chain-structure>`
7509
+ """
7510
+ self.load_markets()
7511
+ currency = self.currency(code)
7512
+ request: dict = {
7513
+ 'underlying': currency['code'] + '_USDT', # todo: currency['id'].upper() & network junctions
7514
+ }
7515
+ response = self.publicOptionsGetContracts(self.extend(request, params))
7516
+ #
7517
+ # [
7518
+ # {
7519
+ # "is_active": True,
7520
+ # "mark_price_round": "0.1",
7521
+ # "settle_fee_rate": "0.00015",
7522
+ # "bid1_size": 434,
7523
+ # "taker_fee_rate": "0.0003",
7524
+ # "price_limit_fee_rate": "0.1",
7525
+ # "order_price_round": "1",
7526
+ # "tag": "day",
7527
+ # "ref_rebate_rate": "0",
7528
+ # "name": "BTC_USDT-20240324-63500-P",
7529
+ # "strike_price": "63500",
7530
+ # "ask1_price": "387",
7531
+ # "ref_discount_rate": "0",
7532
+ # "order_price_deviate": "0.15",
7533
+ # "ask1_size": -454,
7534
+ # "mark_price_down": "124.3",
7535
+ # "orderbook_id": 29600,
7536
+ # "is_call": False,
7537
+ # "last_price": "0",
7538
+ # "mark_price": "366.6",
7539
+ # "underlying": "BTC_USDT",
7540
+ # "create_time": 1711118829,
7541
+ # "settle_limit_fee_rate": "0.1",
7542
+ # "orders_limit": 10,
7543
+ # "mark_price_up": "630",
7544
+ # "position_size": 0,
7545
+ # "order_size_max": 10000,
7546
+ # "position_limit": 10000,
7547
+ # "multiplier": "0.01",
7548
+ # "order_size_min": 1,
7549
+ # "trade_size": 0,
7550
+ # "underlying_price": "64084.65",
7551
+ # "maker_fee_rate": "0.0003",
7552
+ # "expiration_time": 1711267200,
7553
+ # "trade_id": 0,
7554
+ # "bid1_price": "307"
7555
+ # },
7556
+ # ]
7557
+ #
7558
+ return self.parse_option_chain(response, None, 'name')
7559
+
7560
+ def parse_option(self, chain: dict, currency: Currency = None, market: Market = None) -> Option:
7561
+ #
7562
+ # {
7563
+ # "is_active": True,
7564
+ # "mark_price_round": "0.1",
7565
+ # "settle_fee_rate": "0.00015",
7566
+ # "bid1_size": 434,
7567
+ # "taker_fee_rate": "0.0003",
7568
+ # "price_limit_fee_rate": "0.1",
7569
+ # "order_price_round": "1",
7570
+ # "tag": "day",
7571
+ # "ref_rebate_rate": "0",
7572
+ # "name": "BTC_USDT-20240324-63500-P",
7573
+ # "strike_price": "63500",
7574
+ # "ask1_price": "387",
7575
+ # "ref_discount_rate": "0",
7576
+ # "order_price_deviate": "0.15",
7577
+ # "ask1_size": -454,
7578
+ # "mark_price_down": "124.3",
7579
+ # "orderbook_id": 29600,
7580
+ # "is_call": False,
7581
+ # "last_price": "0",
7582
+ # "mark_price": "366.6",
7583
+ # "underlying": "BTC_USDT",
7584
+ # "create_time": 1711118829,
7585
+ # "settle_limit_fee_rate": "0.1",
7586
+ # "orders_limit": 10,
7587
+ # "mark_price_up": "630",
7588
+ # "position_size": 0,
7589
+ # "order_size_max": 10000,
7590
+ # "position_limit": 10000,
7591
+ # "multiplier": "0.01",
7592
+ # "order_size_min": 1,
7593
+ # "trade_size": 0,
7594
+ # "underlying_price": "64084.65",
7595
+ # "maker_fee_rate": "0.0003",
7596
+ # "expiration_time": 1711267200,
7597
+ # "trade_id": 0,
7598
+ # "bid1_price": "307"
7599
+ # }
7600
+ #
7601
+ marketId = self.safe_string(chain, 'name')
7602
+ market = self.safe_market(marketId, market)
7603
+ timestamp = self.safe_timestamp(chain, 'create_time')
7604
+ return {
7605
+ 'info': chain,
7606
+ 'currency': None,
7607
+ 'symbol': market['symbol'],
7608
+ 'timestamp': timestamp,
7609
+ 'datetime': self.iso8601(timestamp),
7610
+ 'impliedVolatility': None,
7611
+ 'openInterest': None,
7612
+ 'bidPrice': self.safe_number(chain, 'bid1_price'),
7613
+ 'askPrice': self.safe_number(chain, 'ask1_price'),
7614
+ 'midPrice': None,
7615
+ 'markPrice': self.safe_number(chain, 'mark_price'),
7616
+ 'lastPrice': self.safe_number(chain, 'last_price'),
7617
+ 'underlyingPrice': self.safe_number(chain, 'underlying_price'),
7618
+ 'change': None,
7619
+ 'percentage': None,
7620
+ 'baseVolume': None,
7621
+ 'quoteVolume': None,
7622
+ }
7623
+
7624
+ def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
7625
+ """
7626
+ fetches historical positions
7627
+
7628
+ https://www.gate.io/docs/developers/apiv4/#list-position-close-history
7629
+ https://www.gate.io/docs/developers/apiv4/#list-position-close-history-2
7630
+
7631
+ :param str[] symbols: unified conract symbols, must all have the same settle currency and the same market type
7632
+ :param int [since]: the earliest time in ms to fetch positions for
7633
+ :param int [limit]: the maximum amount of records to fetch, default=1000
7634
+ :param dict params: extra parameters specific to the exchange api endpoint
7635
+ :param int [params.until]: the latest time in ms to fetch positions for
7636
+
7637
+ EXCHANGE SPECIFIC PARAMETERS
7638
+ :param int [params.offset]: list offset, starting from 0
7639
+ :param str [params.side]: long or short
7640
+ :param str [params.pnl]: query profit or loss
7641
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
7642
+ """
7643
+ self.load_markets()
7644
+ market = None
7645
+ if symbols is not None:
7646
+ symbolsLength = len(symbols)
7647
+ if symbolsLength == 1:
7648
+ market = self.market(symbols[0])
7649
+ marketType = None
7650
+ marketType, params = self.handle_market_type_and_params('fetchPositionsHistory', market, params, 'swap')
7651
+ until = self.safe_integer(params, 'until')
7652
+ params = self.omit(params, 'until')
7653
+ request: dict = {}
7654
+ request, params = self.prepare_request(market, marketType, params)
7655
+ if limit is not None:
7656
+ request['limit'] = limit
7657
+ if since is not None:
7658
+ request['from'] = self.parse_to_int(since / 1000)
7659
+ if until is not None:
7660
+ request['to'] = self.parse_to_int(until / 1000)
7661
+ response = None
7662
+ if marketType == 'swap':
7663
+ response = self.privateFuturesGetSettlePositionClose(self.extend(request, params))
7664
+ elif marketType == 'future':
7665
+ response = self.privateDeliveryGetSettlePositionClose(self.extend(request, params))
7666
+ else:
7667
+ raise NotSupported(self.id + ' fetchPositionsHistory() does not support markets of type ' + marketType)
7668
+ #
7669
+ # [
7670
+ # {
7671
+ # "contract": "SLERF_USDT",
7672
+ # "text": "web",
7673
+ # "long_price": "0.766306",
7674
+ # "pnl": "-23.41702352",
7675
+ # "pnl_pnl": "-22.7187",
7676
+ # "pnl_fee": "-0.06527125",
7677
+ # "pnl_fund": "-0.63305227",
7678
+ # "accum_size": "100",
7679
+ # "time": 1711279263,
7680
+ # "short_price": "0.539119",
7681
+ # "side": "long",
7682
+ # "max_size": "100",
7683
+ # "first_open_time": 1711037985
7684
+ # },
7685
+ # ...
7686
+ # ]
7687
+ #
7688
+ return self.parse_positions(response, symbols, params)
7689
+
7690
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
6683
7691
  if response is None:
6684
7692
  return None
6685
7693
  #
@@ -6688,6 +7696,7 @@ class gate(Exchange, ImplicitAPI):
6688
7696
  # {"label": "INVALID_PARAM_VALUE", "message": "invalid argument: Trigger.rule"}
6689
7697
  # {"label": "INVALID_PARAM_VALUE", "message": "invalid argument: trigger.expiration invalid range"}
6690
7698
  # {"label": "INVALID_ARGUMENT", "detail": "invalid size"}
7699
+ # {"user_id":10406147,"id":"id","succeeded":false,"message":"INVALID_PROTOCOL","label":"INVALID_PROTOCOL"}
6691
7700
  #
6692
7701
  label = self.safe_string(response, 'label')
6693
7702
  if label is not None: