ccxt 4.4.98__py2.py3-none-any.whl → 4.4.100__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 (234) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/bingx.py +1 -0
  3. ccxt/abstract/bitget.py +6 -0
  4. ccxt/abstract/hibachi.py +26 -0
  5. ccxt/alpaca.py +1 -1
  6. ccxt/apex.py +1 -1
  7. ccxt/ascendex.py +1 -1
  8. ccxt/async_support/__init__.py +3 -1
  9. ccxt/async_support/alpaca.py +1 -1
  10. ccxt/async_support/apex.py +1 -1
  11. ccxt/async_support/ascendex.py +1 -1
  12. ccxt/async_support/base/exchange.py +44 -9
  13. ccxt/async_support/base/ws/client.py +3 -1
  14. ccxt/async_support/bigone.py +1 -1
  15. ccxt/async_support/binance.py +10 -8
  16. ccxt/async_support/bingx.py +33 -4
  17. ccxt/async_support/bitbank.py +1 -1
  18. ccxt/async_support/bitfinex.py +4 -1
  19. ccxt/async_support/bitflyer.py +1 -1
  20. ccxt/async_support/bitget.py +2040 -561
  21. ccxt/async_support/bithumb.py +1 -1
  22. ccxt/async_support/bitmart.py +2 -2
  23. ccxt/async_support/bitmex.py +3 -2
  24. ccxt/async_support/bitopro.py +1 -1
  25. ccxt/async_support/bitrue.py +2 -2
  26. ccxt/async_support/bitso.py +1 -1
  27. ccxt/async_support/bitstamp.py +1 -1
  28. ccxt/async_support/bittrade.py +1 -1
  29. ccxt/async_support/bitvavo.py +1 -1
  30. ccxt/async_support/blockchaincom.py +1 -1
  31. ccxt/async_support/blofin.py +1 -1
  32. ccxt/async_support/btcmarkets.py +1 -1
  33. ccxt/async_support/bybit.py +7 -3
  34. ccxt/async_support/coinbase.py +1 -1
  35. ccxt/async_support/coinbaseexchange.py +1 -1
  36. ccxt/async_support/coinbaseinternational.py +1 -1
  37. ccxt/async_support/coincatch.py +2 -2
  38. ccxt/async_support/coinex.py +67 -6
  39. ccxt/async_support/coinmate.py +1 -1
  40. ccxt/async_support/coinsph.py +1 -1
  41. ccxt/async_support/cryptocom.py +2 -2
  42. ccxt/async_support/defx.py +2 -2
  43. ccxt/async_support/delta.py +1 -1
  44. ccxt/async_support/deribit.py +1 -1
  45. ccxt/async_support/digifinex.py +2 -2
  46. ccxt/async_support/ellipx.py +1 -1
  47. ccxt/async_support/exmo.py +1 -1
  48. ccxt/async_support/foxbit.py +3 -3
  49. ccxt/async_support/gate.py +18 -4
  50. ccxt/async_support/gemini.py +1 -1
  51. ccxt/async_support/hashkey.py +2 -2
  52. ccxt/async_support/hibachi.py +2080 -0
  53. ccxt/async_support/hitbtc.py +2 -2
  54. ccxt/async_support/hollaex.py +1 -1
  55. ccxt/async_support/htx.py +4 -3
  56. ccxt/async_support/hyperliquid.py +71 -29
  57. ccxt/async_support/independentreserve.py +1 -1
  58. ccxt/async_support/indodax.py +1 -1
  59. ccxt/async_support/kraken.py +1 -1
  60. ccxt/async_support/krakenfutures.py +2 -1
  61. ccxt/async_support/kucoin.py +2 -2
  62. ccxt/async_support/kucoinfutures.py +2 -1
  63. ccxt/async_support/lbank.py +2 -2
  64. ccxt/async_support/mercado.py +1 -1
  65. ccxt/async_support/mexc.py +9 -2
  66. ccxt/async_support/modetrade.py +93 -2
  67. ccxt/async_support/ndax.py +1 -1
  68. ccxt/async_support/novadax.py +35 -1
  69. ccxt/async_support/okcoin.py +1 -1
  70. ccxt/async_support/okx.py +2 -2
  71. ccxt/async_support/onetrading.py +33 -0
  72. ccxt/async_support/oxfun.py +1 -1
  73. ccxt/async_support/p2b.py +32 -0
  74. ccxt/async_support/paradex.py +2 -1
  75. ccxt/async_support/phemex.py +2 -2
  76. ccxt/async_support/poloniex.py +2 -2
  77. ccxt/async_support/probit.py +36 -1
  78. ccxt/async_support/tokocrypto.py +1 -1
  79. ccxt/async_support/upbit.py +1 -1
  80. ccxt/async_support/vertex.py +1 -1
  81. ccxt/async_support/wavesexchange.py +1 -1
  82. ccxt/async_support/whitebit.py +2 -2
  83. ccxt/async_support/woo.py +4 -4
  84. ccxt/async_support/woofipro.py +93 -2
  85. ccxt/async_support/xt.py +2 -2
  86. ccxt/async_support/yobit.py +1 -1
  87. ccxt/async_support/zaif.py +1 -1
  88. ccxt/async_support/zonda.py +1 -1
  89. ccxt/base/errors.py +0 -6
  90. ccxt/base/exchange.py +11 -9
  91. ccxt/base/types.py +1 -0
  92. ccxt/bigone.py +1 -1
  93. ccxt/binance.py +10 -8
  94. ccxt/bingx.py +33 -4
  95. ccxt/bitbank.py +1 -1
  96. ccxt/bitfinex.py +4 -1
  97. ccxt/bitflyer.py +1 -1
  98. ccxt/bitget.py +2040 -561
  99. ccxt/bithumb.py +1 -1
  100. ccxt/bitmart.py +2 -2
  101. ccxt/bitmex.py +3 -2
  102. ccxt/bitopro.py +1 -1
  103. ccxt/bitrue.py +2 -2
  104. ccxt/bitso.py +1 -1
  105. ccxt/bitstamp.py +1 -1
  106. ccxt/bittrade.py +1 -1
  107. ccxt/bitvavo.py +1 -1
  108. ccxt/blockchaincom.py +1 -1
  109. ccxt/blofin.py +1 -1
  110. ccxt/btcmarkets.py +1 -1
  111. ccxt/bybit.py +7 -3
  112. ccxt/coinbase.py +1 -1
  113. ccxt/coinbaseexchange.py +1 -1
  114. ccxt/coinbaseinternational.py +1 -1
  115. ccxt/coincatch.py +2 -2
  116. ccxt/coinex.py +67 -6
  117. ccxt/coinmate.py +1 -1
  118. ccxt/coinsph.py +1 -1
  119. ccxt/cryptocom.py +2 -2
  120. ccxt/defx.py +2 -2
  121. ccxt/delta.py +1 -1
  122. ccxt/deribit.py +1 -1
  123. ccxt/digifinex.py +2 -2
  124. ccxt/ellipx.py +1 -1
  125. ccxt/exmo.py +1 -1
  126. ccxt/foxbit.py +3 -3
  127. ccxt/gate.py +18 -4
  128. ccxt/gemini.py +1 -1
  129. ccxt/hashkey.py +2 -2
  130. ccxt/hibachi.py +2079 -0
  131. ccxt/hitbtc.py +2 -2
  132. ccxt/hollaex.py +1 -1
  133. ccxt/htx.py +4 -3
  134. ccxt/hyperliquid.py +71 -29
  135. ccxt/independentreserve.py +1 -1
  136. ccxt/indodax.py +1 -1
  137. ccxt/kraken.py +1 -1
  138. ccxt/krakenfutures.py +2 -1
  139. ccxt/kucoin.py +2 -2
  140. ccxt/kucoinfutures.py +2 -1
  141. ccxt/lbank.py +2 -2
  142. ccxt/mercado.py +1 -1
  143. ccxt/mexc.py +9 -2
  144. ccxt/modetrade.py +93 -2
  145. ccxt/ndax.py +1 -1
  146. ccxt/novadax.py +35 -1
  147. ccxt/okcoin.py +1 -1
  148. ccxt/okx.py +2 -2
  149. ccxt/onetrading.py +33 -0
  150. ccxt/oxfun.py +1 -1
  151. ccxt/p2b.py +32 -0
  152. ccxt/paradex.py +2 -1
  153. ccxt/phemex.py +2 -2
  154. ccxt/poloniex.py +2 -2
  155. ccxt/pro/__init__.py +1 -1
  156. ccxt/pro/alpaca.py +2 -2
  157. ccxt/pro/apex.py +2 -2
  158. ccxt/pro/ascendex.py +2 -2
  159. ccxt/pro/binance.py +4 -5
  160. ccxt/pro/bitget.py +3 -3
  161. ccxt/pro/bithumb.py +2 -2
  162. ccxt/pro/bitmart.py +2 -2
  163. ccxt/pro/bitmex.py +3 -3
  164. ccxt/pro/bitstamp.py +3 -3
  165. ccxt/pro/bittrade.py +2 -2
  166. ccxt/pro/bitvavo.py +5 -3
  167. ccxt/pro/bybit.py +5 -4
  168. ccxt/pro/cex.py +3 -2
  169. ccxt/pro/coinbaseexchange.py +4 -4
  170. ccxt/pro/coinbaseinternational.py +2 -2
  171. ccxt/pro/coincatch.py +1 -1
  172. ccxt/pro/coinex.py +1 -1
  173. ccxt/pro/coinone.py +2 -2
  174. ccxt/pro/cryptocom.py +2 -2
  175. ccxt/pro/derive.py +2 -2
  176. ccxt/pro/gate.py +3 -3
  177. ccxt/pro/hollaex.py +2 -2
  178. ccxt/pro/htx.py +3 -3
  179. ccxt/pro/hyperliquid.py +101 -14
  180. ccxt/pro/kraken.py +2 -2
  181. ccxt/pro/krakenfutures.py +4 -3
  182. ccxt/pro/kucoin.py +4 -3
  183. ccxt/pro/kucoinfutures.py +4 -3
  184. ccxt/pro/mexc.py +328 -139
  185. ccxt/pro/modetrade.py +2 -2
  186. ccxt/pro/okcoin.py +2 -2
  187. ccxt/pro/okx.py +7 -6
  188. ccxt/pro/onetrading.py +2 -2
  189. ccxt/pro/oxfun.py +1 -1
  190. ccxt/pro/p2b.py +2 -2
  191. ccxt/pro/paradex.py +2 -2
  192. ccxt/pro/poloniex.py +2 -2
  193. ccxt/pro/probit.py +2 -2
  194. ccxt/pro/vertex.py +2 -2
  195. ccxt/pro/whitebit.py +2 -2
  196. ccxt/pro/woo.py +2 -2
  197. ccxt/pro/woofipro.py +2 -2
  198. ccxt/probit.py +36 -1
  199. ccxt/protobuf/__init__.py +0 -0
  200. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  201. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  202. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  203. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  204. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  205. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  206. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  207. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  208. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  209. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  210. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  211. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  212. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  213. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  214. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  215. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  216. ccxt/protobuf/mexc/__init__.py +0 -0
  217. ccxt/test/tests_async.py +1 -1
  218. ccxt/test/tests_sync.py +1 -1
  219. ccxt/tokocrypto.py +1 -1
  220. ccxt/upbit.py +1 -1
  221. ccxt/vertex.py +1 -1
  222. ccxt/wavesexchange.py +1 -1
  223. ccxt/whitebit.py +2 -2
  224. ccxt/woo.py +4 -4
  225. ccxt/woofipro.py +93 -2
  226. ccxt/xt.py +2 -2
  227. ccxt/yobit.py +1 -1
  228. ccxt/zaif.py +1 -1
  229. ccxt/zonda.py +1 -1
  230. {ccxt-4.4.98.dist-info → ccxt-4.4.100.dist-info}/METADATA +8 -7
  231. {ccxt-4.4.98.dist-info → ccxt-4.4.100.dist-info}/RECORD +234 -213
  232. {ccxt-4.4.98.dist-info → ccxt-4.4.100.dist-info}/LICENSE.txt +0 -0
  233. {ccxt-4.4.98.dist-info → ccxt-4.4.100.dist-info}/WHEEL +0 -0
  234. {ccxt-4.4.98.dist-info → ccxt-4.4.100.dist-info}/top_level.txt +0 -0
@@ -827,6 +827,7 @@ class bitget(Exchange, ImplicitAPI):
827
827
  'get': {
828
828
  'v3/account/assets': 1,
829
829
  'v3/account/settings': 1,
830
+ 'v3/account/deposit-records': 2,
830
831
  'v3/account/financial-records': 1,
831
832
  'v3/account/repayable-coins': 2,
832
833
  'v3/account/payment-coins': 2,
@@ -845,7 +846,9 @@ class bitget(Exchange, ImplicitAPI):
845
846
  'v3/position/history-position': 1,
846
847
  'v3/trade/order-info': 1,
847
848
  'v3/trade/unfilled-orders': 1,
849
+ 'v3/trade/unfilled-strategy-orders': 1,
848
850
  'v3/trade/history-orders': 1,
851
+ 'v3/trade/history-strategy-orders': 1,
849
852
  'v3/trade/fills': 1,
850
853
  'v3/user/sub-list': 2,
851
854
  'v3/user/sub-api-list': 2,
@@ -859,8 +862,11 @@ class bitget(Exchange, ImplicitAPI):
859
862
  'v3/account/max-open-available': 4,
860
863
  'v3/ins-loan/bind-uid': 6.6667,
861
864
  'v3/trade/place-order': 2,
865
+ 'v3/trade/place-strategy-order': 2,
862
866
  'v3/trade/modify-order': 2,
867
+ 'v3/trade/modify-strategy-order': 2,
863
868
  'v3/trade/cancel-order': 2,
869
+ 'v3/trade/cancel-strategy-order': 2,
864
870
  'v3/trade/place-batch': 4,
865
871
  'v3/trade/batch-modify-order': 2,
866
872
  'v3/trade/cancel-batch': 4,
@@ -906,6 +912,7 @@ class bitget(Exchange, ImplicitAPI):
906
912
  # '0': ExchangeError, # 200 successful,when the order placement / cancellation / operation is successful
907
913
  '4001': ExchangeError, # no data received in 30s
908
914
  '4002': ExchangeError, # Buffer full. cannot write data
915
+ '40020': BadRequest, # {"code":"40020","msg":"Parameter orderId error","requestTime":1754305078588,"data":null}
909
916
  # --------------------------------------------------------
910
917
  '30001': AuthenticationError, # {"code": 30001, "message": 'request header "OK_ACCESS_KEY" cannot be blank'}
911
918
  '30002': AuthenticationError, # {"code": 30002, "message": 'request header "OK_ACCESS_SIGN" cannot be blank'}
@@ -1450,6 +1457,19 @@ class bitget(Exchange, ImplicitAPI):
1450
1457
  '1w': '1Wutc',
1451
1458
  '1M': '1Mutc',
1452
1459
  },
1460
+ 'uta': {
1461
+ '1m': '1m',
1462
+ '3m': '3m',
1463
+ '5m': '5m',
1464
+ '15m': '15m',
1465
+ '30m': '30m',
1466
+ '1h': '1H',
1467
+ '2h': '2H',
1468
+ '4h': '4H',
1469
+ '6h': '6H',
1470
+ '12h': '12H',
1471
+ '1d': '1D',
1472
+ },
1453
1473
  },
1454
1474
  'fetchMarkets': {
1455
1475
  'types': ['spot', 'swap'], # there is future markets but they use the same endpoints
@@ -1539,7 +1559,6 @@ class bitget(Exchange, ImplicitAPI):
1539
1559
  'ERC20': 'ERC20',
1540
1560
  'BEP20': 'BSC',
1541
1561
  # 'BEP20': 'BEP20', # different for BEP20
1542
- 'BSC': 'BEP20',
1543
1562
  'ATOM': 'ATOM',
1544
1563
  'ACA': 'AcalaToken',
1545
1564
  'APT': 'Aptos',
@@ -1793,10 +1812,17 @@ class bitget(Exchange, ImplicitAPI):
1793
1812
  # else:
1794
1813
  defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1795
1814
  # }
1796
- productType = self.safe_string(params, 'productType', defaultProductType)
1815
+ productType = self.safe_string_2(params, 'productType', 'category', defaultProductType)
1797
1816
  if (productType is None) and (market is not None):
1798
1817
  settle = market['settle']
1799
- if settle == 'USDT':
1818
+ if market['spot']:
1819
+ marginMode = None
1820
+ marginMode, params = self.handle_margin_mode_and_params('handleProductTypeAndParams', params)
1821
+ if marginMode is not None:
1822
+ productType = 'MARGIN'
1823
+ else:
1824
+ productType = 'SPOT'
1825
+ elif settle == 'USDT':
1800
1826
  productType = 'USDT-FUTURES'
1801
1827
  elif settle == 'USDC':
1802
1828
  productType = 'USDC-FUTURES'
@@ -1809,8 +1835,8 @@ class bitget(Exchange, ImplicitAPI):
1809
1835
  else:
1810
1836
  productType = 'COIN-FUTURES'
1811
1837
  if productType is None:
1812
- raise ArgumentsRequired(self.id + ' requires a productType param, one of "USDT-FUTURES", "USDC-FUTURES", "COIN-FUTURES", "SUSDT-FUTURES", "SUSDC-FUTURES" or "SCOIN-FUTURES"')
1813
- params = self.omit(params, 'productType')
1838
+ raise ArgumentsRequired(self.id + ' requires a productType param, one of "USDT-FUTURES", "USDC-FUTURES", "COIN-FUTURES", "SUSDT-FUTURES", "SUSDC-FUTURES", "SCOIN-FUTURES" or for uta only "SPOT"')
1839
+ params = self.omit(params, ['productType', 'category'])
1814
1840
  return [productType, params]
1815
1841
 
1816
1842
  async def fetch_time(self, params={}) -> Int:
@@ -1843,10 +1869,10 @@ class bitget(Exchange, ImplicitAPI):
1843
1869
  https://www.bitget.com/api-doc/spot/market/Get-Symbols
1844
1870
  https://www.bitget.com/api-doc/contract/market/Get-All-Symbols-Contracts
1845
1871
  https://www.bitget.com/api-doc/margin/common/support-currencies
1846
- https://www.bitget.bike/api-doc/uta/public/Instruments
1872
+ https://www.bitget.com/api-doc/uta/public/Instruments
1847
1873
 
1848
1874
  :param dict [params]: extra parameters specific to the exchange API endpoint
1849
- :param str [params.uta]: set to True to fetch markets for the unified trading account(uta), defaults to False
1875
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
1850
1876
  :returns dict[]: an array of objects representing market data
1851
1877
  """
1852
1878
  if self.options['adjustForTimeDifference']:
@@ -2453,12 +2479,14 @@ class bitget(Exchange, ImplicitAPI):
2453
2479
  https://www.bitget.com/api-doc/contract/position/Get-Query-Position-Lever
2454
2480
  https://www.bitget.com/api-doc/margin/cross/account/Cross-Tier-Data
2455
2481
  https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Tier-Data
2482
+ https://www.bitget.com/api-doc/uta/public/Get-Position-Tier-Data
2456
2483
 
2457
2484
  :param str symbol: unified market symbol
2458
2485
  :param dict [params]: extra parameters specific to the exchange API endpoint
2459
2486
  :param str [params.marginMode]: for spot margin 'cross' or 'isolated', default is 'isolated'
2460
2487
  :param str [params.code]: required for cross spot margin
2461
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
2488
+ :param str [params.productType]: *contract and uta only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
2489
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
2462
2490
  :returns dict: a `leverage tiers structure <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
2463
2491
  """
2464
2492
  await self.load_markets()
@@ -2466,10 +2494,19 @@ class bitget(Exchange, ImplicitAPI):
2466
2494
  request: dict = {}
2467
2495
  response = None
2468
2496
  marginMode = None
2497
+ productType = None
2498
+ uta = None
2469
2499
  marginMode, params = self.handle_margin_mode_and_params('fetchMarketLeverageTiers', params, 'isolated')
2470
- if (market['swap']) or (market['future']):
2471
- productType = None
2472
- productType, params = self.handle_product_type_and_params(market, params)
2500
+ productType, params = self.handle_product_type_and_params(market, params)
2501
+ uta, params = self.handle_option_and_params(params, 'fetchMarketLeverageTiers', 'uta', False)
2502
+ if uta:
2503
+ if productType == 'SPOT':
2504
+ if marginMode is not None:
2505
+ productType = 'MARGIN'
2506
+ request['symbol'] = market['id']
2507
+ request['category'] = productType
2508
+ response = await self.publicUtaGetV3MarketPositionTier(self.extend(request, params))
2509
+ elif (market['swap']) or (market['future']):
2473
2510
  request['productType'] = productType
2474
2511
  request['symbol'] = market['id']
2475
2512
  response = await self.publicMixGetV2MixMarketQueryPositionLever(self.extend(request, params))
@@ -2543,6 +2580,23 @@ class bitget(Exchange, ImplicitAPI):
2543
2580
  # ]
2544
2581
  # }
2545
2582
  #
2583
+ # uta
2584
+ #
2585
+ # {
2586
+ # "code": "00000",
2587
+ # "msg": "success",
2588
+ # "requestTime": 1752735673127,
2589
+ # "data": [
2590
+ # {
2591
+ # "tier": "1",
2592
+ # "minTierValue": "0",
2593
+ # "maxTierValue": "150000",
2594
+ # "leverage": "125",
2595
+ # "mmr": "0.004"
2596
+ # },
2597
+ # ]
2598
+ # }
2599
+ #
2546
2600
  result = self.safe_value(response, 'data', [])
2547
2601
  return self.parse_market_leverage_tiers(result, market)
2548
2602
 
@@ -2583,14 +2637,24 @@ class bitget(Exchange, ImplicitAPI):
2583
2637
  # "maintainMarginRate": "0.1"
2584
2638
  # }
2585
2639
  #
2640
+ # uta
2641
+ #
2642
+ # {
2643
+ # "tier": "1",
2644
+ # "minTierValue": "0",
2645
+ # "maxTierValue": "150000",
2646
+ # "leverage": "125",
2647
+ # "mmr": "0.004"
2648
+ # }
2649
+ #
2586
2650
  tiers = []
2587
2651
  minNotional = 0
2588
2652
  for i in range(0, len(info)):
2589
2653
  item = info[i]
2590
- minimumNotional = self.safe_number(item, 'startUnit')
2654
+ minimumNotional = self.safe_number_2(item, 'startUnit', 'minTierValue')
2591
2655
  if minimumNotional is not None:
2592
2656
  minNotional = minimumNotional
2593
- maxNotional = self.safe_number_n(item, ['endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount'])
2657
+ maxNotional = self.safe_number_n(item, ['endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount', 'maxTierValue'])
2594
2658
  marginCurrency = self.safe_string_2(item, 'coin', 'baseCoin')
2595
2659
  currencyId = marginCurrency if (marginCurrency is not None) else market['base']
2596
2660
  marketId = self.safe_string(item, 'symbol')
@@ -2600,7 +2664,7 @@ class bitget(Exchange, ImplicitAPI):
2600
2664
  'currency': self.safe_currency_code(currencyId),
2601
2665
  'minNotional': minNotional,
2602
2666
  'maxNotional': maxNotional,
2603
- 'maintenanceMarginRate': self.safe_number_2(item, 'keepMarginRate', 'maintainMarginRate'),
2667
+ 'maintenanceMarginRate': self.safe_number_n(item, ['keepMarginRate', 'maintainMarginRate', 'mmr']),
2604
2668
  'maxLeverage': self.safe_number(item, 'leverage'),
2605
2669
  'info': item,
2606
2670
  })
@@ -2667,7 +2731,7 @@ class bitget(Exchange, ImplicitAPI):
2667
2731
  rawTransactions = self.safe_list(response, 'data', [])
2668
2732
  return self.parse_transactions(rawTransactions, None, since, limit)
2669
2733
 
2670
- async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
2734
+ async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
2671
2735
  """
2672
2736
  make a withdrawal
2673
2737
 
@@ -2942,10 +3006,12 @@ class bitget(Exchange, ImplicitAPI):
2942
3006
 
2943
3007
  https://www.bitget.com/api-doc/spot/market/Get-Orderbook
2944
3008
  https://www.bitget.com/api-doc/contract/market/Get-Merge-Depth
3009
+ https://www.bitget.com/api-doc/uta/public/OrderBook
2945
3010
 
2946
3011
  :param str symbol: unified symbol of the market to fetch the order book for
2947
3012
  :param int [limit]: the maximum amount of order book entries to return
2948
3013
  :param dict [params]: extra parameters specific to the exchange API endpoint
3014
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
2949
3015
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
2950
3016
  """
2951
3017
  await self.load_markets()
@@ -2955,12 +3021,17 @@ class bitget(Exchange, ImplicitAPI):
2955
3021
  }
2956
3022
  if limit is not None:
2957
3023
  request['limit'] = limit
3024
+ productType = None
3025
+ productType, params = self.handle_product_type_and_params(market, params)
2958
3026
  response = None
2959
- if market['spot']:
3027
+ uta = None
3028
+ uta, params = self.handle_option_and_params(params, 'fetchOrderBook', 'uta', False)
3029
+ if uta:
3030
+ request['category'] = productType
3031
+ response = await self.publicUtaGetV3MarketOrderbook(self.extend(request, params))
3032
+ elif market['spot']:
2960
3033
  response = await self.publicSpotGetV2SpotMarketOrderbook(self.extend(request, params))
2961
3034
  else:
2962
- productType = None
2963
- productType, params = self.handle_product_type_and_params(market, params)
2964
3035
  request['productType'] = productType
2965
3036
  response = await self.publicMixGetV2MixMarketMergeDepth(self.extend(request, params))
2966
3037
  #
@@ -2975,9 +3046,24 @@ class bitget(Exchange, ImplicitAPI):
2975
3046
  # }
2976
3047
  # }
2977
3048
  #
3049
+ # uta
3050
+ #
3051
+ # {
3052
+ # "code": "00000",
3053
+ # "msg": "success",
3054
+ # "requestTime": 1750329437753,
3055
+ # "data": {
3056
+ # "a": [[104992.60, 0.018411]],
3057
+ # "b":[[104927.40, 0.229914]],
3058
+ # "ts": "1750329437763"
3059
+ # }
3060
+ # }
3061
+ #
2978
3062
  data = self.safe_value(response, 'data', {})
3063
+ bidsKey = 'b' if uta else 'bids'
3064
+ asksKey = 'a' if uta else 'asks'
2979
3065
  timestamp = self.safe_integer(data, 'ts')
2980
- return self.parse_order_book(data, market['symbol'], timestamp)
3066
+ return self.parse_order_book(data, market['symbol'], timestamp, bidsKey, asksKey)
2981
3067
 
2982
3068
  def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
2983
3069
  #
@@ -2989,7 +3075,7 @@ class bitget(Exchange, ImplicitAPI):
2989
3075
  # "ts": "1695793390482"
2990
3076
  # }
2991
3077
  #
2992
- # spot: fetchTicker, fetchTickers
3078
+ # spot
2993
3079
  #
2994
3080
  # {
2995
3081
  # "open": "37202.46",
@@ -3010,90 +3096,115 @@ class bitget(Exchange, ImplicitAPI):
3010
3096
  # "change24h": "0.00321"
3011
3097
  # }
3012
3098
  #
3013
- # swap and future: fetchTicker
3099
+ # swap and future
3014
3100
  #
3015
3101
  # {
3016
3102
  # "symbol": "BTCUSDT",
3017
- # "lastPr": "37577.2",
3018
- # "askPr": "37577.3",
3019
- # "bidPr": "37577.2",
3020
- # "bidSz": "3.679",
3021
- # "askSz": "0.02",
3022
- # "high24h": "37765",
3023
- # "low24h": "36628.9",
3024
- # "ts": "1700533070359",
3025
- # "change24h": "0.00288",
3026
- # "baseVolume": "108606.181",
3027
- # "quoteVolume": "4051316303.9608",
3028
- # "usdtVolume": "4051316303.9608",
3029
- # "openUtc": "37451.5",
3030
- # "changeUtc24h": "0.00336",
3031
- # "indexPrice": "37574.489253",
3032
- # "fundingRate": "0.0001",
3033
- # "holdingAmount": "53464.529",
3103
+ # "lastPr": "104823.8",
3104
+ # "askPr": "104823.8",
3105
+ # "bidPr": "104823.5",
3106
+ # "bidSz": "0.703",
3107
+ # "askSz": "13.894",
3108
+ # "high24h": "105289.3",
3109
+ # "low24h": "103447.9",
3110
+ # "ts": "1750332210370",
3111
+ # "change24h": "0.00471",
3112
+ # "baseVolume": "79089.5675",
3113
+ # "quoteVolume": "8274870921.80485",
3114
+ # "usdtVolume": "8274870921.80485",
3115
+ # "openUtc": "104833",
3116
+ # "changeUtc24h": "-0.00009",
3117
+ # "indexPrice": "104881.953125",
3118
+ # "fundingRate": "-0.000014",
3119
+ # "holdingAmount": "7452.6421",
3034
3120
  # "deliveryStartTime": null,
3035
3121
  # "deliveryTime": null,
3036
3122
  # "deliveryStatus": "",
3037
- # "open24h": "37235.7"
3123
+ # "open24h": "104332.3",
3124
+ # "markPrice": "104824.2"
3125
+ # }
3126
+ #
3127
+ # spot uta
3128
+ #
3129
+ # {
3130
+ # "category": "SPOT",
3131
+ # "symbol": "BTCUSDT",
3132
+ # "ts": "1750330651972",
3133
+ # "lastPrice": "104900.2",
3134
+ # "openPrice24h": "104321.2",
3135
+ # "highPrice24h": "107956.8",
3136
+ # "lowPrice24h": "103600.1",
3137
+ # "ask1Price": "104945.8",
3138
+ # "bid1Price": "104880.6",
3139
+ # "bid1Size": "0.266534",
3140
+ # "ask1Size": "0.014001",
3141
+ # "price24hPcnt": "0.00555",
3142
+ # "volume24h": "355.941109",
3143
+ # "turnover24h": "37302936.008134"
3038
3144
  # }
3039
3145
  #
3040
- # swap and future: fetchTickers
3146
+ # swap and future uta
3041
3147
  #
3042
3148
  # {
3043
- # "open": "14.9776",
3044
- # "symbol": "LINKUSDT",
3045
- # "high24h": "15.3942",
3046
- # "low24h": "14.3457",
3047
- # "lastPr": "14.3748",
3048
- # "quoteVolume": "7008612.4299",
3049
- # "baseVolume": "469908.8523",
3050
- # "usdtVolume": "7008612.42986561",
3051
- # "ts": "1700533772309",
3052
- # "bidPr": "14.375",
3053
- # "askPr": "14.3769",
3054
- # "bidSz": "50.004",
3055
- # "askSz": "0.7647",
3056
- # "openUtc": "14.478",
3057
- # "changeUtc24h": "-0.00713",
3058
- # "change24h": "-0.04978"
3149
+ # "category": "USDT-FUTURES",
3150
+ # "symbol": "BTCUSDT",
3151
+ # "ts": "1750332730472",
3152
+ # "lastPrice": "104738",
3153
+ # "openPrice24h": "104374",
3154
+ # "highPrice24h": "105289.3",
3155
+ # "lowPrice24h": "103447.9",
3156
+ # "ask1Price": "104738",
3157
+ # "bid1Price": "104737.7",
3158
+ # "bid1Size": "2.036",
3159
+ # "ask1Size": "8.094",
3160
+ # "price24hPcnt": "0.00349",
3161
+ # "volume24h": "79101.6477",
3162
+ # "turnover24h": "8276293391.45973",
3163
+ # "indexPrice": "104785.956168",
3164
+ # "markPrice": "104738",
3165
+ # "fundingRate": "-0.000007",
3166
+ # "openInterest": "7465.5938",
3167
+ # "deliveryStartTime": "",
3168
+ # "deliveryTime": "",
3169
+ # "deliveryStatus": ""
3059
3170
  # }
3060
3171
  #
3061
3172
  marketId = self.safe_string(ticker, 'symbol')
3062
- close = self.safe_string(ticker, 'lastPr')
3173
+ close = self.safe_string_2(ticker, 'lastPr', 'lastPrice')
3063
3174
  timestamp = self.safe_integer_omit_zero(ticker, 'ts') # exchange bitget provided 0
3064
3175
  change = self.safe_string(ticker, 'change24h')
3065
- open24 = self.safe_string_2(ticker, 'open24', 'open24h')
3066
- open = self.safe_string(ticker, 'open')
3067
- symbol: str
3068
- openValue: str
3069
- if open is None:
3070
- symbol = self.safe_symbol(marketId, market, None, 'contract')
3071
- openValue = open24
3176
+ category = self.safe_string(ticker, 'category')
3177
+ markPrice = self.safe_string(ticker, 'markPrice')
3178
+ marketType: str
3179
+ if (markPrice is not None) and (category != 'SPOT'):
3180
+ marketType = 'contract'
3072
3181
  else:
3073
- symbol = self.safe_symbol(marketId, market, None, 'spot')
3074
- openValue = open
3182
+ marketType = 'spot'
3183
+ percentage = self.safe_string(ticker, 'price24hPcnt')
3184
+ if percentage is None:
3185
+ percentage = Precise.string_mul(change, '100')
3075
3186
  return self.safe_ticker({
3076
- 'symbol': symbol,
3187
+ 'symbol': self.safe_symbol(marketId, market, None, marketType),
3077
3188
  'timestamp': timestamp,
3078
3189
  'datetime': self.iso8601(timestamp),
3079
- 'high': self.safe_string(ticker, 'high24h'),
3080
- 'low': self.safe_string(ticker, 'low24h'),
3081
- 'bid': self.safe_string(ticker, 'bidPr'),
3082
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
3083
- 'ask': self.safe_string(ticker, 'askPr'),
3084
- 'askVolume': self.safe_string(ticker, 'askSz'),
3190
+ 'high': self.safe_string_2(ticker, 'high24h', 'highPrice24h'),
3191
+ 'low': self.safe_string_2(ticker, 'low24h', 'lowPrice24h'),
3192
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
3193
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
3194
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
3195
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
3085
3196
  'vwap': None,
3086
- 'open': openValue,
3197
+ 'open': self.safe_string_n(ticker, ['open', 'open24h', 'openPrice24h']),
3087
3198
  'close': close,
3088
3199
  'last': close,
3089
3200
  'previousClose': None,
3090
3201
  'change': change,
3091
- 'percentage': Precise.string_mul(change, '100'),
3202
+ 'percentage': percentage,
3092
3203
  'average': None,
3093
- 'baseVolume': self.safe_string(ticker, 'baseVolume'),
3094
- 'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
3204
+ 'baseVolume': self.safe_string_2(ticker, 'baseVolume', 'volume24h'),
3205
+ 'quoteVolume': self.safe_string_2(ticker, 'quoteVolume', 'turnover24h'),
3095
3206
  'indexPrice': self.safe_string(ticker, 'indexPrice'),
3096
- 'markPrice': self.safe_string(ticker, 'markPrice'),
3207
+ 'markPrice': markPrice,
3097
3208
  'info': ticker,
3098
3209
  }, market)
3099
3210
 
@@ -3103,9 +3214,11 @@ class bitget(Exchange, ImplicitAPI):
3103
3214
 
3104
3215
  https://www.bitget.com/api-doc/spot/market/Get-Tickers
3105
3216
  https://www.bitget.com/api-doc/contract/market/Get-Ticker
3217
+ https://www.bitget.com/api-doc/uta/public/Tickers
3106
3218
 
3107
3219
  :param str symbol: unified symbol of the market to fetch the ticker for
3108
3220
  :param dict [params]: extra parameters specific to the exchange API endpoint
3221
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3109
3222
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
3110
3223
  """
3111
3224
  await self.load_markets()
@@ -3113,12 +3226,17 @@ class bitget(Exchange, ImplicitAPI):
3113
3226
  request: dict = {
3114
3227
  'symbol': market['id'],
3115
3228
  }
3229
+ productType = None
3230
+ productType, params = self.handle_product_type_and_params(market, params)
3116
3231
  response = None
3117
- if market['spot']:
3232
+ uta = None
3233
+ uta, params = self.handle_option_and_params(params, 'fetchTicker', 'uta', False)
3234
+ if uta:
3235
+ request['category'] = productType
3236
+ response = await self.publicUtaGetV3MarketTickers(self.extend(request, params))
3237
+ elif market['spot']:
3118
3238
  response = await self.publicSpotGetV2SpotMarketTickers(self.extend(request, params))
3119
3239
  else:
3120
- productType = None
3121
- productType, params = self.handle_product_type_and_params(market, params)
3122
3240
  request['productType'] = productType
3123
3241
  response = await self.publicMixGetV2MixMarketTicker(self.extend(request, params))
3124
3242
  #
@@ -3152,34 +3270,94 @@ class bitget(Exchange, ImplicitAPI):
3152
3270
  #
3153
3271
  # swap and future
3154
3272
  #
3155
- # {
3273
+ # {
3156
3274
  # "code": "00000",
3157
3275
  # "msg": "success",
3158
- # "requestTime": 1700533070357,
3276
+ # "requestTime": 1750332210369,
3159
3277
  # "data": [
3160
3278
  # {
3161
3279
  # "symbol": "BTCUSDT",
3162
- # "lastPr": "37577.2",
3163
- # "askPr": "37577.3",
3164
- # "bidPr": "37577.2",
3165
- # "bidSz": "3.679",
3166
- # "askSz": "0.02",
3167
- # "high24h": "37765",
3168
- # "low24h": "36628.9",
3169
- # "ts": "1700533070359",
3170
- # "change24h": "0.00288",
3171
- # "baseVolume": "108606.181",
3172
- # "quoteVolume": "4051316303.9608",
3173
- # "usdtVolume": "4051316303.9608",
3174
- # "openUtc": "37451.5",
3175
- # "changeUtc24h": "0.00336",
3176
- # "indexPrice": "37574.489253",
3177
- # "fundingRate": "0.0001",
3178
- # "holdingAmount": "53464.529",
3280
+ # "lastPr": "104823.8",
3281
+ # "askPr": "104823.8",
3282
+ # "bidPr": "104823.5",
3283
+ # "bidSz": "0.703",
3284
+ # "askSz": "13.894",
3285
+ # "high24h": "105289.3",
3286
+ # "low24h": "103447.9",
3287
+ # "ts": "1750332210370",
3288
+ # "change24h": "0.00471",
3289
+ # "baseVolume": "79089.5675",
3290
+ # "quoteVolume": "8274870921.80485",
3291
+ # "usdtVolume": "8274870921.80485",
3292
+ # "openUtc": "104833",
3293
+ # "changeUtc24h": "-0.00009",
3294
+ # "indexPrice": "104881.953125",
3295
+ # "fundingRate": "-0.000014",
3296
+ # "holdingAmount": "7452.6421",
3179
3297
  # "deliveryStartTime": null,
3180
3298
  # "deliveryTime": null,
3181
3299
  # "deliveryStatus": "",
3182
- # "open24h": "37235.7"
3300
+ # "open24h": "104332.3",
3301
+ # "markPrice": "104824.2"
3302
+ # }
3303
+ # ]
3304
+ # }
3305
+ #
3306
+ # spot uta
3307
+ #
3308
+ # {
3309
+ # "code": "00000",
3310
+ # "msg": "success",
3311
+ # "requestTime": 1750330653575,
3312
+ # "data": [
3313
+ # {
3314
+ # "category": "SPOT",
3315
+ # "symbol": "BTCUSDT",
3316
+ # "ts": "1750330651972",
3317
+ # "lastPrice": "104900.2",
3318
+ # "openPrice24h": "104321.2",
3319
+ # "highPrice24h": "107956.8",
3320
+ # "lowPrice24h": "103600.1",
3321
+ # "ask1Price": "104945.8",
3322
+ # "bid1Price": "104880.6",
3323
+ # "bid1Size": "0.266534",
3324
+ # "ask1Size": "0.014001",
3325
+ # "price24hPcnt": "0.00555",
3326
+ # "volume24h": "355.941109",
3327
+ # "turnover24h": "37302936.008134"
3328
+ # }
3329
+ # ]
3330
+ # }
3331
+ #
3332
+ # swap and future uta
3333
+ #
3334
+ # {
3335
+ # "code": "00000",
3336
+ # "msg": "success",
3337
+ # "requestTime": 1750332731203,
3338
+ # "data": [
3339
+ # {
3340
+ # "category": "USDT-FUTURES",
3341
+ # "symbol": "BTCUSDT",
3342
+ # "ts": "1750332730472",
3343
+ # "lastPrice": "104738",
3344
+ # "openPrice24h": "104374",
3345
+ # "highPrice24h": "105289.3",
3346
+ # "lowPrice24h": "103447.9",
3347
+ # "ask1Price": "104738",
3348
+ # "bid1Price": "104737.7",
3349
+ # "bid1Size": "2.036",
3350
+ # "ask1Size": "8.094",
3351
+ # "price24hPcnt": "0.00349",
3352
+ # "volume24h": "79101.6477",
3353
+ # "turnover24h": "8276293391.45973",
3354
+ # "indexPrice": "104785.956168",
3355
+ # "markPrice": "104738",
3356
+ # "fundingRate": "-0.000007",
3357
+ # "openInterest": "7465.5938",
3358
+ # "deliveryStartTime": "",
3359
+ # "deliveryTime": "",
3360
+ # "deliveryStatus": ""
3183
3361
  # }
3184
3362
  # ]
3185
3363
  # }
@@ -3219,9 +3397,11 @@ class bitget(Exchange, ImplicitAPI):
3219
3397
 
3220
3398
  https://www.bitget.com/api-doc/spot/market/Get-Tickers
3221
3399
  https://www.bitget.com/api-doc/contract/market/Get-All-Symbol-Ticker
3400
+ https://www.bitget.com/api-doc/uta/public/Tickers
3222
3401
 
3223
3402
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
3224
3403
  :param dict [params]: extra parameters specific to the exchange API endpoint
3404
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3225
3405
  :param str [params.subType]: *contract only* 'linear', 'inverse'
3226
3406
  :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
3227
3407
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -3242,7 +3422,15 @@ class bitget(Exchange, ImplicitAPI):
3242
3422
  productType = None
3243
3423
  productType, params = self.handle_product_type_and_params(market, params)
3244
3424
  # only if passedSubType and productType is None, then use spot
3245
- if type == 'spot' and passedSubType is None:
3425
+ uta = None
3426
+ uta, params = self.handle_option_and_params(params, 'fetchTickers', 'uta', False)
3427
+ if uta:
3428
+ symbolsLength = len(symbols)
3429
+ if (symbols is not None) and (symbolsLength == 1):
3430
+ request['symbol'] = market['id']
3431
+ request['category'] = productType
3432
+ response = await self.publicUtaGetV3MarketTickers(self.extend(request, params))
3433
+ elif type == 'spot' and passedSubType is None:
3246
3434
  response = await self.publicSpotGetV2SpotMarketTickers(self.extend(request, params))
3247
3435
  else:
3248
3436
  request['productType'] = productType
@@ -3304,6 +3492,65 @@ class bitget(Exchange, ImplicitAPI):
3304
3492
  # ]
3305
3493
  # }
3306
3494
  #
3495
+ # spot uta
3496
+ #
3497
+ # {
3498
+ # "code": "00000",
3499
+ # "msg": "success",
3500
+ # "requestTime": 1750330653575,
3501
+ # "data": [
3502
+ # {
3503
+ # "category": "SPOT",
3504
+ # "symbol": "BTCUSDT",
3505
+ # "ts": "1750330651972",
3506
+ # "lastPrice": "104900.2",
3507
+ # "openPrice24h": "104321.2",
3508
+ # "highPrice24h": "107956.8",
3509
+ # "lowPrice24h": "103600.1",
3510
+ # "ask1Price": "104945.8",
3511
+ # "bid1Price": "104880.6",
3512
+ # "bid1Size": "0.266534",
3513
+ # "ask1Size": "0.014001",
3514
+ # "price24hPcnt": "0.00555",
3515
+ # "volume24h": "355.941109",
3516
+ # "turnover24h": "37302936.008134"
3517
+ # }
3518
+ # ]
3519
+ # }
3520
+ #
3521
+ # swap and future uta
3522
+ #
3523
+ # {
3524
+ # "code": "00000",
3525
+ # "msg": "success",
3526
+ # "requestTime": 1750332731203,
3527
+ # "data": [
3528
+ # {
3529
+ # "category": "USDT-FUTURES",
3530
+ # "symbol": "BTCUSDT",
3531
+ # "ts": "1750332730472",
3532
+ # "lastPrice": "104738",
3533
+ # "openPrice24h": "104374",
3534
+ # "highPrice24h": "105289.3",
3535
+ # "lowPrice24h": "103447.9",
3536
+ # "ask1Price": "104738",
3537
+ # "bid1Price": "104737.7",
3538
+ # "bid1Size": "2.036",
3539
+ # "ask1Size": "8.094",
3540
+ # "price24hPcnt": "0.00349",
3541
+ # "volume24h": "79101.6477",
3542
+ # "turnover24h": "8276293391.45973",
3543
+ # "indexPrice": "104785.956168",
3544
+ # "markPrice": "104738",
3545
+ # "fundingRate": "-0.000007",
3546
+ # "openInterest": "7465.5938",
3547
+ # "deliveryStartTime": "",
3548
+ # "deliveryTime": "",
3549
+ # "deliveryStatus": ""
3550
+ # }
3551
+ # ]
3552
+ # }
3553
+ #
3307
3554
  data = self.safe_list(response, 'data', [])
3308
3555
  return self.parse_tickers(data, symbols)
3309
3556
 
@@ -3390,19 +3637,53 @@ class bitget(Exchange, ImplicitAPI):
3390
3637
  # "cTime": "1700720700342"
3391
3638
  # }
3392
3639
  #
3640
+ # uta fetchTrades
3641
+ #
3642
+ # {
3643
+ # "execId": "1319896716324937729",
3644
+ # "price": "105909.1",
3645
+ # "size": "6.3090",
3646
+ # "side": "sell",
3647
+ # "ts": "1750413820344"
3648
+ # }
3649
+ #
3650
+ # uta fetchMyTrades
3651
+ #
3652
+ # {
3653
+ # "execId": "1322441401010528257",
3654
+ # "orderId": "1322441400976261120",
3655
+ # "category": "USDT-FUTURES",
3656
+ # "symbol": "BTCUSDT",
3657
+ # "orderType": "market",
3658
+ # "side": "sell",
3659
+ # "execPrice": "107005.4",
3660
+ # "execQty": "0.0001",
3661
+ # "execValue": "10.7005",
3662
+ # "tradeScope": "taker",
3663
+ # "feeDetail": [{
3664
+ # "feeCoin": "USDT",
3665
+ # "fee":"0.00642032"
3666
+ # }],
3667
+ # "createdTime": "1751020520451",
3668
+ # "updatedTime": "1751020520458",
3669
+ # "execPnl": "0.00017"
3670
+ # }
3671
+ #
3393
3672
  marketId = self.safe_string(trade, 'symbol')
3394
3673
  symbol = self.safe_symbol(marketId, market)
3395
- timestamp = self.safe_integer_2(trade, 'cTime', 'ts')
3674
+ timestamp = self.safe_integer_n(trade, ['cTime', 'ts', 'createdTime'])
3396
3675
  fee = None
3397
3676
  feeDetail = self.safe_value(trade, 'feeDetail')
3398
3677
  posMode = self.safe_string(trade, 'posMode')
3399
- feeStructure = feeDetail[0] if (posMode is not None) else feeDetail
3678
+ category = self.safe_string(trade, 'category')
3679
+ isFeeStructure = (posMode is not None) or (category is not None)
3680
+ feeStructure = feeDetail[0] if isFeeStructure else feeDetail
3400
3681
  if feeStructure is not None:
3401
3682
  currencyCode = self.safe_currency_code(self.safe_string(feeStructure, 'feeCoin'))
3402
3683
  fee = {
3403
3684
  'currency': currencyCode,
3404
3685
  }
3405
- feeCostString = self.safe_string(feeStructure, 'totalFee')
3686
+ feeCostString = self.safe_string_2(feeStructure, 'totalFee', 'fee')
3406
3687
  deduction = self.safe_string(feeStructure, 'deduction') is True if 'yes' else False
3407
3688
  if deduction:
3408
3689
  fee['cost'] = feeCostString
@@ -3410,15 +3691,15 @@ class bitget(Exchange, ImplicitAPI):
3410
3691
  fee['cost'] = Precise.string_neg(feeCostString)
3411
3692
  return self.safe_trade({
3412
3693
  'info': trade,
3413
- 'id': self.safe_string(trade, 'tradeId'),
3694
+ 'id': self.safe_string_2(trade, 'tradeId', 'execId'),
3414
3695
  'order': self.safe_string(trade, 'orderId'),
3415
3696
  'symbol': symbol,
3416
3697
  'side': self.safe_string_lower(trade, 'side'),
3417
3698
  'type': self.safe_string(trade, 'orderType'),
3418
3699
  'takerOrMaker': self.safe_string(trade, 'tradeScope'),
3419
- 'price': self.safe_string_2(trade, 'priceAvg', 'price'),
3420
- 'amount': self.safe_string_2(trade, 'baseVolume', 'size'),
3421
- 'cost': self.safe_string_2(trade, 'quoteVolume', 'amount'),
3700
+ 'price': self.safe_string_n(trade, ['priceAvg', 'price', 'execPrice']),
3701
+ 'amount': self.safe_string_n(trade, ['baseVolume', 'size', 'execQty']),
3702
+ 'cost': self.safe_string_n(trade, ['quoteVolume', 'amount', 'execValue']),
3422
3703
  'timestamp': timestamp,
3423
3704
  'datetime': self.iso8601(timestamp),
3424
3705
  'fee': fee,
@@ -3432,11 +3713,13 @@ class bitget(Exchange, ImplicitAPI):
3432
3713
  https://www.bitget.com/api-doc/spot/market/Get-Market-Trades
3433
3714
  https://www.bitget.com/api-doc/contract/market/Get-Recent-Fills
3434
3715
  https://www.bitget.com/api-doc/contract/market/Get-Fills-History
3716
+ https://www.bitget.com/api-doc/uta/public/Fills
3435
3717
 
3436
3718
  :param str symbol: unified symbol of the market to fetch trades for
3437
3719
  :param int [since]: timestamp in ms of the earliest trade to fetch
3438
3720
  :param int [limit]: the maximum amount of trades to fetch
3439
3721
  :param dict [params]: extra parameters specific to the exchange API endpoint
3722
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3440
3723
  :param int [params.until]: *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* the latest time in ms to fetch trades for
3441
3724
  :param boolean [params.paginate]: *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* default False, when True will automatically paginate by calling self endpoint multiple times
3442
3725
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
@@ -3450,14 +3733,28 @@ class bitget(Exchange, ImplicitAPI):
3450
3733
  request: dict = {
3451
3734
  'symbol': market['id'],
3452
3735
  }
3736
+ uta = None
3737
+ uta, params = self.handle_option_and_params(params, 'fetchTrades', 'uta', False)
3453
3738
  if limit is not None:
3454
- if market['contract']:
3739
+ if uta:
3740
+ request['limit'] = min(limit, 100)
3741
+ elif market['contract']:
3455
3742
  request['limit'] = min(limit, 1000)
3456
3743
  else:
3457
3744
  request['limit'] = limit
3458
3745
  options = self.safe_value(self.options, 'fetchTrades', {})
3459
3746
  response = None
3460
- if market['spot']:
3747
+ productType = None
3748
+ productType, params = self.handle_product_type_and_params(market, params)
3749
+ if uta:
3750
+ if productType == 'SPOT':
3751
+ marginMode = None
3752
+ marginMode, params = self.handle_margin_mode_and_params('fetchTrades', params)
3753
+ if marginMode is not None:
3754
+ productType = 'MARGIN'
3755
+ request['category'] = productType
3756
+ response = await self.publicUtaGetV3MarketFills(self.extend(request, params))
3757
+ elif market['spot']:
3461
3758
  spotOptions = self.safe_value(options, 'spot', {})
3462
3759
  defaultSpotMethod = self.safe_string(spotOptions, 'method', 'publicSpotGetV2SpotMarketFillsHistory')
3463
3760
  spotMethod = self.safe_string(params, 'method', defaultSpotMethod)
@@ -3474,8 +3771,6 @@ class bitget(Exchange, ImplicitAPI):
3474
3771
  defaultSwapMethod = self.safe_string(swapOptions, 'method', 'publicMixGetV2MixMarketFillsHistory')
3475
3772
  swapMethod = self.safe_string(params, 'method', defaultSwapMethod)
3476
3773
  params = self.omit(params, 'method')
3477
- productType = None
3478
- productType, params = self.handle_product_type_and_params(market, params)
3479
3774
  request['productType'] = productType
3480
3775
  if swapMethod == 'publicMixGetV2MixMarketFillsHistory':
3481
3776
  request, params = self.handle_until_option('endTime', request, params)
@@ -3521,6 +3816,23 @@ class bitget(Exchange, ImplicitAPI):
3521
3816
  # ]
3522
3817
  # }
3523
3818
  #
3819
+ # uta
3820
+ #
3821
+ # {
3822
+ # "code": "00000",
3823
+ # "msg": "success",
3824
+ # "requestTime": 1750413823980,
3825
+ # "data": [
3826
+ # {
3827
+ # "execId": "1319896716324937729",
3828
+ # "price": "105909.1",
3829
+ # "size": "6.3090",
3830
+ # "side": "sell",
3831
+ # "ts": "1750413820344"
3832
+ # }
3833
+ # ]
3834
+ # }
3835
+ #
3524
3836
  data = self.safe_list(response, 'data', [])
3525
3837
  return self.parse_trades(data, market, since, limit)
3526
3838
 
@@ -3702,13 +4014,15 @@ class bitget(Exchange, ImplicitAPI):
3702
4014
  # "1399132.341"
3703
4015
  # ]
3704
4016
  #
4017
+ inverse = self.safe_bool(market, 'inverse')
4018
+ volumeIndex = 6 if inverse else 5
3705
4019
  return [
3706
4020
  self.safe_integer(ohlcv, 0),
3707
4021
  self.safe_number(ohlcv, 1),
3708
4022
  self.safe_number(ohlcv, 2),
3709
4023
  self.safe_number(ohlcv, 3),
3710
4024
  self.safe_number(ohlcv, 4),
3711
- self.safe_number(ohlcv, 5),
4025
+ self.safe_number(ohlcv, volumeIndex),
3712
4026
  ]
3713
4027
 
3714
4028
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
@@ -3721,12 +4035,14 @@ class bitget(Exchange, ImplicitAPI):
3721
4035
  https://www.bitget.com/api-doc/contract/market/Get-History-Candle-Data
3722
4036
  https://www.bitget.com/api-doc/contract/market/Get-History-Index-Candle-Data
3723
4037
  https://www.bitget.com/api-doc/contract/market/Get-History-Mark-Candle-Data
4038
+ https://www.bitget.com/api-doc/uta/public/Get-Candle-Data
3724
4039
 
3725
4040
  :param str symbol: unified symbol of the market to fetch OHLCV data for
3726
4041
  :param str timeframe: the length of time each candle represents
3727
4042
  :param int [since]: timestamp in ms of the earliest candle to fetch
3728
4043
  :param int [limit]: the maximum amount of candles to fetch
3729
4044
  :param dict [params]: extra parameters specific to the exchange API endpoint
4045
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3730
4046
  :param int [params.until]: timestamp in ms of the latest candle to fetch
3731
4047
  :param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
3732
4048
  :param boolean [params.useHistoryEndpointForPagination]: whether to force to use historical endpoint for pagination(default True)
@@ -3746,12 +4062,20 @@ class bitget(Exchange, ImplicitAPI):
3746
4062
  limitForPagination = maxLimitForHistoryEndpoint if useHistoryEndpointForPagination else maxLimitForRecentEndpoint
3747
4063
  return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, limitForPagination)
3748
4064
  market = self.market(symbol)
3749
- marketType = 'spot' if market['spot'] else 'swap'
3750
- timeframes = self.options['timeframes'][marketType]
3751
4065
  request: dict = {
3752
4066
  'symbol': market['id'],
3753
- 'granularity': self.safe_string(timeframes, timeframe, timeframe),
3754
4067
  }
4068
+ marketType = None
4069
+ timeframes = None
4070
+ uta = None
4071
+ uta, params = self.handle_option_and_params(params, 'fetchOHLCV', 'uta', False)
4072
+ if uta:
4073
+ timeframes = self.options['timeframes']['uta']
4074
+ request['interval'] = self.safe_string(timeframes, timeframe, timeframe)
4075
+ else:
4076
+ marketType = 'spot' if market['spot'] else 'swap'
4077
+ timeframes = self.options['timeframes'][marketType]
4078
+ request['granularity'] = self.safe_string(timeframes, timeframe, timeframe)
3755
4079
  msInDay = 86400000
3756
4080
  now = self.milliseconds()
3757
4081
  duration = self.parse_timeframe(timeframe) * 1000
@@ -3812,7 +4136,19 @@ class bitget(Exchange, ImplicitAPI):
3812
4136
  request['limit'] = limit
3813
4137
  # make request
3814
4138
  response = None
3815
- if market['spot']:
4139
+ productType = None
4140
+ priceType = None
4141
+ priceType, params = self.handle_param_string(params, 'price')
4142
+ productType, params = self.handle_product_type_and_params(market, params)
4143
+ if uta:
4144
+ if priceType is not None:
4145
+ if priceType == 'mark':
4146
+ request['type'] = 'MARK'
4147
+ elif priceType == 'index':
4148
+ request['type'] = 'INDEX'
4149
+ request['category'] = productType
4150
+ response = await self.publicUtaGetV3MarketCandles(self.extend(request, params))
4151
+ elif market['spot']:
3816
4152
  # checks if we need history endpoint
3817
4153
  if historicalEndpointNeeded:
3818
4154
  response = await self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
@@ -3822,10 +4158,6 @@ class bitget(Exchange, ImplicitAPI):
3822
4158
  limit = 1000
3823
4159
  response = await self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3824
4160
  else:
3825
- priceType = None
3826
- priceType, params = self.handle_param_string(params, 'price')
3827
- productType = None
3828
- productType, params = self.handle_product_type_and_params(market, params)
3829
4161
  request['productType'] = productType
3830
4162
  extended = self.extend(request, params)
3831
4163
  if not historicalEndpointNeeded and (priceType == 'mark' or priceType == 'index'):
@@ -3863,9 +4195,11 @@ class bitget(Exchange, ImplicitAPI):
3863
4195
  https://www.bitget.com/api-doc/margin/isolated/account/Get-Isolated-Assets
3864
4196
  https://bitgetlimited.github.io/apidoc/en/margin/#get-cross-assets
3865
4197
  https://bitgetlimited.github.io/apidoc/en/margin/#get-isolated-assets
4198
+ https://www.bitget.com/api-doc/uta/account/Get-Account
3866
4199
 
3867
4200
  :param dict [params]: extra parameters specific to the exchange API endpoint
3868
4201
  :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
4202
+ :param str [params.uta]: set to True for the unified trading account(uta), defaults to False
3869
4203
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
3870
4204
  """
3871
4205
  await self.load_markets()
@@ -3873,9 +4207,16 @@ class bitget(Exchange, ImplicitAPI):
3873
4207
  marketType = None
3874
4208
  marginMode = None
3875
4209
  response = None
4210
+ uta = None
4211
+ uta, params = self.handle_option_and_params(params, 'fetchBalance', 'uta', False)
3876
4212
  marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
3877
4213
  marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
3878
- if (marketType == 'swap') or (marketType == 'future'):
4214
+ if uta:
4215
+ response = await self.privateUtaGetV3AccountAssets(self.extend(request, params))
4216
+ results = self.safe_dict(response, 'data', {})
4217
+ assets = self.safe_list(results, 'assets', [])
4218
+ return self.parse_uta_balance(assets)
4219
+ elif (marketType == 'swap') or (marketType == 'future'):
3879
4220
  productType = None
3880
4221
  productType, params = self.handle_product_type_and_params(None, params)
3881
4222
  request['productType'] = productType
@@ -3975,9 +4316,66 @@ class bitget(Exchange, ImplicitAPI):
3975
4316
  # ]
3976
4317
  # }
3977
4318
  #
4319
+ # uta
4320
+ #
4321
+ # {
4322
+ # "code": "00000",
4323
+ # "msg": "success",
4324
+ # "requestTime": 1749980065089,
4325
+ # "data": {
4326
+ # "accountEquity": "11.13919278",
4327
+ # "usdtEquity": "11.13921165",
4328
+ # "btcEquity": "0.00011256",
4329
+ # "unrealisedPnl": "0",
4330
+ # "usdtUnrealisedPnl": "0",
4331
+ # "btcUnrealizedPnl": "0",
4332
+ # "effEquity": "6.19299777",
4333
+ # "mmr": "0",
4334
+ # "imr": "0",
4335
+ # "mgnRatio": "0",
4336
+ # "positionMgnRatio": "0",
4337
+ # "assets": [
4338
+ # {
4339
+ # "coin": "USDT",
4340
+ # "equity": "6.19300826",
4341
+ # "usdValue": "6.19299777",
4342
+ # "balance": "6.19300826",
4343
+ # "available": "6.19300826",
4344
+ # "debt": "0",
4345
+ # "locked": "0"
4346
+ # }
4347
+ # ]
4348
+ # }
4349
+ # }
4350
+ #
3978
4351
  data = self.safe_value(response, 'data', [])
3979
4352
  return self.parse_balance(data)
3980
4353
 
4354
+ def parse_uta_balance(self, balance) -> Balances:
4355
+ result: dict = {'info': balance}
4356
+ #
4357
+ # {
4358
+ # "coin": "USDT",
4359
+ # "equity": "6.19300826",
4360
+ # "usdValue": "6.19299777",
4361
+ # "balance": "6.19300826",
4362
+ # "available": "6.19300826",
4363
+ # "debt": "0",
4364
+ # "locked": "0"
4365
+ # }
4366
+ #
4367
+ for i in range(0, len(balance)):
4368
+ entry = balance[i]
4369
+ account = self.account()
4370
+ currencyId = self.safe_string(entry, 'coin')
4371
+ code = self.safe_currency_code(currencyId)
4372
+ account['debt'] = self.safe_string(entry, 'debt')
4373
+ account['used'] = self.safe_string(entry, 'locked')
4374
+ account['free'] = self.safe_string(entry, 'available')
4375
+ account['total'] = self.safe_string(entry, 'balance')
4376
+ result[code] = account
4377
+ return self.safe_balance(result)
4378
+
3981
4379
  def parse_balance(self, balance) -> Balances:
3982
4380
  result: dict = {'info': balance}
3983
4381
  #
@@ -4111,7 +4509,7 @@ class bitget(Exchange, ImplicitAPI):
4111
4509
  # },
4112
4510
  # ]
4113
4511
  #
4114
- # spot, swap, future and spot margin: cancelOrder, cancelOrders
4512
+ # spot, swap, future, spot margin and uta: cancelOrder, cancelOrders, cancelAllOrders
4115
4513
  #
4116
4514
  # {
4117
4515
  # "orderId": "1098758604547850241",
@@ -4240,6 +4638,66 @@ class bitget(Exchange, ImplicitAPI):
4240
4638
  # "stopLossTriggerType": "fill_price",
4241
4639
  # }
4242
4640
  #
4641
+ # uta: fetchOrder, fetchOpenOrders, fetchCanceledAndClosedOrders
4642
+ #
4643
+ # {
4644
+ # "orderId": "1320244799629316096",
4645
+ # "clientOid": "1320244799633510400",
4646
+ # "category": "USDT-FUTURES",
4647
+ # "symbol": "BTCUSDT",
4648
+ # "orderType": "limit",
4649
+ # "side": "buy",
4650
+ # "price": "50000",
4651
+ # "qty": "0.001",
4652
+ # "amount": "0",
4653
+ # "cumExecQty": "0",
4654
+ # "cumExecValue": "0",
4655
+ # "avgPrice": "0",
4656
+ # "timeInForce": "gtc",
4657
+ # "orderStatus": "live",
4658
+ # "posSide": "long",
4659
+ # "holdMode": "hedge_mode",
4660
+ # "reduceOnly": "NO",
4661
+ # "feeDetail": [{
4662
+ # "feeCoin": "",
4663
+ # "fee": ""
4664
+ # }],
4665
+ # "createdTime": "1750496809871",
4666
+ # "updatedTime": "1750496809886",
4667
+ # "cancelReason": "",
4668
+ # "execType": "normal",
4669
+ # "stpMode": "none",
4670
+ # "tpTriggerBy": null,
4671
+ # "slTriggerBy": null,
4672
+ # "takeProfit": null,
4673
+ # "stopLoss": null,
4674
+ # "tpOrderType": null,
4675
+ # "slOrderType": null,
4676
+ # "tpLimitPrice": null,
4677
+ # "slLimitPrice": null
4678
+ # }
4679
+ #
4680
+ # uta trigger: fetchClosedOrders, fetchCanceledOrders
4681
+ #
4682
+ # {
4683
+ # "orderId": "1330984742276198400",
4684
+ # "clientOid": "1330984742276198400",
4685
+ # "symbol": "BTCUSDT",
4686
+ # "category": "USDT-FUTURES",
4687
+ # "qty": "0.001",
4688
+ # "posSide": "long",
4689
+ # "tpTriggerBy": "market",
4690
+ # "slTriggerBy": "mark",
4691
+ # "takeProfit": "",
4692
+ # "stopLoss": "112000",
4693
+ # "tpOrderType": "market",
4694
+ # "slOrderType": "limit",
4695
+ # "tpLimitPrice": "",
4696
+ # "slLimitPrice": "111000",
4697
+ # "createdTime": "1753057411736",
4698
+ # "updatedTime": "1753058267412"
4699
+ # }
4700
+ #
4243
4701
  errorMessage = self.safe_string(order, 'errorMsg')
4244
4702
  if errorMessage is not None:
4245
4703
  return self.safe_order({
@@ -4248,16 +4706,16 @@ class bitget(Exchange, ImplicitAPI):
4248
4706
  'clientOrderId': self.safe_string_2(order, 'clientOrderId', 'clientOid'),
4249
4707
  'status': 'rejected',
4250
4708
  }, market)
4251
- isContractOrder = ('posSide' in order)
4709
+ posSide = self.safe_string(order, 'posSide')
4710
+ isContractOrder = (posSide is not None)
4252
4711
  marketType = 'contract' if isContractOrder else 'spot'
4253
4712
  if market is not None:
4254
4713
  marketType = market['type']
4255
4714
  marketId = self.safe_string(order, 'symbol')
4256
4715
  market = self.safe_market(marketId, market, None, marketType)
4257
- timestamp = self.safe_integer_2(order, 'cTime', 'ctime')
4258
- updateTimestamp = self.safe_integer(order, 'uTime')
4259
- rawStatus = self.safe_string_2(order, 'status', 'state')
4260
- rawStatus = self.safe_string(order, 'planStatus', rawStatus)
4716
+ timestamp = self.safe_integer_n(order, ['cTime', 'ctime', 'createdTime'])
4717
+ updateTimestamp = self.safe_integer_2(order, 'uTime', 'updatedTime')
4718
+ rawStatus = self.safe_string_n(order, ['status', 'state', 'orderStatus', 'planStatus'])
4261
4719
  fee = None
4262
4720
  feeCostString = self.safe_string(order, 'fee')
4263
4721
  if feeCostString is not None:
@@ -4267,21 +4725,30 @@ class bitget(Exchange, ImplicitAPI):
4267
4725
  'currency': market['settle'],
4268
4726
  }
4269
4727
  feeDetail = self.safe_value(order, 'feeDetail')
4270
- if feeDetail is not None:
4271
- parsedFeeDetail = json.loads(feeDetail)
4272
- feeValues = list(parsedFeeDetail.values())
4273
- feeObject = None
4274
- for i in range(0, len(feeValues)):
4275
- feeValue = feeValues[i]
4276
- if self.safe_value(feeValue, 'feeCoinCode') is not None:
4277
- feeObject = feeValue
4278
- break
4728
+ uta = self.safe_string(order, 'category') is not None
4729
+ if uta:
4730
+ feeResult = self.safe_dict(feeDetail, 0, {})
4731
+ utaFee = self.safe_string(feeResult, 'fee')
4279
4732
  fee = {
4280
- 'cost': self.parse_number(Precise.string_neg(self.safe_string(feeObject, 'totalFee'))),
4281
- 'currency': self.safe_currency_code(self.safe_string(feeObject, 'feeCoinCode')),
4733
+ 'cost': self.parse_number(Precise.string_neg(utaFee)),
4734
+ 'currency': market['settle'],
4282
4735
  }
4736
+ else:
4737
+ if feeDetail is not None:
4738
+ parsedFeeDetail = json.loads(feeDetail)
4739
+ feeValues = list(parsedFeeDetail.values())
4740
+ feeObject = None
4741
+ for i in range(0, len(feeValues)):
4742
+ feeValue = feeValues[i]
4743
+ if self.safe_value(feeValue, 'feeCoinCode') is not None:
4744
+ feeObject = feeValue
4745
+ break
4746
+ fee = {
4747
+ 'cost': self.parse_number(Precise.string_neg(self.safe_string(feeObject, 'totalFee'))),
4748
+ 'currency': self.safe_currency_code(self.safe_string(feeObject, 'feeCoinCode')),
4749
+ }
4283
4750
  postOnly = None
4284
- timeInForce = self.safe_string_upper(order, 'force')
4751
+ timeInForce = self.safe_string_upper_2(order, 'force', 'timeInForce')
4285
4752
  if timeInForce == 'POST_ONLY':
4286
4753
  postOnly = True
4287
4754
  timeInForce = 'PO'
@@ -4297,7 +4764,7 @@ class bitget(Exchange, ImplicitAPI):
4297
4764
  price = self.safe_string(order, 'priceAvg')
4298
4765
  average = self.safe_string(order, 'basePrice')
4299
4766
  else:
4300
- price = self.safe_string_2(order, 'price', 'executePrice')
4767
+ price = self.safe_string_n(order, ['price', 'executePrice', 'slLimitPrice', 'tpLimitPrice'])
4301
4768
  average = self.safe_string(order, 'priceAvg')
4302
4769
  size = None
4303
4770
  filled = None
@@ -4307,8 +4774,8 @@ class bitget(Exchange, ImplicitAPI):
4307
4774
  size = baseSize
4308
4775
  filled = self.safe_string(order, 'size')
4309
4776
  else:
4310
- size = self.safe_string(order, 'size')
4311
- filled = self.safe_string(order, 'baseVolume')
4777
+ size = self.safe_string_2(order, 'size', 'qty')
4778
+ filled = self.safe_string_2(order, 'baseVolume', 'cumExecQty')
4312
4779
  side = self.safe_string(order, 'side')
4313
4780
  posMode = self.safe_string(order, 'posMode')
4314
4781
  if posMode == 'hedge_mode' and reduceOnly:
@@ -4341,8 +4808,8 @@ class bitget(Exchange, ImplicitAPI):
4341
4808
  'postOnly': postOnly,
4342
4809
  'reduceOnly': reduceOnly,
4343
4810
  'triggerPrice': self.safe_number(order, 'triggerPrice'),
4344
- 'takeProfitPrice': self.safe_number_2(order, 'presetStopSurplusPrice', 'stopSurplusTriggerPrice'),
4345
- 'stopLossPrice': self.safe_number_2(order, 'presetStopLossPrice', 'stopLossTriggerPrice'),
4811
+ 'takeProfitPrice': self.safe_number_n(order, ['presetStopSurplusPrice', 'stopSurplusTriggerPrice', 'takeProfit']),
4812
+ 'stopLossPrice': self.safe_number_n(order, ['presetStopLossPrice', 'stopLossTriggerPrice', 'stopLoss']),
4346
4813
  'status': self.parse_order_status(rawStatus),
4347
4814
  'fee': fee,
4348
4815
  'trades': None,
@@ -4381,6 +4848,8 @@ class bitget(Exchange, ImplicitAPI):
4381
4848
  https://www.bitget.com/api-doc/contract/plan/Place-Plan-Order
4382
4849
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Place-Order
4383
4850
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
4851
+ https://www.bitget.com/api-doc/uta/trade/Place-Order
4852
+ https://www.bitget.com/api-doc/uta/strategy/Place-Strategy-Order
4384
4853
 
4385
4854
  :param str symbol: unified symbol of the market to create an order in
4386
4855
  :param str type: 'market' or 'limit'
@@ -4410,6 +4879,8 @@ class bitget(Exchange, ImplicitAPI):
4410
4879
  :param boolean [params.oneWayMode]: *swap and future only* required to set self to True in one_way_mode and you can leave self in hedge_mode, can adjust the mode using the setPositionMode() method
4411
4880
  :param bool [params.hedged]: *swap and future only* True for hedged mode, False for one way mode, default is False
4412
4881
  :param bool [params.reduceOnly]: True or False whether the order is reduce-only
4882
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4883
+ :param str [params.posSide]: *uta only* hedged two-way position side, long or short
4413
4884
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4414
4885
  """
4415
4886
  await self.load_markets()
@@ -4425,24 +4896,33 @@ class bitget(Exchange, ImplicitAPI):
4425
4896
  isStopLossTriggerOrder = stopLossTriggerPrice is not None
4426
4897
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
4427
4898
  isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
4428
- request = self.create_order_request(symbol, type, side, amount, price, params)
4429
4899
  response = None
4430
- if market['spot']:
4431
- if isTriggerOrder:
4432
- response = await self.privateSpotPostV2SpotTradePlacePlanOrder(request)
4433
- elif marginMode == 'isolated':
4434
- response = await self.privateMarginPostV2MarginIsolatedPlaceOrder(request)
4435
- elif marginMode == 'cross':
4436
- response = await self.privateMarginPostV2MarginCrossedPlaceOrder(request)
4900
+ uta = None
4901
+ uta, params = self.handle_option_and_params(params, 'createOrder', 'uta', False)
4902
+ if uta:
4903
+ request = self.create_uta_order_request(symbol, type, side, amount, price, params)
4904
+ if isStopLossOrTakeProfitTrigger:
4905
+ response = await self.privateUtaPostV3TradePlaceStrategyOrder(request)
4437
4906
  else:
4438
- response = await self.privateSpotPostV2SpotTradePlaceOrder(request)
4907
+ response = await self.privateUtaPostV3TradePlaceOrder(request)
4439
4908
  else:
4440
- if isTriggerOrder or isTrailingPercentOrder:
4441
- response = await self.privateMixPostV2MixOrderPlacePlanOrder(request)
4442
- elif isStopLossOrTakeProfitTrigger:
4443
- response = await self.privateMixPostV2MixOrderPlaceTpslOrder(request)
4909
+ request = self.create_order_request(symbol, type, side, amount, price, params)
4910
+ if market['spot']:
4911
+ if isTriggerOrder:
4912
+ response = await self.privateSpotPostV2SpotTradePlacePlanOrder(request)
4913
+ elif marginMode == 'isolated':
4914
+ response = await self.privateMarginPostV2MarginIsolatedPlaceOrder(request)
4915
+ elif marginMode == 'cross':
4916
+ response = await self.privateMarginPostV2MarginCrossedPlaceOrder(request)
4917
+ else:
4918
+ response = await self.privateSpotPostV2SpotTradePlaceOrder(request)
4444
4919
  else:
4445
- response = await self.privateMixPostV2MixOrderPlaceOrder(request)
4920
+ if isTriggerOrder or isTrailingPercentOrder:
4921
+ response = await self.privateMixPostV2MixOrderPlacePlanOrder(request)
4922
+ elif isStopLossOrTakeProfitTrigger:
4923
+ response = await self.privateMixPostV2MixOrderPlaceTpslOrder(request)
4924
+ else:
4925
+ response = await self.privateMixPostV2MixOrderPlaceOrder(request)
4446
4926
  #
4447
4927
  # {
4448
4928
  # "code": "00000",
@@ -4457,24 +4937,124 @@ class bitget(Exchange, ImplicitAPI):
4457
4937
  data = self.safe_dict(response, 'data', {})
4458
4938
  return self.parse_order(data, market)
4459
4939
 
4460
- def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
4940
+ def create_uta_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
4461
4941
  market = self.market(symbol)
4462
- marketType = None
4463
- marginMode = None
4464
- marketType, params = self.handle_market_type_and_params('createOrder', market, params)
4465
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
4942
+ productType = None
4943
+ productType, params = self.handle_product_type_and_params(market, params)
4944
+ if productType == 'SPOT':
4945
+ marginMode = None
4946
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
4947
+ if marginMode is not None:
4948
+ productType = 'MARGIN'
4466
4949
  request: dict = {
4950
+ 'category': productType,
4467
4951
  'symbol': market['id'],
4468
- 'orderType': type,
4952
+ 'qty': self.amount_to_precision(symbol, amount),
4953
+ 'side': side,
4469
4954
  }
4470
- isMarketOrder = type == 'market'
4471
- triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
4472
- stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
4473
- takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
4955
+ clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
4956
+ if clientOrderId is not None:
4957
+ request['clientOid'] = clientOrderId
4958
+ params = self.omit(params, 'clientOrderId')
4959
+ stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
4960
+ takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
4474
4961
  stopLoss = self.safe_value(params, 'stopLoss')
4475
4962
  takeProfit = self.safe_value(params, 'takeProfit')
4476
- isTriggerOrder = triggerPrice is not None
4477
- isStopLossTriggerOrder = stopLossTriggerPrice is not None
4963
+ isStopLoss = stopLoss is not None
4964
+ isTakeProfit = takeProfit is not None
4965
+ isStopLossTrigger = stopLossTriggerPrice is not None
4966
+ isTakeProfitTrigger = takeProfitTriggerPrice is not None
4967
+ isStopLossOrTakeProfitTrigger = isStopLossTrigger or isTakeProfitTrigger
4968
+ if isStopLossOrTakeProfitTrigger:
4969
+ if isStopLossTrigger:
4970
+ slType = self.safe_string(params, 'slTriggerBy', 'mark')
4971
+ request['slTriggerBy'] = slType
4972
+ request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
4973
+ if price is not None:
4974
+ request['slLimitPrice'] = self.price_to_precision(symbol, price)
4975
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
4976
+ else:
4977
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
4978
+ elif isTakeProfitTrigger:
4979
+ tpType = self.safe_string(params, 'tpTriggerBy', 'mark')
4980
+ request['tpTriggerBy'] = tpType
4981
+ request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
4982
+ if price is not None:
4983
+ request['tpLimitPrice'] = self.price_to_precision(symbol, price)
4984
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
4985
+ else:
4986
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
4987
+ params = self.omit(params, ['stopLossPrice', 'takeProfitPrice'])
4988
+ else:
4989
+ if isStopLoss:
4990
+ slTriggerPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'stopPrice')
4991
+ slLimitPrice = self.safe_number(stopLoss, 'price')
4992
+ request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
4993
+ if slLimitPrice is not None:
4994
+ request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
4995
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
4996
+ else:
4997
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
4998
+ if isTakeProfit:
4999
+ tpTriggerPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'stopPrice')
5000
+ tpLimitPrice = self.safe_number(takeProfit, 'price')
5001
+ request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
5002
+ if tpLimitPrice is not None:
5003
+ request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
5004
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
5005
+ else:
5006
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
5007
+ isMarketOrder = type == 'market'
5008
+ if not isMarketOrder:
5009
+ request['price'] = self.price_to_precision(symbol, price)
5010
+ request['orderType'] = type
5011
+ exchangeSpecificTifParam = self.safe_string(params, 'timeInForce')
5012
+ postOnly = None
5013
+ postOnly, params = self.handle_post_only(isMarketOrder, exchangeSpecificTifParam == 'post_only', params)
5014
+ defaultTimeInForce = self.safe_string_upper(self.options, 'defaultTimeInForce')
5015
+ timeInForce = self.safe_string_upper(params, 'timeInForce', defaultTimeInForce)
5016
+ if postOnly:
5017
+ request['timeInForce'] = 'post_only'
5018
+ elif timeInForce == 'GTC':
5019
+ request['timeInForce'] = 'gtc'
5020
+ elif timeInForce == 'FOK':
5021
+ request['timeInForce'] = 'fok'
5022
+ elif timeInForce == 'IOC':
5023
+ request['timeInForce'] = 'ioc'
5024
+ reduceOnly = self.safe_bool(params, 'reduceOnly', False)
5025
+ hedged = None
5026
+ hedged, params = self.handle_param_bool(params, 'hedged', False)
5027
+ if reduceOnly:
5028
+ if hedged or isStopLossOrTakeProfitTrigger:
5029
+ reduceOnlyPosSide = 'long' if (side == 'sell') else 'short'
5030
+ request['posSide'] = reduceOnlyPosSide
5031
+ elif not isStopLossOrTakeProfitTrigger:
5032
+ request['reduceOnly'] = 'yes'
5033
+ else:
5034
+ if hedged:
5035
+ posSide = 'long' if (side == 'buy') else 'short'
5036
+ request['posSide'] = posSide
5037
+ params = self.omit(params, ['stopLoss', 'takeProfit', 'postOnly', 'reduceOnly', 'hedged'])
5038
+ return self.extend(request, params)
5039
+
5040
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5041
+ market = self.market(symbol)
5042
+ marketType = None
5043
+ marginMode = None
5044
+ marketType, params = self.handle_market_type_and_params('createOrder', market, params)
5045
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
5046
+ request: dict = {
5047
+ 'symbol': market['id'],
5048
+ 'orderType': type,
5049
+ }
5050
+ isMarketOrder = type == 'market'
5051
+ triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
5052
+ stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
5053
+ takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
5054
+ stopLoss = self.safe_value(params, 'stopLoss')
5055
+ takeProfit = self.safe_value(params, 'takeProfit')
5056
+ isTriggerOrder = triggerPrice is not None
5057
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
4478
5058
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
4479
5059
  isStopLoss = stopLoss is not None
4480
5060
  isTakeProfit = takeProfit is not None
@@ -4528,16 +5108,16 @@ class bitget(Exchange, ImplicitAPI):
4528
5108
  if price is not None:
4529
5109
  request['executePrice'] = self.price_to_precision(symbol, price)
4530
5110
  if isStopLoss:
4531
- slTriggerPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'stopPrice')
5111
+ slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice')
4532
5112
  request['stopLossTriggerPrice'] = self.price_to_precision(symbol, slTriggerPrice)
4533
- slPrice = self.safe_number(stopLoss, 'price')
5113
+ slPrice = self.safe_string(stopLoss, 'price')
4534
5114
  request['stopLossExecutePrice'] = self.price_to_precision(symbol, slPrice)
4535
5115
  slType = self.safe_string(stopLoss, 'type', 'mark_price')
4536
5116
  request['stopLossTriggerType'] = slType
4537
5117
  if isTakeProfit:
4538
- tpTriggerPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'stopPrice')
5118
+ tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice')
4539
5119
  request['stopSurplusTriggerPrice'] = self.price_to_precision(symbol, tpTriggerPrice)
4540
- tpPrice = self.safe_number(takeProfit, 'price')
5120
+ tpPrice = self.safe_string(takeProfit, 'price')
4541
5121
  request['stopSurplusExecutePrice'] = self.price_to_precision(symbol, tpPrice)
4542
5122
  tpType = self.safe_string(takeProfit, 'type', 'mark_price')
4543
5123
  request['stopSurplusTriggerType'] = tpType
@@ -4630,6 +5210,52 @@ class bitget(Exchange, ImplicitAPI):
4630
5210
  raise NotSupported(self.id + ' createOrder() does not support ' + marketType + ' orders')
4631
5211
  return self.extend(request, params)
4632
5212
 
5213
+ async def create_uta_orders(self, orders: List[OrderRequest], params={}):
5214
+ await self.load_markets()
5215
+ ordersRequests = []
5216
+ symbol = None
5217
+ marginMode = None
5218
+ for i in range(0, len(orders)):
5219
+ rawOrder = orders[i]
5220
+ marketId = self.safe_string(rawOrder, 'symbol')
5221
+ if symbol is None:
5222
+ symbol = marketId
5223
+ else:
5224
+ if symbol != marketId:
5225
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
5226
+ type = self.safe_string(rawOrder, 'type')
5227
+ side = self.safe_string(rawOrder, 'side')
5228
+ amount = self.safe_value(rawOrder, 'amount')
5229
+ price = self.safe_value(rawOrder, 'price')
5230
+ orderParams = self.safe_value(rawOrder, 'params', {})
5231
+ marginResult = self.handle_margin_mode_and_params('createOrders', orderParams)
5232
+ currentMarginMode = marginResult[0]
5233
+ if currentMarginMode is not None:
5234
+ if marginMode is None:
5235
+ marginMode = currentMarginMode
5236
+ else:
5237
+ if marginMode != currentMarginMode:
5238
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same margin mode(isolated or cross)')
5239
+ orderRequest = self.create_uta_order_request(marketId, type, side, amount, price, orderParams)
5240
+ ordersRequests.append(orderRequest)
5241
+ market = self.market(symbol)
5242
+ response = await self.privateUtaPostV3TradePlaceBatch(ordersRequests)
5243
+ #
5244
+ # {
5245
+ # "code": "00000",
5246
+ # "msg": "success",
5247
+ # "requestTime": 1752810184560,
5248
+ # "data": [
5249
+ # {
5250
+ # "orderId": "1329947796441513984",
5251
+ # "clientOid": "1329947796483457024"
5252
+ # },
5253
+ # ]
5254
+ # }
5255
+ #
5256
+ data = self.safe_list(response, 'data', [])
5257
+ return self.parse_orders(data, market)
5258
+
4633
5259
  async def create_orders(self, orders: List[OrderRequest], params={}):
4634
5260
  """
4635
5261
  create a list of trade orders(all orders should be of the same symbol)
@@ -4638,12 +5264,18 @@ class bitget(Exchange, ImplicitAPI):
4638
5264
  https://www.bitget.com/api-doc/contract/trade/Batch-Order
4639
5265
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Order
4640
5266
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Order
5267
+ https://www.bitget.com/api-doc/uta/trade/Place-Batch
4641
5268
 
4642
5269
  :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
4643
5270
  :param dict [params]: extra parameters specific to the api endpoint
5271
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4644
5272
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4645
5273
  """
4646
5274
  await self.load_markets()
5275
+ uta = None
5276
+ uta, params = self.handle_option_and_params(params, 'createOrders', 'uta', False)
5277
+ if uta:
5278
+ return await self.create_uta_orders(orders, params)
4647
5279
  ordersRequests = []
4648
5280
  symbol = None
4649
5281
  marginMode = None
@@ -4729,6 +5361,8 @@ class bitget(Exchange, ImplicitAPI):
4729
5361
  https://www.bitget.com/api-doc/contract/trade/Modify-Order
4730
5362
  https://www.bitget.com/api-doc/contract/plan/Modify-Tpsl-Order
4731
5363
  https://www.bitget.com/api-doc/contract/plan/Modify-Plan-Order
5364
+ https://www.bitget.com/api-doc/uta/trade/Modify-Order
5365
+ https://www.bitget.com/api-doc/uta/strategy/Modify-Strategy-Order
4732
5366
 
4733
5367
  :param str id: cancel order id
4734
5368
  :param str symbol: unified symbol of the market to create an order in
@@ -4751,6 +5385,7 @@ class bitget(Exchange, ImplicitAPI):
4751
5385
  :param str [params.trailingPercent]: *swap and future only* the percent to trail away from the current market price, rate can not be greater than 10
4752
5386
  :param str [params.trailingTriggerPrice]: *swap and future only* the price to trigger a trailing stop order, default uses the price argument
4753
5387
  :param str [params.newTriggerType]: *swap and future only* 'fill_price', 'mark_price' or 'index_price'
5388
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4754
5389
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4755
5390
  """
4756
5391
  await self.load_markets()
@@ -4779,7 +5414,39 @@ class bitget(Exchange, ImplicitAPI):
4779
5414
  request['clientOid'] = clientOrderId
4780
5415
  params = self.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent'])
4781
5416
  response = None
4782
- if market['spot']:
5417
+ productType = None
5418
+ uta = None
5419
+ productType, params = self.handle_product_type_and_params(market, params)
5420
+ uta, params = self.handle_option_and_params(params, 'editOrder', 'uta', False)
5421
+ if uta:
5422
+ if amount is not None:
5423
+ request['qty'] = self.amount_to_precision(symbol, amount)
5424
+ if isStopLossOrder or isTakeProfitOrder:
5425
+ if isStopLossOrder:
5426
+ slType = self.safe_string(params, 'slTriggerBy', 'mark')
5427
+ request['slTriggerBy'] = slType
5428
+ request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
5429
+ if price is not None:
5430
+ request['slLimitPrice'] = self.price_to_precision(symbol, price)
5431
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
5432
+ else:
5433
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
5434
+ elif isTakeProfitOrder:
5435
+ tpType = self.safe_string(params, 'tpTriggerBy', 'mark')
5436
+ request['tpTriggerBy'] = tpType
5437
+ request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
5438
+ if price is not None:
5439
+ request['tpLimitPrice'] = self.price_to_precision(symbol, price)
5440
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
5441
+ else:
5442
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
5443
+ params = self.omit(params, ['stopLossPrice', 'takeProfitPrice'])
5444
+ response = await self.privateUtaPostV3TradeModifyStrategyOrder(self.extend(request, params))
5445
+ else:
5446
+ if price is not None:
5447
+ request['price'] = self.price_to_precision(symbol, price)
5448
+ response = await self.privateUtaPostV3TradeModifyOrder(self.extend(request, params))
5449
+ elif market['spot']:
4783
5450
  if triggerPrice is None:
4784
5451
  raise NotSupported(self.id + ' editOrder() only supports plan/trigger spot orders')
4785
5452
  editMarketBuyOrderRequiresPrice = self.safe_bool(self.options, 'editMarketBuyOrderRequiresPrice', True)
@@ -4801,8 +5468,6 @@ class bitget(Exchange, ImplicitAPI):
4801
5468
  if (not market['swap']) and (not market['future']):
4802
5469
  raise NotSupported(self.id + ' editOrder() does not support ' + market['type'] + ' orders')
4803
5470
  request['symbol'] = market['id']
4804
- productType = None
4805
- productType, params = self.handle_product_type_and_params(market, params)
4806
5471
  request['productType'] = productType
4807
5472
  if not isTakeProfitOrder and not isStopLossOrder:
4808
5473
  request['newSize'] = self.amount_to_precision(symbol, amount)
@@ -4878,6 +5543,8 @@ class bitget(Exchange, ImplicitAPI):
4878
5543
  https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
4879
5544
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Cancel-Order
4880
5545
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Cancel-Order
5546
+ https://www.bitget.com/api-doc/uta/trade/Cancel-Order
5547
+ https://www.bitget.com/api-doc/uta/strategy/Cancel-Strategy-Order
4881
5548
 
4882
5549
  :param str id: order id
4883
5550
  :param str symbol: unified symbol of the market the order was made in
@@ -4886,6 +5553,8 @@ class bitget(Exchange, ImplicitAPI):
4886
5553
  :param boolean [params.trigger]: set to True for canceling trigger orders
4887
5554
  :param str [params.planType]: *swap only* either profit_plan, loss_plan, normal_plan, pos_profit, pos_loss, moving_plan or track_plan
4888
5555
  :param boolean [params.trailing]: set to True if you want to cancel a trailing order
5556
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5557
+ :param str [params.clientOrderId]: the clientOrderId of the order, id does not need to be provided if clientOrderId is provided
4889
5558
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4890
5559
  """
4891
5560
  if symbol is None:
@@ -4901,19 +5570,37 @@ class bitget(Exchange, ImplicitAPI):
4901
5570
  params = self.omit(params, ['stop', 'trigger', 'trailing'])
4902
5571
  if not (market['spot'] and trigger):
4903
5572
  request['symbol'] = market['id']
4904
- if not ((market['swap'] or market['future']) and trigger):
4905
- request['orderId'] = id
4906
- if (market['swap']) or (market['future']):
5573
+ uta = None
5574
+ uta, params = self.handle_option_and_params(params, 'cancelOrder', 'uta', False)
5575
+ isPlanOrder = trigger or trailing
5576
+ isContract = market['swap'] or market['future']
5577
+ isContractTriggerEndpoint = isContract and isPlanOrder and not uta
5578
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clientOid')
5579
+ if isContractTriggerEndpoint:
5580
+ orderIdList = []
5581
+ orderId: dict = {}
5582
+ if clientOrderId is not None:
5583
+ params = self.omit(params, 'clientOrderId')
5584
+ orderId['clientOid'] = clientOrderId
5585
+ else:
5586
+ orderId['orderId'] = id
5587
+ orderIdList.append(orderId)
5588
+ request['orderIdList'] = orderIdList
5589
+ else:
5590
+ if clientOrderId is not None:
5591
+ params = self.omit(params, 'clientOrderId')
5592
+ request['clientOid'] = clientOrderId
5593
+ else:
5594
+ request['orderId'] = id
5595
+ if uta:
5596
+ if trigger:
5597
+ response = await self.privateUtaPostV3TradeCancelStrategyOrder(self.extend(request, params))
5598
+ else:
5599
+ response = await self.privateUtaPostV3TradeCancelOrder(self.extend(request, params))
5600
+ elif (market['swap']) or (market['future']):
4907
5601
  productType = None
4908
5602
  productType, params = self.handle_product_type_and_params(market, params)
4909
5603
  request['productType'] = productType
4910
- if trigger or trailing:
4911
- orderIdList = []
4912
- orderId: dict = {
4913
- 'orderId': id,
4914
- }
4915
- orderIdList.append(orderId)
4916
- request['orderIdList'] = orderIdList
4917
5604
  if trailing:
4918
5605
  planType = self.safe_string(params, 'planType', 'track_plan')
4919
5606
  request['planType'] = planType
@@ -4976,15 +5663,60 @@ class bitget(Exchange, ImplicitAPI):
4976
5663
  # }
4977
5664
  # }
4978
5665
  #
5666
+ # uta trigger
5667
+ #
5668
+ # {
5669
+ # "code": "00000",
5670
+ # "msg": "success",
5671
+ # "requestTime": "1753058267399",
5672
+ # "data": null
5673
+ # }
5674
+ #
4979
5675
  data = self.safe_value(response, 'data', {})
4980
5676
  order = None
4981
- if (market['swap'] or market['future']) and trigger:
5677
+ if isContractTriggerEndpoint:
4982
5678
  orderInfo = self.safe_value(data, 'successList', [])
4983
5679
  order = orderInfo[0]
4984
5680
  else:
4985
- order = data
5681
+ if uta and trigger:
5682
+ order = response
5683
+ else:
5684
+ order = data
4986
5685
  return self.parse_order(order, market)
4987
5686
 
5687
+ async def cancel_uta_orders(self, ids, symbol: Str = None, params={}):
5688
+ if symbol is None:
5689
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
5690
+ await self.load_markets()
5691
+ market = self.market(symbol)
5692
+ productType = None
5693
+ productType, params = self.handle_product_type_and_params(market, params)
5694
+ requestList = []
5695
+ for i in range(0, len(ids)):
5696
+ individualId = ids[i]
5697
+ order: dict = {
5698
+ 'orderId': individualId,
5699
+ 'symbol': market['id'],
5700
+ 'category': productType,
5701
+ }
5702
+ requestList.append(order)
5703
+ response = await self.privateUtaPostV3TradeCancelBatch(requestList)
5704
+ #
5705
+ # {
5706
+ # "code": "00000",
5707
+ # "msg": "success",
5708
+ # "requestTime": 1752813731517,
5709
+ # "data": [
5710
+ # {
5711
+ # "orderId": "1329948909442023424",
5712
+ # "clientOid": "1329948909446217728"
5713
+ # },
5714
+ # ]
5715
+ # }
5716
+ #
5717
+ data = self.safe_list(response, 'data', [])
5718
+ return self.parse_orders(data, market)
5719
+
4988
5720
  async def cancel_orders(self, ids, symbol: Str = None, params={}):
4989
5721
  """
4990
5722
  cancel multiple orders
@@ -4994,18 +5726,24 @@ class bitget(Exchange, ImplicitAPI):
4994
5726
  https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
4995
5727
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Cancel-Order
4996
5728
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Cancel-Orders
5729
+ https://www.bitget.com/api-doc/uta/trade/Cancel-Batch
4997
5730
 
4998
5731
  :param str[] ids: order ids
4999
5732
  :param str symbol: unified market symbol, default is None
5000
5733
  :param dict [params]: extra parameters specific to the exchange API endpoint
5001
5734
  :param str [params.marginMode]: 'isolated' or 'cross' for spot margin trading
5002
5735
  :param boolean [params.trigger]: *contract only* set to True for canceling trigger orders
5736
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5003
5737
  :returns dict: an array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5004
5738
  """
5005
5739
  if symbol is None:
5006
5740
  raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
5007
5741
  await self.load_markets()
5008
5742
  market = self.market(symbol)
5743
+ uta = None
5744
+ uta, params = self.handle_option_and_params(params, 'cancelOrders', 'uta', False)
5745
+ if uta:
5746
+ return await self.cancel_uta_orders(ids, symbol, params)
5009
5747
  marginMode = None
5010
5748
  marginMode, params = self.handle_margin_mode_and_params('cancelOrders', params)
5011
5749
  trigger = self.safe_value_2(params, 'stop', 'trigger')
@@ -5070,11 +5808,13 @@ class bitget(Exchange, ImplicitAPI):
5070
5808
  https://www.bitget.com/api-doc/contract/trade/Batch-Cancel-Orders
5071
5809
  https://bitgetlimited.github.io/apidoc/en/margin/#isolated-batch-cancel-orders
5072
5810
  https://bitgetlimited.github.io/apidoc/en/margin/#cross-batch-cancel-order
5811
+ https://www.bitget.com/api-doc/uta/trade/Cancel-All-Order
5073
5812
 
5074
5813
  :param str symbol: unified market symbol
5075
5814
  :param dict [params]: extra parameters specific to the exchange API endpoint
5076
5815
  :param str [params.marginMode]: 'isolated' or 'cross' for spot margin trading
5077
5816
  :param boolean [params.trigger]: *contract only* set to True for canceling trigger orders
5817
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5078
5818
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5079
5819
  """
5080
5820
  if symbol is None:
@@ -5083,13 +5823,38 @@ class bitget(Exchange, ImplicitAPI):
5083
5823
  market = self.market(symbol)
5084
5824
  marginMode = None
5085
5825
  marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
5826
+ productType = None
5827
+ productType, params = self.handle_product_type_and_params(market, params)
5086
5828
  request: dict = {
5087
5829
  'symbol': market['id'],
5088
5830
  }
5089
5831
  trigger = self.safe_bool_2(params, 'stop', 'trigger')
5090
5832
  params = self.omit(params, ['stop', 'trigger'])
5091
5833
  response = None
5092
- if market['spot']:
5834
+ uta = None
5835
+ uta, params = self.handle_option_and_params(params, 'cancelAllOrders', 'uta', False)
5836
+ if uta:
5837
+ if productType == 'SPOT':
5838
+ if marginMode is not None:
5839
+ productType = 'MARGIN'
5840
+ request['category'] = productType
5841
+ response = await self.privateUtaPostV3TradeCancelSymbolOrder(self.extend(request, params))
5842
+ #
5843
+ # {
5844
+ # "code": "00000",
5845
+ # "msg": "success",
5846
+ # "requestTime": 1750751578138,
5847
+ # "data": {
5848
+ # "list": [
5849
+ # {
5850
+ # "orderId": "1321313242969427968",
5851
+ # "clientOid": "1321313242969427969"
5852
+ # }
5853
+ # ]
5854
+ # }
5855
+ # }
5856
+ #
5857
+ elif market['spot']:
5093
5858
  if marginMode is not None:
5094
5859
  if marginMode == 'cross':
5095
5860
  response = await self.privateMarginPostMarginV1CrossOrderBatchCancelOrder(self.extend(request, params))
@@ -5141,8 +5906,6 @@ class bitget(Exchange, ImplicitAPI):
5141
5906
  }),
5142
5907
  ]
5143
5908
  else:
5144
- productType = None
5145
- productType, params = self.handle_product_type_and_params(market, params)
5146
5909
  request['productType'] = productType
5147
5910
  if trigger:
5148
5911
  response = await self.privateMixPostV2MixOrderCancelPlanOrder(self.extend(request, params))
@@ -5163,9 +5926,13 @@ class bitget(Exchange, ImplicitAPI):
5163
5926
  # }
5164
5927
  # }
5165
5928
  data = self.safe_dict(response, 'data')
5166
- resultList = self.safe_list_2(data, 'resultList', 'successList')
5929
+ resultList = self.safe_list_n(data, ['resultList', 'successList', 'list'])
5167
5930
  failureList = self.safe_list_2(data, 'failure', 'failureList')
5168
- responseList = self.array_concat(resultList, failureList)
5931
+ responseList = None
5932
+ if (resultList is not None) and (failureList is not None):
5933
+ responseList = self.array_concat(resultList, failureList)
5934
+ else:
5935
+ responseList = resultList
5169
5936
  return self.parse_orders(responseList)
5170
5937
 
5171
5938
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
@@ -5174,10 +5941,13 @@ class bitget(Exchange, ImplicitAPI):
5174
5941
 
5175
5942
  https://www.bitget.com/api-doc/spot/trade/Get-Order-Info
5176
5943
  https://www.bitget.com/api-doc/contract/trade/Get-Order-Details
5944
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-Details
5177
5945
 
5178
5946
  :param str id: the order id
5179
5947
  :param str symbol: unified symbol of the market the order was made in
5180
5948
  :param dict [params]: extra parameters specific to the exchange API endpoint
5949
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5950
+ :param str [params.clientOrderId]: the clientOrderId of the order, id does not need to be provided if clientOrderId is provided
5181
5951
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
5182
5952
  """
5183
5953
  if symbol is None:
@@ -5185,10 +5955,20 @@ class bitget(Exchange, ImplicitAPI):
5185
5955
  await self.load_markets()
5186
5956
  market = self.market(symbol)
5187
5957
  request: dict = {
5188
- 'orderId': id,
5958
+ # 'orderId': id,
5189
5959
  }
5960
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'clientOid')
5961
+ if clientOrderId is not None:
5962
+ params = self.omit(params, ['clientOrderId'])
5963
+ request['clientOid'] = clientOrderId
5964
+ else:
5965
+ request['orderId'] = id
5190
5966
  response = None
5191
- if market['spot']:
5967
+ uta = None
5968
+ uta, params = self.handle_option_and_params(params, 'fetchOrder', 'uta', False)
5969
+ if uta:
5970
+ response = await self.privateUtaGetV3TradeOrderInfo(self.extend(request, params))
5971
+ elif market['spot']:
5192
5972
  response = await self.privateSpotGetV2SpotTradeOrderInfo(self.extend(request, params))
5193
5973
  elif market['swap'] or market['future']:
5194
5974
  request['symbol'] = market['id']
@@ -5265,13 +6045,60 @@ class bitget(Exchange, ImplicitAPI):
5265
6045
  # }
5266
6046
  # }
5267
6047
  #
5268
- if isinstance(response, str):
6048
+ # uta
6049
+ #
6050
+ # {
6051
+ # "code": "00000",
6052
+ # "msg": "success",
6053
+ # "requestTime": 1750496858333,
6054
+ # "data": {
6055
+ # "orderId": "1320244799629316096",
6056
+ # "clientOid": "1320244799633510400",
6057
+ # "category": "USDT-FUTURES",
6058
+ # "symbol": "BTCUSDT",
6059
+ # "orderType": "limit",
6060
+ # "side": "buy",
6061
+ # "price": "50000",
6062
+ # "qty": "0.001",
6063
+ # "amount": "0",
6064
+ # "cumExecQty": "0",
6065
+ # "cumExecValue": "0",
6066
+ # "avgPrice": "0",
6067
+ # "timeInForce": "gtc",
6068
+ # "orderStatus": "live",
6069
+ # "posSide": "long",
6070
+ # "holdMode": "hedge_mode",
6071
+ # "reduceOnly": "NO",
6072
+ # "feeDetail": [{
6073
+ # "feeCoin": "",
6074
+ # "fee": ""
6075
+ # }],
6076
+ # "createdTime": "1750496809871",
6077
+ # "updatedTime": "1750496809886",
6078
+ # "cancelReason": "",
6079
+ # "execType": "normal",
6080
+ # "stpMode": "none",
6081
+ # "tpTriggerBy": null,
6082
+ # "slTriggerBy": null,
6083
+ # "takeProfit": null,
6084
+ # "stopLoss": null,
6085
+ # "tpOrderType": null,
6086
+ # "slOrderType": null,
6087
+ # "tpLimitPrice": null,
6088
+ # "slLimitPrice": null
6089
+ # }
6090
+ # }
6091
+ #
6092
+ if not uta and (isinstance(response, str)):
5269
6093
  response = json.loads(response)
5270
6094
  data = self.safe_dict(response, 'data')
5271
6095
  if (data is not None):
5272
6096
  if not isinstance(data, list):
5273
6097
  return self.parse_order(data, market)
5274
6098
  dataList = self.safe_list(response, 'data', [])
6099
+ dataListLength = len(dataList)
6100
+ if dataListLength == 0:
6101
+ raise OrderNotFound(self.id + ' fetchOrder() could not find order id ' + id + ' in ' + self.json(response))
5275
6102
  first = self.safe_dict(dataList, 0, {})
5276
6103
  return self.parse_order(first, market)
5277
6104
  # first = self.safe_dict(data, 0, data)
@@ -5287,6 +6114,7 @@ class bitget(Exchange, ImplicitAPI):
5287
6114
  https://www.bitget.com/api-doc/contract/plan/get-orders-plan-pending
5288
6115
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Open-Orders
5289
6116
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Open-Orders
6117
+ https://www.bitget.com/api-doc/uta/strategy/Get-Unfilled-Strategy-Orders
5290
6118
 
5291
6119
  :param str symbol: unified market symbol
5292
6120
  :param int [since]: the earliest time in ms to fetch open orders for
@@ -5298,6 +6126,7 @@ class bitget(Exchange, ImplicitAPI):
5298
6126
  :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)
5299
6127
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5300
6128
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
6129
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5301
6130
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5302
6131
  """
5303
6132
  await self.load_markets()
@@ -5306,6 +6135,8 @@ class bitget(Exchange, ImplicitAPI):
5306
6135
  request: dict = {}
5307
6136
  marginMode = None
5308
6137
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
6138
+ uta = None
6139
+ uta, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'uta', False)
5309
6140
  if symbol is not None:
5310
6141
  market = self.market(symbol)
5311
6142
  request['symbol'] = market['id']
@@ -5319,58 +6150,71 @@ class bitget(Exchange, ImplicitAPI):
5319
6150
  paginate, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'paginate')
5320
6151
  if paginate:
5321
6152
  cursorReceived = None
5322
- if type == 'spot':
6153
+ cursorSent = None
6154
+ if uta:
6155
+ cursorReceived = 'cursor'
6156
+ cursorSent = 'cursor'
6157
+ elif type == 'spot':
5323
6158
  if marginMode is not None:
5324
6159
  cursorReceived = 'minId'
6160
+ cursorSent = 'idLessThan'
5325
6161
  else:
5326
6162
  cursorReceived = 'endId'
5327
- return await self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, 'idLessThan')
6163
+ cursorSent = 'idLessThan'
6164
+ return await self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, cursorSent)
5328
6165
  response = None
5329
6166
  trailing = self.safe_bool(params, 'trailing')
5330
6167
  trigger = self.safe_bool_2(params, 'stop', 'trigger')
5331
6168
  planTypeDefined = self.safe_string(params, 'planType') is not None
5332
6169
  isTrigger = (trigger or planTypeDefined)
5333
- params = self.omit(params, ['stop', 'trigger', 'trailing'])
5334
6170
  request, params = self.handle_until_option('endTime', request, params)
5335
6171
  if since is not None:
5336
6172
  request['startTime'] = since
5337
6173
  if limit is not None:
5338
6174
  request['limit'] = limit
5339
- if (type == 'swap') or (type == 'future') or (marginMode is not None):
6175
+ if not uta and ((type == 'swap') or (type == 'future') or (marginMode is not None)):
5340
6176
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
5341
6177
  params = self.omit(params, 'clientOrderId')
5342
6178
  if clientOrderId is not None:
5343
6179
  request['clientOid'] = clientOrderId
5344
- query = None
5345
- query = self.omit(params, ['type'])
5346
- if type == 'spot':
6180
+ productType = None
6181
+ productType, params = self.handle_product_type_and_params(market, params)
6182
+ params = self.omit(params, ['type', 'stop', 'trigger', 'trailing'])
6183
+ if uta:
6184
+ if type == 'spot':
6185
+ if marginMode is not None:
6186
+ productType = 'MARGIN'
6187
+ request['category'] = productType
6188
+ if trigger:
6189
+ response = await self.privateUtaGetV3TradeUnfilledStrategyOrders(self.extend(request, params))
6190
+ else:
6191
+ response = await self.privateUtaGetV3TradeUnfilledOrders(self.extend(request, params))
6192
+ elif type == 'spot':
5347
6193
  if marginMode is not None:
5348
6194
  if since is None:
5349
6195
  since = self.milliseconds() - 7776000000
5350
6196
  request['startTime'] = since
5351
6197
  if marginMode == 'isolated':
5352
- response = await self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, query))
6198
+ response = await self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, params))
5353
6199
  elif marginMode == 'cross':
5354
- response = await self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, query))
6200
+ response = await self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, params))
5355
6201
  else:
5356
6202
  if trigger:
5357
- response = await self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, query))
6203
+ response = await self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, params))
5358
6204
  else:
5359
- response = await self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, query))
6205
+ response = await self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, params))
5360
6206
  else:
5361
- productType = None
5362
- productType, query = self.handle_product_type_and_params(market, query)
5363
6207
  request['productType'] = productType
5364
6208
  if trailing:
5365
6209
  planType = self.safe_string(params, 'planType', 'track_plan')
5366
6210
  request['planType'] = planType
5367
- response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, query))
6211
+ response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, params))
5368
6212
  elif isTrigger:
5369
- planType = self.safe_string(query, 'planType', 'normal_plan')
6213
+ planType = self.safe_string(params, 'planType', 'normal_plan')
5370
6214
  request['planType'] = planType
5371
- response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, query))
6215
+ response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, params))
5372
6216
  else:
5373
- response = await self.privateMixGetV2MixOrderOrdersPending(self.extend(request, query))
6217
+ response = await self.privateMixGetV2MixOrderOrdersPending(self.extend(request, params))
5374
6218
  #
5375
6219
  # spot
5376
6220
  #
@@ -5546,8 +6390,92 @@ class bitget(Exchange, ImplicitAPI):
5546
6390
  # }
5547
6391
  # }
5548
6392
  #
6393
+ # uta
6394
+ #
6395
+ # {
6396
+ # "code": "00000",
6397
+ # "msg": "success",
6398
+ # "requestTime": 1750753395850,
6399
+ # "data": {
6400
+ # "list": [
6401
+ # {
6402
+ # "orderId": "1321320757371228160",
6403
+ # "clientOid": "1321320757371228161",
6404
+ # "category": "USDT-FUTURES",
6405
+ # "symbol": "BTCUSDT",
6406
+ # "orderType": "limit",
6407
+ # "side": "buy",
6408
+ # "price": "50000",
6409
+ # "qty": "0.001",
6410
+ # "amount": "0",
6411
+ # "cumExecQty": "0",
6412
+ # "cumExecValue": "0",
6413
+ # "avgPrice": "0",
6414
+ # "timeInForce": "gtc",
6415
+ # "orderStatus": "live",
6416
+ # "posSide": "long",
6417
+ # "holdMode": "hedge_mode",
6418
+ # "reduceOnly": "NO",
6419
+ # "feeDetail": [
6420
+ # {
6421
+ # "feeCoin": "",
6422
+ # "fee": ""
6423
+ # }
6424
+ # ],
6425
+ # "createdTime": "1750753338186",
6426
+ # "updatedTime": "1750753338203",
6427
+ # "stpMode": "none",
6428
+ # "tpTriggerBy": null,
6429
+ # "slTriggerBy": null,
6430
+ # "takeProfit": null,
6431
+ # "stopLoss": null,
6432
+ # "tpOrderType": null,
6433
+ # "slOrderType": null,
6434
+ # "tpLimitPrice": null,
6435
+ # "slLimitPrice": null
6436
+ # }
6437
+ # ],
6438
+ # "cursor": "1321320757371228160"
6439
+ # }
6440
+ # }
6441
+ #
6442
+ # uta trigger
6443
+ #
6444
+ # {
6445
+ # "code": "00000",
6446
+ # "msg": "success",
6447
+ # "requestTime": 1753057527060,
6448
+ # "data": [
6449
+ # {
6450
+ # "orderId": "1330984742276198400",
6451
+ # "clientOid": "1330984742276198400",
6452
+ # "symbol": "BTCUSDT",
6453
+ # "category": "USDT-FUTURES",
6454
+ # "qty": "0.001",
6455
+ # "posSide": "long",
6456
+ # "tpTriggerBy": "market",
6457
+ # "slTriggerBy": "mark",
6458
+ # "takeProfit": "",
6459
+ # "stopLoss":"114000",
6460
+ # "tpOrderType": "market",
6461
+ # "slOrderType": "limit",
6462
+ # "tpLimitPrice": "",
6463
+ # "slLimitPrice": "113000",
6464
+ # "createdTime": "1753057411736",
6465
+ # "updatedTime": "1753057411747"
6466
+ # }
6467
+ # ]
6468
+ # }
6469
+ #
5549
6470
  data = self.safe_value(response, 'data')
5550
- if type == 'spot':
6471
+ if uta:
6472
+ result = None
6473
+ if trigger:
6474
+ result = self.safe_list(response, 'data', [])
6475
+ else:
6476
+ result = self.safe_list(data, 'list', [])
6477
+ return self.parse_orders(result, market, since, limit)
6478
+ elif type == 'spot':
5551
6479
  if (marginMode is not None) or trigger:
5552
6480
  resultList = self.safe_list(data, 'orderList', [])
5553
6481
  return self.parse_orders(resultList, market, since, limit)
@@ -5566,6 +6494,7 @@ class bitget(Exchange, ImplicitAPI):
5566
6494
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5567
6495
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5568
6496
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6497
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
5569
6498
 
5570
6499
  :param str symbol: unified market symbol of the closed orders
5571
6500
  :param int [since]: timestamp in ms of the earliest order
@@ -5593,6 +6522,7 @@ class bitget(Exchange, ImplicitAPI):
5593
6522
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5594
6523
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5595
6524
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6525
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
5596
6526
 
5597
6527
  :param str symbol: unified market symbol of the canceled orders
5598
6528
  :param int [since]: timestamp in ms of the earliest order
@@ -5619,6 +6549,8 @@ class bitget(Exchange, ImplicitAPI):
5619
6549
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5620
6550
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5621
6551
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6552
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
6553
+ https://www.bitget.com/api-doc/uta/strategy/Get-History-Strategy-Orders
5622
6554
 
5623
6555
  fetches information on multiple canceled and closed orders made by the user
5624
6556
  :param str symbol: unified market symbol of the market orders were made in
@@ -5631,8 +6563,13 @@ class bitget(Exchange, ImplicitAPI):
5631
6563
  :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)
5632
6564
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5633
6565
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
6566
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5634
6567
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5635
6568
  """
6569
+ uta = None
6570
+ uta, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'uta', False)
6571
+ if uta:
6572
+ return await self.fetch_uta_canceled_and_closed_orders(symbol, since, limit, params)
5636
6573
  await self.load_markets()
5637
6574
  market = None
5638
6575
  request: dict = {}
@@ -5894,32 +6831,150 @@ class bitget(Exchange, ImplicitAPI):
5894
6831
  orders = self.safe_list(response, 'data', [])
5895
6832
  return self.parse_orders(orders, market, since, limit)
5896
6833
 
5897
- async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
5898
- """
5899
- fetch the history of changes, actions done by the user or operations that altered the balance of the user
5900
-
5901
- https://www.bitget.com/api-doc/spot/account/Get-Account-Bills
5902
- https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
5903
-
5904
- :param str [code]: unified currency code, default is None
5905
- :param int [since]: timestamp in ms of the earliest ledger entry, default is None
5906
- :param int [limit]: max number of ledger entries to return, default is None
5907
- :param dict [params]: extra parameters specific to the exchange API endpoint
5908
- :param int [params.until]: end time in ms
5909
- :param str [params.symbol]: *contract only* unified market symbol
5910
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
5911
- :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)
5912
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
5913
- """
6834
+ async def fetch_uta_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5914
6835
  await self.load_markets()
5915
- symbol = self.safe_string(params, 'symbol')
5916
- params = self.omit(params, 'symbol')
5917
6836
  market = None
5918
6837
  if symbol is not None:
5919
6838
  market = self.market(symbol)
5920
- marketType = None
5921
- marketType, params = self.handle_market_type_and_params('fetchLedger', market, params)
5922
- paginate = False
6839
+ productType = None
6840
+ productType, params = self.handle_product_type_and_params(market, params)
6841
+ if productType == 'SPOT':
6842
+ marginMode = None
6843
+ marginMode, params = self.handle_margin_mode_and_params('fetchCanceledAndClosedOrders', params)
6844
+ if marginMode is not None:
6845
+ productType = 'MARGIN'
6846
+ request: dict = {
6847
+ 'category': productType,
6848
+ }
6849
+ paginate = False
6850
+ paginate, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'paginate')
6851
+ if paginate:
6852
+ return await self.fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, 'cursor', 'cursor')
6853
+ request, params = self.handle_until_option('endTime', request, params)
6854
+ if since is not None:
6855
+ request['startTime'] = since
6856
+ if limit is not None:
6857
+ request['limit'] = limit
6858
+ response = None
6859
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
6860
+ params = self.omit(params, ['stop', 'trigger'])
6861
+ if trigger:
6862
+ response = await self.privateUtaGetV3TradeHistoryStrategyOrders(self.extend(request, params))
6863
+ else:
6864
+ response = await self.privateUtaGetV3TradeHistoryOrders(self.extend(request, params))
6865
+ #
6866
+ # uta
6867
+ #
6868
+ # {
6869
+ # "code": "00000",
6870
+ # "msg": "success",
6871
+ # "requestTime": 1752531592855,
6872
+ # "data": {
6873
+ # "list": [
6874
+ # {
6875
+ # "orderId": "1322441400976261120",
6876
+ # "clientOid": "1322441400976261121",
6877
+ # "category": "USDT-FUTURES",
6878
+ # "symbol": "BTCUSDT",
6879
+ # "orderType": "market",
6880
+ # "side": "sell",
6881
+ # "price": "0",
6882
+ # "qty": "0.0001",
6883
+ # "amount": "0",
6884
+ # "cumExecQty": "0.0001",
6885
+ # "cumExecValue": "10.7005",
6886
+ # "avgPrice": "107005.4",
6887
+ # "timeInForce": "gtc",
6888
+ # "orderStatus": "filled",
6889
+ # "posSide": "long",
6890
+ # "holdMode": "hedge_mode",
6891
+ # "reduceOnly": "NO",
6892
+ # "feeDetail": [
6893
+ # {
6894
+ # "feeCoin": "USDT",
6895
+ # "fee": "0.00642032"
6896
+ # }
6897
+ # ],
6898
+ # "createdTime": "1751020520442",
6899
+ # "updatedTime": "1751020520457",
6900
+ # "cancelReason": "",
6901
+ # "execType": "normal",
6902
+ # "stpMode": "none",
6903
+ # "tpTriggerBy": null,
6904
+ # "slTriggerBy": null,
6905
+ # "takeProfit": null,
6906
+ # "stopLoss": null,
6907
+ # "tpOrderType": null,
6908
+ # "slOrderType": null,
6909
+ # "tpLimitPrice": null,
6910
+ # "slLimitPrice": null
6911
+ # },
6912
+ # ],
6913
+ # "cursor": "1322441328637100035"
6914
+ # }
6915
+ # }
6916
+ #
6917
+ # uta trigger
6918
+ #
6919
+ # {
6920
+ # "code": "00000",
6921
+ # "msg": "success",
6922
+ # "requestTime": 1753058447920,
6923
+ # "data": {
6924
+ # "list": [
6925
+ # {
6926
+ # "orderId": "1330984742276198400",
6927
+ # "clientOid": "1330984742276198400",
6928
+ # "symbol": "BTCUSDT",
6929
+ # "category": "USDT-FUTURES",
6930
+ # "qty": "0.001",
6931
+ # "posSide": "long",
6932
+ # "tpTriggerBy": "market",
6933
+ # "slTriggerBy": "mark",
6934
+ # "takeProfit": "",
6935
+ # "stopLoss": "112000",
6936
+ # "tpOrderType": "market",
6937
+ # "slOrderType": "limit",
6938
+ # "tpLimitPrice": "",
6939
+ # "slLimitPrice": "111000",
6940
+ # "createdTime": "1753057411736",
6941
+ # "updatedTime": "1753058267412"
6942
+ # },
6943
+ # ],
6944
+ # "cursor": 1330960754317619202
6945
+ # }
6946
+ # }
6947
+ #
6948
+ data = self.safe_dict(response, 'data', {})
6949
+ orders = self.safe_list(data, 'list', [])
6950
+ return self.parse_orders(orders, market, since, limit)
6951
+
6952
+ async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
6953
+ """
6954
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
6955
+
6956
+ https://www.bitget.com/api-doc/spot/account/Get-Account-Bills
6957
+ https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
6958
+
6959
+ :param str [code]: unified currency code, default is None
6960
+ :param int [since]: timestamp in ms of the earliest ledger entry, default is None
6961
+ :param int [limit]: max number of ledger entries to return, default is None
6962
+ :param dict [params]: extra parameters specific to the exchange API endpoint
6963
+ :param int [params.until]: end time in ms
6964
+ :param str [params.symbol]: *contract only* unified market symbol
6965
+ :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
6966
+ :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)
6967
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
6968
+ """
6969
+ await self.load_markets()
6970
+ symbol = self.safe_string(params, 'symbol')
6971
+ params = self.omit(params, 'symbol')
6972
+ market = None
6973
+ if symbol is not None:
6974
+ market = self.market(symbol)
6975
+ marketType = None
6976
+ marketType, params = self.handle_market_type_and_params('fetchLedger', market, params)
6977
+ paginate = False
5923
6978
  paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
5924
6979
  if paginate:
5925
6980
  cursorReceived = None
@@ -6109,55 +7164,67 @@ class bitget(Exchange, ImplicitAPI):
6109
7164
  https://www.bitget.com/api-doc/contract/trade/Get-Order-Fills
6110
7165
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-Fills
6111
7166
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Transaction-Details
7167
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-Fills
6112
7168
 
6113
7169
  :param str symbol: unified market symbol
6114
7170
  :param int [since]: the earliest time in ms to fetch trades for
6115
7171
  :param int [limit]: the maximum number of trades structures to retrieve
6116
7172
  :param dict [params]: extra parameters specific to the exchange API endpoint
6117
7173
  :param int [params.until]: the latest time in ms to fetch trades for
7174
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6118
7175
  :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)
6119
7176
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
6120
7177
  """
6121
- if symbol is None:
7178
+ uta = None
7179
+ uta, params = self.handle_option_and_params(params, 'fetchMyTrades', 'uta', False)
7180
+ if not uta and (symbol is None):
6122
7181
  raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
6123
7182
  await self.load_markets()
6124
7183
  market = self.market(symbol)
6125
- marginMode = None
6126
- marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
7184
+ request: dict = {}
7185
+ request, params = self.handle_until_option('endTime', request, params)
7186
+ if since is not None:
7187
+ request['startTime'] = since
7188
+ if limit is not None:
7189
+ request['limit'] = limit
6127
7190
  paginate = False
7191
+ marginMode = None
6128
7192
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
7193
+ marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
6129
7194
  if paginate:
6130
7195
  cursorReceived = None
6131
- if market['spot']:
7196
+ cursorSent = None
7197
+ if uta:
7198
+ cursorReceived = 'cursor'
7199
+ cursorSent = 'cursor'
7200
+ elif market['spot']:
6132
7201
  if marginMode is not None:
6133
7202
  cursorReceived = 'minId'
7203
+ cursorSent = 'idLessThan'
6134
7204
  else:
6135
7205
  cursorReceived = 'endId'
6136
- return await self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, cursorReceived, 'idLessThan')
7206
+ cursorSent = 'idLessThan'
7207
+ return await self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, cursorReceived, cursorSent)
6137
7208
  response = None
6138
- request: dict = {
6139
- 'symbol': market['id'],
6140
- }
6141
- request, params = self.handle_until_option('endTime', request, params)
6142
- if since is not None:
6143
- request['startTime'] = since
6144
- if limit is not None:
6145
- request['limit'] = limit
6146
- if market['spot']:
6147
- if marginMode is not None:
6148
- if since is None:
6149
- request['startTime'] = self.milliseconds() - 7776000000
6150
- if marginMode == 'isolated':
6151
- response = await self.privateMarginGetV2MarginIsolatedFills(self.extend(request, params))
6152
- elif marginMode == 'cross':
6153
- response = await self.privateMarginGetV2MarginCrossedFills(self.extend(request, params))
6154
- else:
6155
- response = await self.privateSpotGetV2SpotTradeFills(self.extend(request, params))
7209
+ if uta:
7210
+ response = await self.privateUtaGetV3TradeFills(self.extend(request, params))
6156
7211
  else:
6157
- productType = None
6158
- productType, params = self.handle_product_type_and_params(market, params)
6159
- request['productType'] = productType
6160
- response = await self.privateMixGetV2MixOrderFills(self.extend(request, params))
7212
+ request['symbol'] = market['id']
7213
+ if market['spot']:
7214
+ if marginMode is not None:
7215
+ if since is None:
7216
+ request['startTime'] = self.milliseconds() - 7776000000
7217
+ if marginMode == 'isolated':
7218
+ response = await self.privateMarginGetV2MarginIsolatedFills(self.extend(request, params))
7219
+ elif marginMode == 'cross':
7220
+ response = await self.privateMarginGetV2MarginCrossedFills(self.extend(request, params))
7221
+ else:
7222
+ response = await self.privateSpotGetV2SpotTradeFills(self.extend(request, params))
7223
+ else:
7224
+ productType = None
7225
+ productType, params = self.handle_product_type_and_params(market, params)
7226
+ request['productType'] = productType
7227
+ response = await self.privateMixGetV2MixOrderFills(self.extend(request, params))
6161
7228
  #
6162
7229
  # spot
6163
7230
  #
@@ -6257,10 +7324,45 @@ class bitget(Exchange, ImplicitAPI):
6257
7324
  # }
6258
7325
  # }
6259
7326
  #
7327
+ # uta
7328
+ #
7329
+ # {
7330
+ # "code": "00000",
7331
+ # "msg": "success",
7332
+ # "requestTime": 1751099666579,
7333
+ # "data": {
7334
+ # "list": [
7335
+ # {
7336
+ # "execId": "1322441401010528257",
7337
+ # "orderId": "1322441400976261120",
7338
+ # "category": "USDT-FUTURES",
7339
+ # "symbol": "BTCUSDT",
7340
+ # "orderType": "market",
7341
+ # "side": "sell",
7342
+ # "execPrice": "107005.4",
7343
+ # "execQty": "0.0001",
7344
+ # "execValue": "10.7005",
7345
+ # "tradeScope": "taker",
7346
+ # "feeDetail": [{
7347
+ # "feeCoin": "USDT",
7348
+ # "fee":"0.00642032"
7349
+ # }],
7350
+ # "createdTime": "1751020520451",
7351
+ # "updatedTime": "1751020520458",
7352
+ # "execPnl": "0.00017"
7353
+ # },
7354
+ # ],
7355
+ # "cursor": "1322061241878880257"
7356
+ # }
7357
+ # }
7358
+ #
6260
7359
  data = self.safe_value(response, 'data')
6261
- if (market['swap']) or (market['future']):
6262
- fillList = self.safe_list(data, 'fillList', [])
6263
- return self.parse_trades(fillList, market, since, limit)
7360
+ if uta:
7361
+ fills = self.safe_list(data, 'list', [])
7362
+ return self.parse_trades(fills, market, since, limit)
7363
+ elif (market['swap'] or (market['future'])):
7364
+ fills = self.safe_list(data, 'fillList', [])
7365
+ return self.parse_trades(fills, market, since, limit)
6264
7366
  elif marginMode is not None:
6265
7367
  fills = self.safe_list(data, 'fills', [])
6266
7368
  return self.parse_trades(fills, market, since, limit)
@@ -6271,9 +7373,11 @@ class bitget(Exchange, ImplicitAPI):
6271
7373
  fetch data on a single open contract trade position
6272
7374
 
6273
7375
  https://www.bitget.com/api-doc/contract/position/get-single-position
7376
+ https://www.bitget.com/api-doc/uta/trade/Get-Position
6274
7377
 
6275
7378
  :param str symbol: unified market symbol of the market the position is held in
6276
7379
  :param dict [params]: extra parameters specific to the exchange API endpoint
7380
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6277
7381
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
6278
7382
  """
6279
7383
  await self.load_markets()
@@ -6282,42 +7386,90 @@ class bitget(Exchange, ImplicitAPI):
6282
7386
  productType, params = self.handle_product_type_and_params(market, params)
6283
7387
  request: dict = {
6284
7388
  'symbol': market['id'],
6285
- 'marginCoin': market['settleId'],
6286
- 'productType': productType,
6287
7389
  }
6288
- response = await self.privateMixGetV2MixPositionSinglePosition(self.extend(request, params))
6289
- #
6290
- # {
6291
- # "code": "00000",
6292
- # "msg": "success",
6293
- # "requestTime": 1700807531673,
6294
- # "data": [
6295
- # {
6296
- # "marginCoin": "USDT",
6297
- # "symbol": "BTCUSDT",
6298
- # "holdSide": "long",
6299
- # "openDelegateSize": "0",
6300
- # "marginSize": "3.73555",
6301
- # "available": "0.002",
6302
- # "locked": "0",
6303
- # "total": "0.002",
6304
- # "leverage": "20",
6305
- # "achievedProfits": "0",
6306
- # "openPriceAvg": "37355.5",
6307
- # "marginMode": "crossed",
6308
- # "posMode": "hedge_mode",
6309
- # "unrealizedPL": "0.007",
6310
- # "liquidationPrice": "31724.970702417",
6311
- # "keepMarginRate": "0.004",
6312
- # "markPrice": "37359",
6313
- # "marginRatio": "0.029599540355",
6314
- # "cTime": "1700807507275"
6315
- # }
6316
- # ]
6317
- # }
6318
- #
6319
- data = self.safe_list(response, 'data', [])
6320
- first = self.safe_dict(data, 0, {})
7390
+ response = None
7391
+ uta = None
7392
+ result = None
7393
+ uta, params = self.handle_option_and_params(params, 'fetchPosition', 'uta', False)
7394
+ if uta:
7395
+ request['category'] = productType
7396
+ response = await self.privateUtaGetV3PositionCurrentPosition(self.extend(request, params))
7397
+ #
7398
+ # {
7399
+ # "code": "00000",
7400
+ # "msg": "success",
7401
+ # "requestTime": 1750929905423,
7402
+ # "data": {
7403
+ # "list": [
7404
+ # {
7405
+ # "category": "USDT-FUTURES",
7406
+ # "symbol": "BTCUSDT",
7407
+ # "marginCoin": "USDT",
7408
+ # "holdMode": "hedge_mode",
7409
+ # "posSide": "long",
7410
+ # "marginMode": "crossed",
7411
+ # "positionBalance": "5.435199",
7412
+ # "available": "0.001",
7413
+ # "frozen": "0",
7414
+ # "total": "0.001",
7415
+ # "leverage": "20",
7416
+ # "curRealisedPnl": "0",
7417
+ # "avgPrice": "107410.3",
7418
+ # "positionStatus": "normal",
7419
+ # "unrealisedPnl": "0.0047",
7420
+ # "liquidationPrice": "0",
7421
+ # "mmr": "0.004",
7422
+ # "profitRate": "0.0008647337475591",
7423
+ # "markPrice": "107415.3",
7424
+ # "breakEvenPrice": "107539.2",
7425
+ # "totalFunding": "0",
7426
+ # "openFeeTotal": "-0.06444618",
7427
+ # "closeFeeTotal": "0",
7428
+ # "createdTime": "1750495670699",
7429
+ # "updatedTime": "1750929883465"
7430
+ # }
7431
+ # ]
7432
+ # }
7433
+ # }
7434
+ #
7435
+ data = self.safe_dict(response, 'data', {})
7436
+ result = self.safe_list(data, 'list', [])
7437
+ else:
7438
+ request['marginCoin'] = market['settleId']
7439
+ request['productType'] = productType
7440
+ response = await self.privateMixGetV2MixPositionSinglePosition(self.extend(request, params))
7441
+ #
7442
+ # {
7443
+ # "code": "00000",
7444
+ # "msg": "success",
7445
+ # "requestTime": 1700807531673,
7446
+ # "data": [
7447
+ # {
7448
+ # "marginCoin": "USDT",
7449
+ # "symbol": "BTCUSDT",
7450
+ # "holdSide": "long",
7451
+ # "openDelegateSize": "0",
7452
+ # "marginSize": "3.73555",
7453
+ # "available": "0.002",
7454
+ # "locked": "0",
7455
+ # "total": "0.002",
7456
+ # "leverage": "20",
7457
+ # "achievedProfits": "0",
7458
+ # "openPriceAvg": "37355.5",
7459
+ # "marginMode": "crossed",
7460
+ # "posMode": "hedge_mode",
7461
+ # "unrealizedPL": "0.007",
7462
+ # "liquidationPrice": "31724.970702417",
7463
+ # "keepMarginRate": "0.004",
7464
+ # "markPrice": "37359",
7465
+ # "marginRatio": "0.029599540355",
7466
+ # "cTime": "1700807507275"
7467
+ # }
7468
+ # ]
7469
+ # }
7470
+ #
7471
+ result = self.safe_list(response, 'data', [])
7472
+ first = self.safe_dict(result, 0, {})
6321
7473
  return self.parse_position(first, market)
6322
7474
 
6323
7475
  async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
@@ -6480,6 +7632,36 @@ class bitget(Exchange, ImplicitAPI):
6480
7632
  # "cTime": "1700807507275"
6481
7633
  # }
6482
7634
  #
7635
+ # uta: fetchPosition
7636
+ #
7637
+ # {
7638
+ # "category": "USDT-FUTURES",
7639
+ # "symbol": "BTCUSDT",
7640
+ # "marginCoin": "USDT",
7641
+ # "holdMode": "hedge_mode",
7642
+ # "posSide": "long",
7643
+ # "marginMode": "crossed",
7644
+ # "positionBalance": "5.435199",
7645
+ # "available": "0.001",
7646
+ # "frozen": "0",
7647
+ # "total": "0.001",
7648
+ # "leverage": "20",
7649
+ # "curRealisedPnl": "0",
7650
+ # "avgPrice": "107410.3",
7651
+ # "positionStatus": "normal",
7652
+ # "unrealisedPnl": "0.0047",
7653
+ # "liquidationPrice": "0",
7654
+ # "mmr": "0.004",
7655
+ # "profitRate": "0.0008647337475591",
7656
+ # "markPrice": "107415.3",
7657
+ # "breakEvenPrice": "107539.2",
7658
+ # "totalFunding": "0",
7659
+ # "openFeeTotal": "-0.06444618",
7660
+ # "closeFeeTotal": "0",
7661
+ # "createdTime": "1750495670699",
7662
+ # "updatedTime": "1750929883465"
7663
+ # }
7664
+ #
6483
7665
  # fetchPositions: privateMixGetV2MixPositionAllPosition
6484
7666
  #
6485
7667
  # {
@@ -6531,32 +7713,55 @@ class bitget(Exchange, ImplicitAPI):
6531
7713
  # "clientOid": "1120923953904893956"
6532
7714
  # }
6533
7715
  #
7716
+ # uta: fetchPositionsHistory
7717
+ #
7718
+ # {
7719
+ # "positionId": "1322441328637100049",
7720
+ # "category": "USDT-FUTURES",
7721
+ # "symbol": "BTCUSDT",
7722
+ # "marginCoin": "USDT",
7723
+ # "holdMode": "hedge_mode",
7724
+ # "posSide": "long",
7725
+ # "marginMode": "crossed",
7726
+ # "openPriceAvg": "107003.7",
7727
+ # "closePriceAvg": "107005.4",
7728
+ # "openTotalPos": "0.0001",
7729
+ # "closeTotalPos": "0.0001",
7730
+ # "cumRealisedPnl": "0.00017",
7731
+ # "netProfit": "-0.01267055",
7732
+ # "totalFunding": "0",
7733
+ # "openFeeTotal": "-0.00642022",
7734
+ # "closeFeeTotal": "-0.00642032",
7735
+ # "createdTime": "1751020503195",
7736
+ # "updatedTime": "1751020520458"
7737
+ # }
7738
+ #
6534
7739
  marketId = self.safe_string(position, 'symbol')
6535
7740
  market = self.safe_market(marketId, market, None, 'contract')
6536
7741
  symbol = market['symbol']
6537
- timestamp = self.safe_integer_2(position, 'cTime', 'ctime')
7742
+ timestamp = self.safe_integer_n(position, ['cTime', 'ctime', 'createdTime'])
6538
7743
  marginMode = self.safe_string(position, 'marginMode')
6539
7744
  collateral = None
6540
7745
  initialMargin = None
6541
- unrealizedPnl = self.safe_string(position, 'unrealizedPL')
6542
- rawCollateral = self.safe_string(position, 'marginSize')
7746
+ unrealizedPnl = self.safe_string_2(position, 'unrealizedPL', 'unrealisedPnl')
7747
+ rawCollateral = self.safe_string_2(position, 'marginSize', 'positionBalance')
6543
7748
  if marginMode == 'isolated':
6544
7749
  collateral = Precise.string_add(rawCollateral, unrealizedPnl)
6545
7750
  elif marginMode == 'crossed':
6546
7751
  marginMode = 'cross'
6547
7752
  initialMargin = rawCollateral
6548
- holdMode = self.safe_string(position, 'posMode')
7753
+ holdMode = self.safe_string_2(position, 'posMode', 'holdMode')
6549
7754
  hedged = None
6550
7755
  if holdMode == 'hedge_mode':
6551
7756
  hedged = True
6552
7757
  elif holdMode == 'one_way_mode':
6553
7758
  hedged = False
6554
- side = self.safe_string(position, 'holdSide')
7759
+ side = self.safe_string_2(position, 'holdSide', 'posSide')
6555
7760
  leverage = self.safe_string(position, 'leverage')
6556
7761
  contractSizeNumber = self.safe_value(market, 'contractSize')
6557
7762
  contractSize = self.number_to_string(contractSizeNumber)
6558
- baseAmount = self.safe_string(position, 'total')
6559
- entryPrice = self.safe_string_2(position, 'openPriceAvg', 'openAvgPrice')
7763
+ baseAmount = self.safe_string_2(position, 'total', 'openTotalPos')
7764
+ entryPrice = self.safe_string_n(position, ['openPriceAvg', 'openAvgPrice', 'avgPrice'])
6560
7765
  maintenanceMarginPercentage = self.safe_string(position, 'keepMarginRate')
6561
7766
  openNotional = Precise.string_mul(entryPrice, baseAmount)
6562
7767
  if initialMargin is None:
@@ -6588,31 +7793,31 @@ class bitget(Exchange, ImplicitAPI):
6588
7793
  percentage = Precise.string_mul(Precise.string_div(unrealizedPnl, initialMargin, 4), '100')
6589
7794
  return self.safe_position({
6590
7795
  'info': position,
6591
- 'id': self.safe_string(position, 'orderId'),
7796
+ 'id': self.safe_string_2(position, 'orderId', 'positionId'),
6592
7797
  'symbol': symbol,
6593
7798
  'notional': self.parse_number(notional),
6594
7799
  'marginMode': marginMode,
6595
7800
  'liquidationPrice': liquidationPrice,
6596
7801
  'entryPrice': self.parse_number(entryPrice),
6597
7802
  'unrealizedPnl': self.parse_number(unrealizedPnl),
6598
- 'realizedPnl': self.safe_number(position, 'pnl'),
7803
+ 'realizedPnl': self.safe_number_n(position, ['pnl', 'curRealisedPnl', 'cumRealisedPnl']),
6599
7804
  'percentage': self.parse_number(percentage),
6600
7805
  'contracts': contracts,
6601
7806
  'contractSize': contractSizeNumber,
6602
7807
  'markPrice': self.parse_number(markPrice),
6603
- 'lastPrice': self.safe_number(position, 'closeAvgPrice'),
7808
+ 'lastPrice': self.safe_number_2(position, 'closeAvgPrice', 'closePriceAvg'),
6604
7809
  'side': side,
6605
7810
  'hedged': hedged,
6606
7811
  'timestamp': timestamp,
6607
7812
  'datetime': self.iso8601(timestamp),
6608
- 'lastUpdateTimestamp': self.safe_integer(position, 'utime'),
7813
+ 'lastUpdateTimestamp': self.safe_integer_2(position, 'utime', 'updatedTime'),
6609
7814
  'maintenanceMargin': self.parse_number(maintenanceMargin),
6610
7815
  'maintenanceMarginPercentage': self.parse_number(maintenanceMarginPercentage),
6611
7816
  'collateral': self.parse_number(collateral),
6612
7817
  'initialMargin': self.parse_number(initialMargin),
6613
7818
  'initialMarginPercentage': self.parse_number(initialMarginPercentage),
6614
7819
  'leverage': self.parse_number(leverage),
6615
- 'marginRatio': self.safe_number(position, 'marginRatio'),
7820
+ 'marginRatio': self.safe_number_2(position, 'marginRatio', 'mmr'),
6616
7821
  'stopLossPrice': None,
6617
7822
  'takeProfitPrice': None,
6618
7823
  })
@@ -6622,54 +7827,82 @@ class bitget(Exchange, ImplicitAPI):
6622
7827
  fetches historical funding rate prices
6623
7828
 
6624
7829
  https://www.bitget.com/api-doc/contract/market/Get-History-Funding-Rate
7830
+ https://www.bitget.com/api-doc/uta/public/Get-History-Funding-Rate
6625
7831
 
6626
7832
  :param str symbol: unified symbol of the market to fetch the funding rate history for
6627
7833
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
6628
7834
  :param int [limit]: the maximum amount of funding rate structures to fetch
6629
7835
  :param dict [params]: extra parameters specific to the exchange API endpoint
7836
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6630
7837
  :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)
6631
7838
  :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
6632
7839
  """
6633
7840
  if symbol is None:
6634
7841
  raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
6635
7842
  await self.load_markets()
6636
- paginate = False
6637
- paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
6638
- if paginate:
6639
- return await self.fetch_paginated_call_incremental('fetchFundingRateHistory', symbol, since, limit, params, 'pageNo', 100)
6640
7843
  market = self.market(symbol)
6641
- productType = None
6642
- productType, params = self.handle_product_type_and_params(market, params)
6643
7844
  request: dict = {
6644
7845
  'symbol': market['id'],
6645
- 'productType': productType,
6646
- # 'pageSize': limit, # default 20
6647
- # 'pageNo': 1,
6648
7846
  }
6649
- if limit is not None:
6650
- request['pageSize'] = limit
6651
- response = await self.publicMixGetV2MixMarketHistoryFundRate(self.extend(request, params))
6652
- #
6653
- # {
6654
- # "code": "00000",
6655
- # "msg": "success",
6656
- # "requestTime": 1652406728393,
6657
- # "data": [
6658
- # {
6659
- # "symbol": "BTCUSDT",
6660
- # "fundingRate": "-0.0003",
6661
- # "fundingTime": "1652396400000"
6662
- # },
6663
- # ]
6664
- # }
6665
- #
6666
- data = self.safe_value(response, 'data', [])
7847
+ productType = None
7848
+ uta = None
7849
+ response = None
7850
+ result = None
7851
+ productType, params = self.handle_product_type_and_params(market, params)
7852
+ uta, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'uta', False)
7853
+ if uta:
7854
+ if limit is not None:
7855
+ request['limit'] = limit
7856
+ request['category'] = productType
7857
+ response = await self.publicUtaGetV3MarketHistoryFundRate(self.extend(request, params))
7858
+ #
7859
+ # {
7860
+ # "code": "00000",
7861
+ # "msg": "success",
7862
+ # "requestTime": 1750435113658,
7863
+ # "data": {
7864
+ # "resultList": [
7865
+ # {
7866
+ # "symbol": "BTCUSDT",
7867
+ # "fundingRate": "-0.000017",
7868
+ # "fundingRateTimestamp": "1750431600000"
7869
+ # },
7870
+ # ]
7871
+ # }
7872
+ # }
7873
+ #
7874
+ data = self.safe_dict(response, 'data', {})
7875
+ result = self.safe_list(data, 'resultList', [])
7876
+ else:
7877
+ paginate = False
7878
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
7879
+ if paginate:
7880
+ return await self.fetch_paginated_call_incremental('fetchFundingRateHistory', symbol, since, limit, params, 'pageNo', 100)
7881
+ if limit is not None:
7882
+ request['pageSize'] = limit
7883
+ request['productType'] = productType
7884
+ response = await self.publicMixGetV2MixMarketHistoryFundRate(self.extend(request, params))
7885
+ #
7886
+ # {
7887
+ # "code": "00000",
7888
+ # "msg": "success",
7889
+ # "requestTime": 1652406728393,
7890
+ # "data": [
7891
+ # {
7892
+ # "symbol": "BTCUSDT",
7893
+ # "fundingRate": "-0.0003",
7894
+ # "fundingTime": "1652396400000"
7895
+ # },
7896
+ # ]
7897
+ # }
7898
+ #
7899
+ result = self.safe_list(response, 'data', [])
6667
7900
  rates = []
6668
- for i in range(0, len(data)):
6669
- entry = data[i]
7901
+ for i in range(0, len(result)):
7902
+ entry = result[i]
6670
7903
  marketId = self.safe_string(entry, 'symbol')
6671
7904
  symbolInner = self.safe_symbol(marketId, market)
6672
- timestamp = self.safe_integer(entry, 'fundingTime')
7905
+ timestamp = self.safe_integer_2(entry, 'fundingTime', 'fundingRateTimestamp')
6673
7906
  rates.append({
6674
7907
  'info': entry,
6675
7908
  'symbol': symbolInner,
@@ -6686,9 +7919,11 @@ class bitget(Exchange, ImplicitAPI):
6686
7919
 
6687
7920
  https://www.bitget.com/api-doc/contract/market/Get-Current-Funding-Rate
6688
7921
  https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
7922
+ https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
6689
7923
 
6690
7924
  :param str symbol: unified market symbol
6691
7925
  :param dict [params]: extra parameters specific to the exchange API endpoint
7926
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6692
7927
  :param str [params.method]: either(default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
6693
7928
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
6694
7929
  """
@@ -6700,46 +7935,68 @@ class bitget(Exchange, ImplicitAPI):
6700
7935
  productType, params = self.handle_product_type_and_params(market, params)
6701
7936
  request: dict = {
6702
7937
  'symbol': market['id'],
6703
- 'productType': productType,
6704
7938
  }
6705
- method = None
6706
- method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
7939
+ uta = None
6707
7940
  response = None
6708
- if method == 'publicMixGetV2MixMarketCurrentFundRate':
6709
- response = await self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
7941
+ uta, params = self.handle_option_and_params(params, 'fetchFundingRate', 'uta', False)
7942
+ if uta:
7943
+ response = await self.publicUtaGetV3MarketCurrentFundRate(self.extend(request, params))
6710
7944
  #
6711
7945
  # {
6712
7946
  # "code": "00000",
6713
7947
  # "msg": "success",
6714
- # "requestTime": 1745500709429,
7948
+ # "requestTime": 1750897372153,
6715
7949
  # "data": [
6716
7950
  # {
6717
7951
  # "symbol": "BTCUSDT",
6718
- # "fundingRate": "-0.000013",
7952
+ # "fundingRate": "0.00001",
6719
7953
  # "fundingRateInterval": "8",
6720
- # "nextUpdate": "1745510400000",
7954
+ # "nextUpdate": "1750924800000",
6721
7955
  # "minFundingRate": "-0.003",
6722
7956
  # "maxFundingRate": "0.003"
6723
7957
  # }
6724
7958
  # ]
6725
7959
  # }
6726
7960
  #
6727
- elif method == 'publicMixGetV2MixMarketFundingTime':
6728
- response = await self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
6729
- #
6730
- # {
6731
- # "code": "00000",
6732
- # "msg": "success",
6733
- # "requestTime": 1745402092428,
6734
- # "data": [
6735
- # {
6736
- # "symbol": "BTCUSDT",
6737
- # "nextFundingTime": "1745424000000",
6738
- # "ratePeriod": "8"
6739
- # }
6740
- # ]
6741
- # }
6742
- #
7961
+ else:
7962
+ request['productType'] = productType
7963
+ method = None
7964
+ method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
7965
+ if method == 'publicMixGetV2MixMarketCurrentFundRate':
7966
+ response = await self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
7967
+ #
7968
+ # {
7969
+ # "code": "00000",
7970
+ # "msg": "success",
7971
+ # "requestTime": 1745500709429,
7972
+ # "data": [
7973
+ # {
7974
+ # "symbol": "BTCUSDT",
7975
+ # "fundingRate": "-0.000013",
7976
+ # "fundingRateInterval": "8",
7977
+ # "nextUpdate": "1745510400000",
7978
+ # "minFundingRate": "-0.003",
7979
+ # "maxFundingRate": "0.003"
7980
+ # }
7981
+ # ]
7982
+ # }
7983
+ #
7984
+ elif method == 'publicMixGetV2MixMarketFundingTime':
7985
+ response = await self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
7986
+ #
7987
+ # {
7988
+ # "code": "00000",
7989
+ # "msg": "success",
7990
+ # "requestTime": 1745402092428,
7991
+ # "data": [
7992
+ # {
7993
+ # "symbol": "BTCUSDT",
7994
+ # "nextFundingTime": "1745424000000",
7995
+ # "ratePeriod": "8"
7996
+ # }
7997
+ # ]
7998
+ # }
7999
+ #
6743
8000
  data = self.safe_list(response, 'data', [])
6744
8001
  return self.parse_funding_rate(data[0], market)
6745
8002
 
@@ -6803,7 +8060,7 @@ class bitget(Exchange, ImplicitAPI):
6803
8060
 
6804
8061
  def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
6805
8062
  #
6806
- # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate
8063
+ # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate, publicUtaGetV3MarketCurrentFundRate
6807
8064
  #
6808
8065
  # {
6809
8066
  # "symbol": "BTCUSDT",
@@ -7144,16 +8401,19 @@ class bitget(Exchange, ImplicitAPI):
7144
8401
  'shortLeverage': self.safe_integer(leverage, shortLevKey),
7145
8402
  }
7146
8403
 
7147
- async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
8404
+ async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
7148
8405
  """
7149
8406
  set the level of leverage for a market
7150
8407
 
7151
8408
  https://www.bitget.com/api-doc/contract/account/Change-Leverage
8409
+ https://www.bitget.com/api-doc/uta/account/Change-Leverage
7152
8410
 
7153
8411
  :param int leverage: the rate of leverage
7154
8412
  :param str symbol: unified market symbol
7155
8413
  :param dict [params]: extra parameters specific to the exchange API endpoint
7156
8414
  :param str [params.holdSide]: *isolated only* position direction, 'long' or 'short'
8415
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8416
+ :param boolean [params.posSide]: required for uta isolated margin, long or short
7157
8417
  :returns dict: response from the exchange
7158
8418
  """
7159
8419
  if symbol is None:
@@ -7164,27 +8424,47 @@ class bitget(Exchange, ImplicitAPI):
7164
8424
  productType, params = self.handle_product_type_and_params(market, params)
7165
8425
  request: dict = {
7166
8426
  'symbol': market['id'],
7167
- 'marginCoin': market['settleId'],
7168
8427
  'leverage': self.number_to_string(leverage),
7169
- 'productType': productType,
7170
- # 'holdSide': 'long',
7171
8428
  }
7172
- response = await self.privateMixPostV2MixAccountSetLeverage(self.extend(request, params))
7173
- #
7174
- # {
7175
- # "code": "00000",
7176
- # "msg": "success",
7177
- # "requestTime": 1700864711517,
7178
- # "data": {
7179
- # "symbol": "BTCUSDT",
7180
- # "marginCoin": "USDT",
7181
- # "longLeverage": "25",
7182
- # "shortLeverage": "25",
7183
- # "crossMarginLeverage": "25",
7184
- # "marginMode": "crossed"
7185
- # }
7186
- # }
7187
- #
8429
+ uta = None
8430
+ response = None
8431
+ uta, params = self.handle_option_and_params(params, 'setLeverage', 'uta', False)
8432
+ if uta:
8433
+ if productType == 'SPOT':
8434
+ marginMode = None
8435
+ marginMode, params = self.handle_margin_mode_and_params('fetchTrades', params)
8436
+ if marginMode is not None:
8437
+ productType = 'MARGIN'
8438
+ request['coin'] = market['settleId']
8439
+ request['category'] = productType
8440
+ response = await self.privateUtaPostV3AccountSetLeverage(self.extend(request, params))
8441
+ #
8442
+ # {
8443
+ # "code": "00000",
8444
+ # "msg": "success",
8445
+ # "requestTime": 1752815940833,
8446
+ # "data": "success"
8447
+ # }
8448
+ #
8449
+ else:
8450
+ request['marginCoin'] = market['settleId']
8451
+ request['productType'] = productType
8452
+ response = await self.privateMixPostV2MixAccountSetLeverage(self.extend(request, params))
8453
+ #
8454
+ # {
8455
+ # "code": "00000",
8456
+ # "msg": "success",
8457
+ # "requestTime": 1700864711517,
8458
+ # "data": {
8459
+ # "symbol": "BTCUSDT",
8460
+ # "marginCoin": "USDT",
8461
+ # "longLeverage": "25",
8462
+ # "shortLeverage": "25",
8463
+ # "crossMarginLeverage": "25",
8464
+ # "marginMode": "crossed"
8465
+ # }
8466
+ # }
8467
+ #
7188
8468
  return response
7189
8469
 
7190
8470
  async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
@@ -7237,35 +8517,51 @@ class bitget(Exchange, ImplicitAPI):
7237
8517
  set hedged to True or False for a market
7238
8518
 
7239
8519
  https://www.bitget.com/api-doc/contract/account/Change-Hold-Mode
8520
+ https://www.bitget.com/api-doc/uta/account/Change-Position-Mode
7240
8521
 
7241
8522
  :param bool hedged: set to True to use dualSidePosition
7242
8523
  :param str symbol: not used by bitget setPositionMode()
7243
8524
  :param dict [params]: extra parameters specific to the exchange API endpoint
7244
- :param str [params.productType]: required if symbol is None: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
8525
+ :param str [params.productType]: required if not uta and symbol is None: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
8526
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
7245
8527
  :returns dict: response from the exchange
7246
8528
  """
7247
8529
  await self.load_markets()
7248
8530
  posMode = 'hedge_mode' if hedged else 'one_way_mode'
8531
+ request: dict = {}
7249
8532
  market = None
7250
8533
  if symbol is not None:
7251
8534
  market = self.market(symbol)
7252
8535
  productType = None
8536
+ uta = None
8537
+ response = None
7253
8538
  productType, params = self.handle_product_type_and_params(market, params)
7254
- request: dict = {
7255
- 'posMode': posMode,
7256
- 'productType': productType,
7257
- }
7258
- response = await self.privateMixPostV2MixAccountSetPositionMode(self.extend(request, params))
7259
- #
7260
- # {
7261
- # "code": "00000",
7262
- # "msg": "success",
7263
- # "requestTime": 1700865608009,
7264
- # "data": {
7265
- # "posMode": "hedge_mode"
7266
- # }
7267
- # }
7268
- #
8539
+ uta, params = self.handle_option_and_params(params, 'setPositionMode', 'uta', False)
8540
+ if uta:
8541
+ request['holdMode'] = posMode
8542
+ response = await self.privateUtaPostV3AccountSetHoldMode(self.extend(request, params))
8543
+ #
8544
+ # {
8545
+ # "code": "00000",
8546
+ # "msg": "success",
8547
+ # "requestTime": 1752816734592,
8548
+ # "data": "success"
8549
+ # }
8550
+ #
8551
+ else:
8552
+ request['posMode'] = posMode
8553
+ request['productType'] = productType
8554
+ response = await self.privateMixPostV2MixAccountSetPositionMode(self.extend(request, params))
8555
+ #
8556
+ # {
8557
+ # "code": "00000",
8558
+ # "msg": "success",
8559
+ # "requestTime": 1700865608009,
8560
+ # "data": {
8561
+ # "posMode": "hedge_mode"
8562
+ # }
8563
+ # }
8564
+ #
7269
8565
  return response
7270
8566
 
7271
8567
  async def fetch_open_interest(self, symbol: str, params={}):
@@ -7273,9 +8569,11 @@ class bitget(Exchange, ImplicitAPI):
7273
8569
  retrieves the open interest of a contract trading pair
7274
8570
 
7275
8571
  https://www.bitget.com/api-doc/contract/market/Get-Open-Interest
8572
+ https://www.bitget.com/api-doc/uta/public/Get-Open-Interest
7276
8573
 
7277
8574
  :param str symbol: unified CCXT market symbol
7278
8575
  :param dict [params]: exchange specific parameters
8576
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
7279
8577
  :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
7280
8578
  """
7281
8579
  await self.load_markets()
@@ -7286,29 +8584,54 @@ class bitget(Exchange, ImplicitAPI):
7286
8584
  productType, params = self.handle_product_type_and_params(market, params)
7287
8585
  request: dict = {
7288
8586
  'symbol': market['id'],
7289
- 'productType': productType,
7290
8587
  }
7291
- response = await self.publicMixGetV2MixMarketOpenInterest(self.extend(request, params))
7292
- #
7293
- # {
7294
- # "code": "00000",
7295
- # "msg": "success",
7296
- # "requestTime": 1700866041022,
7297
- # "data": {
7298
- # "openInterestList": [
7299
- # {
7300
- # "symbol": "BTCUSDT",
7301
- # "size": "52234.134"
7302
- # }
7303
- # ],
7304
- # "ts": "1700866041023"
7305
- # }
7306
- # }
7307
- #
8588
+ uta = None
8589
+ response = None
8590
+ uta, params = self.handle_option_and_params(params, 'fetchOpenInterest', 'uta', False)
8591
+ if uta:
8592
+ request['category'] = productType
8593
+ response = await self.publicUtaGetV3MarketOpenInterest(self.extend(request, params))
8594
+ #
8595
+ # {
8596
+ # "code": "00000",
8597
+ # "msg": "success",
8598
+ # "requestTime": 1751101221545,
8599
+ # "data": {
8600
+ # "list": [
8601
+ # {
8602
+ # "symbol": "BTCUSDT",
8603
+ # "openInterest": "18166.3583"
8604
+ # }
8605
+ # ],
8606
+ # "ts": "1751101220993"
8607
+ # }
8608
+ # }
8609
+ #
8610
+ else:
8611
+ request['productType'] = productType
8612
+ response = await self.publicMixGetV2MixMarketOpenInterest(self.extend(request, params))
8613
+ #
8614
+ # {
8615
+ # "code": "00000",
8616
+ # "msg": "success",
8617
+ # "requestTime": 1700866041022,
8618
+ # "data": {
8619
+ # "openInterestList": [
8620
+ # {
8621
+ # "symbol": "BTCUSDT",
8622
+ # "size": "52234.134"
8623
+ # }
8624
+ # ],
8625
+ # "ts": "1700866041023"
8626
+ # }
8627
+ # }
8628
+ #
7308
8629
  data = self.safe_dict(response, 'data', {})
7309
8630
  return self.parse_open_interest(data, market)
7310
8631
 
7311
8632
  def parse_open_interest(self, interest, market: Market = None):
8633
+ #
8634
+ # default
7312
8635
  #
7313
8636
  # {
7314
8637
  # "openInterestList": [
@@ -7320,12 +8643,24 @@ class bitget(Exchange, ImplicitAPI):
7320
8643
  # "ts": "1700866041023"
7321
8644
  # }
7322
8645
  #
7323
- data = self.safe_value(interest, 'openInterestList', [])
8646
+ # uta
8647
+ #
8648
+ # {
8649
+ # "list": [
8650
+ # {
8651
+ # "symbol": "BTCUSDT",
8652
+ # "openInterest": "18166.3583"
8653
+ # }
8654
+ # ],
8655
+ # "ts": "1751101220993"
8656
+ # }
8657
+ #
8658
+ data = self.safe_list_2(interest, 'openInterestList', 'list', [])
7324
8659
  timestamp = self.safe_integer(interest, 'ts')
7325
8660
  marketId = self.safe_string(data[0], 'symbol')
7326
8661
  return self.safe_open_interest({
7327
8662
  'symbol': self.safe_symbol(marketId, market, None, 'contract'),
7328
- 'openInterestAmount': self.safe_number(data[0], 'size'),
8663
+ 'openInterestAmount': self.safe_number_2(data[0], 'size', 'openInterest'),
7329
8664
  'openInterestValue': None,
7330
8665
  'timestamp': timestamp,
7331
8666
  'datetime': self.iso8601(timestamp),
@@ -8048,10 +9383,11 @@ class bitget(Exchange, ImplicitAPI):
8048
9383
  fetch the rate of interest to borrow a currency for margin trading
8049
9384
 
8050
9385
  https://www.bitget.com/api-doc/margin/cross/account/Get-Cross-Margin-Interest-Rate-And-Borrowable
9386
+ https://www.bitget.com/api-doc/uta/public/Get-Margin-Loans
8051
9387
 
8052
9388
  :param str code: unified currency code
8053
9389
  :param dict [params]: extra parameters specific to the exchange API endpoint
8054
- :param str [params.symbol]: required for isolated margin
9390
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8055
9391
  :returns dict: a `borrow rate structure <https://github.com/ccxt/ccxt/wiki/Manual#borrow-rate-structure>`
8056
9392
  """
8057
9393
  await self.load_markets()
@@ -8059,40 +9395,62 @@ class bitget(Exchange, ImplicitAPI):
8059
9395
  request: dict = {
8060
9396
  'coin': currency['id'],
8061
9397
  }
8062
- response = await self.privateMarginGetV2MarginCrossedInterestRateAndLimit(self.extend(request, params))
8063
- #
8064
- # {
8065
- # "code": "00000",
8066
- # "msg": "success",
8067
- # "requestTime": 1700879047861,
8068
- # "data": [
8069
- # {
8070
- # "coin": "BTC",
8071
- # "leverage": "3",
8072
- # "transferable": True,
8073
- # "borrowable": True,
8074
- # "dailyInterestRate": "0.00007",
8075
- # "annualInterestRate": "0.02555",
8076
- # "maxBorrowableAmount": "26",
8077
- # "vipList": [
8078
- # {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
8079
- # {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
8080
- # {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
8081
- # {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
8082
- # {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
8083
- # {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
8084
- # ]
8085
- # }
8086
- # ]
8087
- # }
8088
- #
9398
+ uta = None
9399
+ response = None
9400
+ result = None
9401
+ uta, params = self.handle_option_and_params(params, 'fetchCrossBorrowRate', 'uta', False)
9402
+ if uta:
9403
+ response = await self.publicUtaGetV3MarketMarginLoans(self.extend(request, params))
9404
+ #
9405
+ # {
9406
+ # "code": "00000",
9407
+ # "msg": "success",
9408
+ # "requestTime": 1752817798893,
9409
+ # "data": {
9410
+ # "dailyInterest": "0.00100008",
9411
+ # "annualInterest": "0.3650292",
9412
+ # "limit": "100"
9413
+ # }
9414
+ # }
9415
+ #
9416
+ result = self.safe_dict(response, 'data', {})
9417
+ else:
9418
+ response = await self.privateMarginGetV2MarginCrossedInterestRateAndLimit(self.extend(request, params))
9419
+ #
9420
+ # {
9421
+ # "code": "00000",
9422
+ # "msg": "success",
9423
+ # "requestTime": 1700879047861,
9424
+ # "data": [
9425
+ # {
9426
+ # "coin": "BTC",
9427
+ # "leverage": "3",
9428
+ # "transferable": True,
9429
+ # "borrowable": True,
9430
+ # "dailyInterestRate": "0.00007",
9431
+ # "annualInterestRate": "0.02555",
9432
+ # "maxBorrowableAmount": "26",
9433
+ # "vipList": [
9434
+ # {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
9435
+ # {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
9436
+ # {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
9437
+ # {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
9438
+ # {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
9439
+ # {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
9440
+ # ]
9441
+ # }
9442
+ # ]
9443
+ # }
9444
+ #
9445
+ data = self.safe_value(response, 'data', [])
9446
+ result = self.safe_value(data, 0, {})
8089
9447
  timestamp = self.safe_integer(response, 'requestTime')
8090
- data = self.safe_value(response, 'data', [])
8091
- first = self.safe_value(data, 0, {})
8092
- first['timestamp'] = timestamp
8093
- return self.parse_borrow_rate(first, currency)
9448
+ result['timestamp'] = timestamp
9449
+ return self.parse_borrow_rate(result, currency)
8094
9450
 
8095
9451
  def parse_borrow_rate(self, info, currency: Currency = None):
9452
+ #
9453
+ # default
8096
9454
  #
8097
9455
  # {
8098
9456
  # "coin": "BTC",
@@ -8112,11 +9470,19 @@ class bitget(Exchange, ImplicitAPI):
8112
9470
  # ]
8113
9471
  # }
8114
9472
  #
9473
+ # uta
9474
+ #
9475
+ # {
9476
+ # "dailyInterest": "0.00100008",
9477
+ # "annualInterest": "0.3650292",
9478
+ # "limit": "100"
9479
+ # }
9480
+ #
8115
9481
  currencyId = self.safe_string(info, 'coin')
8116
9482
  timestamp = self.safe_integer(info, 'timestamp')
8117
9483
  return {
8118
9484
  'currency': self.safe_currency_code(currencyId, currency),
8119
- 'rate': self.safe_number(info, 'dailyInterestRate'),
9485
+ 'rate': self.safe_number_2(info, 'dailyInterestRate', 'dailyInterest'),
8120
9486
  'period': 86400000, # 1-Day
8121
9487
  'timestamp': timestamp,
8122
9488
  'datetime': self.iso8601(timestamp),
@@ -8272,42 +9638,68 @@ class bitget(Exchange, ImplicitAPI):
8272
9638
  closes an open position for a market
8273
9639
 
8274
9640
  https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
9641
+ https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
8275
9642
 
8276
9643
  :param str symbol: unified CCXT market symbol
8277
9644
  :param str [side]: one-way mode: 'buy' or 'sell', hedge-mode: 'long' or 'short'
8278
9645
  :param dict [params]: extra parameters specific to the exchange API endpoint
9646
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8279
9647
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
8280
9648
  """
8281
9649
  await self.load_markets()
8282
9650
  market = self.market(symbol)
8283
- productType = None
8284
- productType, params = self.handle_product_type_and_params(market, params)
8285
9651
  request: dict = {
8286
9652
  'symbol': market['id'],
8287
- 'productType': productType,
8288
9653
  }
8289
- if side is not None:
8290
- request['holdSide'] = side
8291
- response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
8292
- #
8293
- # {
8294
- # "code": "00000",
8295
- # "msg": "success",
8296
- # "requestTime": 1702975017017,
8297
- # "data": {
8298
- # "successList": [
8299
- # {
8300
- # "orderId": "1120923953904893955",
8301
- # "clientOid": "1120923953904893956"
8302
- # }
8303
- # ],
8304
- # "failureList": [],
8305
- # "result": False
8306
- # }
8307
- # }
8308
- #
9654
+ productType = None
9655
+ uta = None
9656
+ response = None
9657
+ productType, params = self.handle_product_type_and_params(market, params)
9658
+ uta, params = self.handle_option_and_params(params, 'closePosition', 'uta', False)
9659
+ if uta:
9660
+ if side is not None:
9661
+ request['posSide'] = side
9662
+ request['category'] = productType
9663
+ response = await self.privateUtaPostV3TradeClosePositions(self.extend(request, params))
9664
+ #
9665
+ # {
9666
+ # "code": "00000",
9667
+ # "msg": "success",
9668
+ # "requestTime": 1751020218384,
9669
+ # "data": {
9670
+ # "list": [
9671
+ # {
9672
+ # "orderId": "1322440134099320832",
9673
+ # "clientOid": "1322440134099320833"
9674
+ # }
9675
+ # ]
9676
+ # }
9677
+ # }
9678
+ #
9679
+ else:
9680
+ if side is not None:
9681
+ request['holdSide'] = side
9682
+ request['productType'] = productType
9683
+ response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
9684
+ #
9685
+ # {
9686
+ # "code": "00000",
9687
+ # "msg": "success",
9688
+ # "requestTime": 1702975017017,
9689
+ # "data": {
9690
+ # "successList": [
9691
+ # {
9692
+ # "orderId": "1120923953904893955",
9693
+ # "clientOid": "1120923953904893956"
9694
+ # }
9695
+ # ],
9696
+ # "failureList": [],
9697
+ # "result": False
9698
+ # }
9699
+ # }
9700
+ #
8309
9701
  data = self.safe_value(response, 'data', {})
8310
- order = self.safe_list(data, 'successList', [])
9702
+ order = self.safe_list_2(data, 'successList', 'list', [])
8311
9703
  return self.parse_order(order[0], market)
8312
9704
 
8313
9705
  async def close_all_positions(self, params={}) -> List[Position]:
@@ -8315,37 +9707,60 @@ class bitget(Exchange, ImplicitAPI):
8315
9707
  closes all open positions for a market type
8316
9708
 
8317
9709
  https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
9710
+ https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
8318
9711
 
8319
9712
  :param dict [params]: extra parameters specific to the exchange API endpoint
8320
9713
  :param str [params.productType]: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
9714
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8321
9715
  :returns dict[]: A list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
8322
9716
  """
8323
9717
  await self.load_markets()
9718
+ request: dict = {}
8324
9719
  productType = None
9720
+ uta = None
9721
+ response = None
8325
9722
  productType, params = self.handle_product_type_and_params(None, params)
8326
- request: dict = {
8327
- 'productType': productType,
8328
- }
8329
- response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
8330
- #
8331
- # {
8332
- # "code": "00000",
8333
- # "msg": "success",
8334
- # "requestTime": 1702975017017,
8335
- # "data": {
8336
- # "successList": [
8337
- # {
8338
- # "orderId": "1120923953904893955",
8339
- # "clientOid": "1120923953904893956"
8340
- # }
8341
- # ],
8342
- # "failureList": [],
8343
- # "result": False
8344
- # }
8345
- # }
8346
- #
9723
+ uta, params = self.handle_option_and_params(params, 'closeAllPositions', 'uta', False)
9724
+ if uta:
9725
+ request['category'] = productType
9726
+ response = await self.privateUtaPostV3TradeClosePositions(self.extend(request, params))
9727
+ #
9728
+ # {
9729
+ # "code": "00000",
9730
+ # "msg": "success",
9731
+ # "requestTime": 1751020218384,
9732
+ # "data": {
9733
+ # "list": [
9734
+ # {
9735
+ # "orderId": "1322440134099320832",
9736
+ # "clientOid": "1322440134099320833"
9737
+ # }
9738
+ # ]
9739
+ # }
9740
+ # }
9741
+ #
9742
+ else:
9743
+ request['productType'] = productType
9744
+ response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
9745
+ #
9746
+ # {
9747
+ # "code": "00000",
9748
+ # "msg": "success",
9749
+ # "requestTime": 1702975017017,
9750
+ # "data": {
9751
+ # "successList": [
9752
+ # {
9753
+ # "orderId": "1120923953904893955",
9754
+ # "clientOid": "1120923953904893956"
9755
+ # }
9756
+ # ],
9757
+ # "failureList": [],
9758
+ # "result": False
9759
+ # }
9760
+ # }
9761
+ #
8347
9762
  data = self.safe_value(response, 'data', {})
8348
- orderInfo = self.safe_list(data, 'successList', [])
9763
+ orderInfo = self.safe_list_2(data, 'successList', 'list', [])
8349
9764
  return self.parse_positions(orderInfo, None, params)
8350
9765
 
8351
9766
  async def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
@@ -8413,21 +9828,23 @@ class bitget(Exchange, ImplicitAPI):
8413
9828
  fetches historical positions
8414
9829
 
8415
9830
  https://www.bitget.com/api-doc/contract/position/Get-History-Position
9831
+ https://www.bitget.com/api-doc/uta/trade/Get-Position-History
8416
9832
 
8417
9833
  :param str[] [symbols]: unified contract symbols
8418
9834
  :param int [since]: timestamp in ms of the earliest position to fetch, default=3 months ago, max range for params["until"] - since is 3 months
8419
9835
  :param int [limit]: the maximum amount of records to fetch, default=20, max=100
8420
9836
  :param dict params: extra parameters specific to the exchange api endpoint
8421
9837
  :param int [params.until]: timestamp in ms of the latest position to fetch, max range for params["until"] - since is 3 months
8422
-
8423
- EXCHANGE SPECIFIC PARAMETERS
8424
9838
  :param str [params.productType]: USDT-FUTURES(default), COIN-FUTURES, USDC-FUTURES, SUSDT-FUTURES, SCOIN-FUTURES, or SUSDC-FUTURES
9839
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8425
9840
  :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
8426
9841
  """
8427
9842
  await self.load_markets()
8428
- until = self.safe_integer(params, 'until')
8429
- params = self.omit(params, 'until')
8430
9843
  request: dict = {}
9844
+ market = None
9845
+ productType = None
9846
+ uta = None
9847
+ response = None
8431
9848
  if symbols is not None:
8432
9849
  symbolsLength = len(symbols)
8433
9850
  if symbolsLength > 0:
@@ -8437,40 +9854,77 @@ class bitget(Exchange, ImplicitAPI):
8437
9854
  request['startTime'] = since
8438
9855
  if limit is not None:
8439
9856
  request['limit'] = limit
8440
- if until is not None:
8441
- request['endTime'] = until
8442
- response = await self.privateMixGetV2MixPositionHistoryPosition(self.extend(request, params))
8443
- #
8444
- # {
8445
- # code: '00000',
8446
- # msg: 'success',
8447
- # requestTime: '1712794148791',
8448
- # data: {
8449
- # list: [
8450
- # {
8451
- # symbol: 'XRPUSDT',
8452
- # marginCoin: 'USDT',
8453
- # holdSide: 'long',
8454
- # openAvgPrice: '0.64967',
8455
- # closeAvgPrice: '0.58799',
8456
- # marginMode: 'isolated',
8457
- # openTotalPos: '10',
8458
- # closeTotalPos: '10',
8459
- # pnl: '-0.62976205',
8460
- # netProfit: '-0.65356802',
8461
- # totalFunding: '-0.01638',
8462
- # openFee: '-0.00389802',
8463
- # closeFee: '-0.00352794',
8464
- # ctime: '1709590322199',
8465
- # utime: '1709667583395'
8466
- # },
8467
- # ...
8468
- # ]
8469
- # }
8470
- # }
8471
- #
8472
- data = self.safe_dict(response, 'data')
8473
- responseList = self.safe_list(data, 'list')
9857
+ request, params = self.handle_until_option('endTime', request, params)
9858
+ productType, params = self.handle_product_type_and_params(market, params)
9859
+ uta, params = self.handle_option_and_params(params, 'fetchPositionsHistory', 'uta', False)
9860
+ if uta:
9861
+ request['category'] = productType
9862
+ response = await self.privateUtaGetV3PositionHistoryPosition(self.extend(request, params))
9863
+ #
9864
+ # {
9865
+ # "code": "00000",
9866
+ # "msg": "success",
9867
+ # "requestTime": 1751020950427,
9868
+ # "data": {
9869
+ # "list": [
9870
+ # {
9871
+ # "positionId": "1322441328637100049",
9872
+ # "category": "USDT-FUTURES",
9873
+ # "symbol": "BTCUSDT",
9874
+ # "marginCoin": "USDT",
9875
+ # "holdMode": "hedge_mode",
9876
+ # "posSide": "long",
9877
+ # "marginMode": "crossed",
9878
+ # "openPriceAvg": "107003.7",
9879
+ # "closePriceAvg": "107005.4",
9880
+ # "openTotalPos": "0.0001",
9881
+ # "closeTotalPos": "0.0001",
9882
+ # "cumRealisedPnl": "0.00017",
9883
+ # "netProfit": "-0.01267055",
9884
+ # "totalFunding": "0",
9885
+ # "openFeeTotal": "-0.00642022",
9886
+ # "closeFeeTotal": "-0.00642032",
9887
+ # "createdTime": "1751020503195",
9888
+ # "updatedTime": "1751020520458"
9889
+ # },
9890
+ # ],
9891
+ # "cursor": "1322440134158041089"
9892
+ # }
9893
+ # }
9894
+ #
9895
+ else:
9896
+ response = await self.privateMixGetV2MixPositionHistoryPosition(self.extend(request, params))
9897
+ #
9898
+ # {
9899
+ # code: '00000',
9900
+ # msg: 'success',
9901
+ # requestTime: '1712794148791',
9902
+ # data: {
9903
+ # list: [
9904
+ # {
9905
+ # symbol: 'XRPUSDT',
9906
+ # marginCoin: 'USDT',
9907
+ # holdSide: 'long',
9908
+ # openAvgPrice: '0.64967',
9909
+ # closeAvgPrice: '0.58799',
9910
+ # marginMode: 'isolated',
9911
+ # openTotalPos: '10',
9912
+ # closeTotalPos: '10',
9913
+ # pnl: '-0.62976205',
9914
+ # netProfit: '-0.65356802',
9915
+ # totalFunding: '-0.01638',
9916
+ # openFee: '-0.00389802',
9917
+ # closeFee: '-0.00352794',
9918
+ # ctime: '1709590322199',
9919
+ # utime: '1709667583395'
9920
+ # },
9921
+ # ...
9922
+ # ]
9923
+ # }
9924
+ # }
9925
+ #
9926
+ data = self.safe_dict(response, 'data', {})
9927
+ responseList = self.safe_list(data, 'list', [])
8474
9928
  positions = self.parse_positions(responseList, symbols, params)
8475
9929
  return self.filter_by_since_limit(positions, since, limit)
8476
9930
 
@@ -8742,9 +10196,11 @@ class bitget(Exchange, ImplicitAPI):
8742
10196
  fetch the current funding rate interval
8743
10197
 
8744
10198
  https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
10199
+ https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
8745
10200
 
8746
10201
  :param str symbol: unified market symbol
8747
10202
  :param dict [params]: extra parameters specific to the exchange API endpoint
10203
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8748
10204
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
8749
10205
  """
8750
10206
  await self.load_markets()
@@ -8753,23 +10209,46 @@ class bitget(Exchange, ImplicitAPI):
8753
10209
  productType, params = self.handle_product_type_and_params(market, params)
8754
10210
  request: dict = {
8755
10211
  'symbol': market['id'],
8756
- 'productType': productType,
8757
10212
  }
8758
- response = await self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
8759
- #
8760
- # {
8761
- # "code": "00000",
8762
- # "msg": "success",
8763
- # "requestTime": 1727930153888,
8764
- # "data": [
8765
- # {
8766
- # "symbol": "BTCUSDT",
8767
- # "nextFundingTime": "1727942400000",
8768
- # "ratePeriod": "8"
8769
- # }
8770
- # ]
8771
- # }
8772
- #
10213
+ response = None
10214
+ uta = None
10215
+ uta, params = self.handle_option_and_params(params, 'fetchFundingInterval', 'uta', False)
10216
+ if uta:
10217
+ response = await self.publicUtaGetV3MarketCurrentFundRate(self.extend(request, params))
10218
+ #
10219
+ # {
10220
+ # "code": "00000",
10221
+ # "msg": "success",
10222
+ # "requestTime": 1752880157959,
10223
+ # "data": [
10224
+ # {
10225
+ # "symbol": "BTCUSDT",
10226
+ # "fundingRate": "0.0001",
10227
+ # "fundingRateInterval": "8",
10228
+ # "nextUpdate": "1752883200000",
10229
+ # "minFundingRate": "-0.003",
10230
+ # "maxFundingRate": "0.003"
10231
+ # }
10232
+ # ]
10233
+ # }
10234
+ #
10235
+ else:
10236
+ request['productType'] = productType
10237
+ response = await self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
10238
+ #
10239
+ # {
10240
+ # "code": "00000",
10241
+ # "msg": "success",
10242
+ # "requestTime": 1727930153888,
10243
+ # "data": [
10244
+ # {
10245
+ # "symbol": "BTCUSDT",
10246
+ # "nextFundingTime": "1727942400000",
10247
+ # "ratePeriod": "8"
10248
+ # }
10249
+ # ]
10250
+ # }
10251
+ #
8773
10252
  data = self.safe_list(response, 'data', [])
8774
10253
  first = self.safe_dict(data, 0, {})
8775
10254
  return self.parse_funding_rate(first, market)
@@ -8929,7 +10408,7 @@ class bitget(Exchange, ImplicitAPI):
8929
10408
  if method == 'POST':
8930
10409
  headers['Content-Type'] = 'application/json'
8931
10410
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
8932
- if sandboxMode and (path != 'v2/public/time'):
10411
+ if sandboxMode and (path != 'v2/public/time') and (path != 'v3/market/current-fund-rate'):
8933
10412
  # https://github.com/ccxt/ccxt/issues/25252#issuecomment-2662742336
8934
10413
  if headers is None:
8935
10414
  headers = {}