bitget 0.0.79__py3-none-any.whl → 0.0.80__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.
bitget/ccxt/bitget.py CHANGED
@@ -826,6 +826,7 @@ class bitget(Exchange, ImplicitAPI):
826
826
  'get': {
827
827
  'v3/account/assets': 1,
828
828
  'v3/account/settings': 1,
829
+ 'v3/account/deposit-records': 2,
829
830
  'v3/account/financial-records': 1,
830
831
  'v3/account/repayable-coins': 2,
831
832
  'v3/account/payment-coins': 2,
@@ -844,7 +845,9 @@ class bitget(Exchange, ImplicitAPI):
844
845
  'v3/position/history-position': 1,
845
846
  'v3/trade/order-info': 1,
846
847
  'v3/trade/unfilled-orders': 1,
848
+ 'v3/trade/unfilled-strategy-orders': 1,
847
849
  'v3/trade/history-orders': 1,
850
+ 'v3/trade/history-strategy-orders': 1,
848
851
  'v3/trade/fills': 1,
849
852
  'v3/user/sub-list': 2,
850
853
  'v3/user/sub-api-list': 2,
@@ -858,8 +861,11 @@ class bitget(Exchange, ImplicitAPI):
858
861
  'v3/account/max-open-available': 4,
859
862
  'v3/ins-loan/bind-uid': 6.6667,
860
863
  'v3/trade/place-order': 2,
864
+ 'v3/trade/place-strategy-order': 2,
861
865
  'v3/trade/modify-order': 2,
866
+ 'v3/trade/modify-strategy-order': 2,
862
867
  'v3/trade/cancel-order': 2,
868
+ 'v3/trade/cancel-strategy-order': 2,
863
869
  'v3/trade/place-batch': 4,
864
870
  'v3/trade/batch-modify-order': 2,
865
871
  'v3/trade/cancel-batch': 4,
@@ -905,6 +911,7 @@ class bitget(Exchange, ImplicitAPI):
905
911
  # '0': ExchangeError, # 200 successful,when the order placement / cancellation / operation is successful
906
912
  '4001': ExchangeError, # no data received in 30s
907
913
  '4002': ExchangeError, # Buffer full. cannot write data
914
+ '40020': BadRequest, # {"code":"40020","msg":"Parameter orderId error","requestTime":1754305078588,"data":null}
908
915
  # --------------------------------------------------------
909
916
  '30001': AuthenticationError, # {"code": 30001, "message": 'request header "OK_ACCESS_KEY" cannot be blank'}
910
917
  '30002': AuthenticationError, # {"code": 30002, "message": 'request header "OK_ACCESS_SIGN" cannot be blank'}
@@ -1449,6 +1456,19 @@ class bitget(Exchange, ImplicitAPI):
1449
1456
  '1w': '1Wutc',
1450
1457
  '1M': '1Mutc',
1451
1458
  },
1459
+ 'uta': {
1460
+ '1m': '1m',
1461
+ '3m': '3m',
1462
+ '5m': '5m',
1463
+ '15m': '15m',
1464
+ '30m': '30m',
1465
+ '1h': '1H',
1466
+ '2h': '2H',
1467
+ '4h': '4H',
1468
+ '6h': '6H',
1469
+ '12h': '12H',
1470
+ '1d': '1D',
1471
+ },
1452
1472
  },
1453
1473
  'fetchMarkets': {
1454
1474
  'types': ['spot', 'swap'], # there is future markets but they use the same endpoints
@@ -1538,7 +1558,6 @@ class bitget(Exchange, ImplicitAPI):
1538
1558
  'ERC20': 'ERC20',
1539
1559
  'BEP20': 'BSC',
1540
1560
  # 'BEP20': 'BEP20', # different for BEP20
1541
- 'BSC': 'BEP20',
1542
1561
  'ATOM': 'ATOM',
1543
1562
  'ACA': 'AcalaToken',
1544
1563
  'APT': 'Aptos',
@@ -1792,10 +1811,17 @@ class bitget(Exchange, ImplicitAPI):
1792
1811
  # else:
1793
1812
  defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1794
1813
  # }
1795
- productType = self.safe_string(params, 'productType', defaultProductType)
1814
+ productType = self.safe_string_2(params, 'productType', 'category', defaultProductType)
1796
1815
  if (productType is None) and (market is not None):
1797
1816
  settle = market['settle']
1798
- if settle == 'USDT':
1817
+ if market['spot']:
1818
+ marginMode = None
1819
+ marginMode, params = self.handle_margin_mode_and_params('handleProductTypeAndParams', params)
1820
+ if marginMode is not None:
1821
+ productType = 'MARGIN'
1822
+ else:
1823
+ productType = 'SPOT'
1824
+ elif settle == 'USDT':
1799
1825
  productType = 'USDT-FUTURES'
1800
1826
  elif settle == 'USDC':
1801
1827
  productType = 'USDC-FUTURES'
@@ -1808,8 +1834,8 @@ class bitget(Exchange, ImplicitAPI):
1808
1834
  else:
1809
1835
  productType = 'COIN-FUTURES'
1810
1836
  if productType is None:
1811
- raise ArgumentsRequired(self.id + ' requires a productType param, one of "USDT-FUTURES", "USDC-FUTURES", "COIN-FUTURES", "SUSDT-FUTURES", "SUSDC-FUTURES" or "SCOIN-FUTURES"')
1812
- params = self.omit(params, 'productType')
1837
+ 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"')
1838
+ params = self.omit(params, ['productType', 'category'])
1813
1839
  return [productType, params]
1814
1840
 
1815
1841
  def fetch_time(self, params={}) -> Int:
@@ -1842,10 +1868,10 @@ class bitget(Exchange, ImplicitAPI):
1842
1868
  https://www.bitget.com/api-doc/spot/market/Get-Symbols
1843
1869
  https://www.bitget.com/api-doc/contract/market/Get-All-Symbols-Contracts
1844
1870
  https://www.bitget.com/api-doc/margin/common/support-currencies
1845
- https://www.bitget.bike/api-doc/uta/public/Instruments
1871
+ https://www.bitget.com/api-doc/uta/public/Instruments
1846
1872
 
1847
1873
  :param dict [params]: extra parameters specific to the exchange API endpoint
1848
- :param str [params.uta]: set to True to fetch markets for the unified trading account(uta), defaults to False
1874
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
1849
1875
  :returns dict[]: an array of objects representing market data
1850
1876
  """
1851
1877
  if self.options['adjustForTimeDifference']:
@@ -2452,12 +2478,14 @@ class bitget(Exchange, ImplicitAPI):
2452
2478
  https://www.bitget.com/api-doc/contract/position/Get-Query-Position-Lever
2453
2479
  https://www.bitget.com/api-doc/margin/cross/account/Cross-Tier-Data
2454
2480
  https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Tier-Data
2481
+ https://www.bitget.com/api-doc/uta/public/Get-Position-Tier-Data
2455
2482
 
2456
2483
  :param str symbol: unified market symbol
2457
2484
  :param dict [params]: extra parameters specific to the exchange API endpoint
2458
2485
  :param str [params.marginMode]: for spot margin 'cross' or 'isolated', default is 'isolated'
2459
2486
  :param str [params.code]: required for cross spot margin
2460
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
2487
+ :param str [params.productType]: *contract and uta only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
2488
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
2461
2489
  :returns dict: a `leverage tiers structure <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
2462
2490
  """
2463
2491
  self.load_markets()
@@ -2465,10 +2493,19 @@ class bitget(Exchange, ImplicitAPI):
2465
2493
  request: dict = {}
2466
2494
  response = None
2467
2495
  marginMode = None
2496
+ productType = None
2497
+ uta = None
2468
2498
  marginMode, params = self.handle_margin_mode_and_params('fetchMarketLeverageTiers', params, 'isolated')
2469
- if (market['swap']) or (market['future']):
2470
- productType = None
2471
- productType, params = self.handle_product_type_and_params(market, params)
2499
+ productType, params = self.handle_product_type_and_params(market, params)
2500
+ uta, params = self.handle_option_and_params(params, 'fetchMarketLeverageTiers', 'uta', False)
2501
+ if uta:
2502
+ if productType == 'SPOT':
2503
+ if marginMode is not None:
2504
+ productType = 'MARGIN'
2505
+ request['symbol'] = market['id']
2506
+ request['category'] = productType
2507
+ response = self.publicUtaGetV3MarketPositionTier(self.extend(request, params))
2508
+ elif (market['swap']) or (market['future']):
2472
2509
  request['productType'] = productType
2473
2510
  request['symbol'] = market['id']
2474
2511
  response = self.publicMixGetV2MixMarketQueryPositionLever(self.extend(request, params))
@@ -2542,6 +2579,23 @@ class bitget(Exchange, ImplicitAPI):
2542
2579
  # ]
2543
2580
  # }
2544
2581
  #
2582
+ # uta
2583
+ #
2584
+ # {
2585
+ # "code": "00000",
2586
+ # "msg": "success",
2587
+ # "requestTime": 1752735673127,
2588
+ # "data": [
2589
+ # {
2590
+ # "tier": "1",
2591
+ # "minTierValue": "0",
2592
+ # "maxTierValue": "150000",
2593
+ # "leverage": "125",
2594
+ # "mmr": "0.004"
2595
+ # },
2596
+ # ]
2597
+ # }
2598
+ #
2545
2599
  result = self.safe_value(response, 'data', [])
2546
2600
  return self.parse_market_leverage_tiers(result, market)
2547
2601
 
@@ -2582,14 +2636,24 @@ class bitget(Exchange, ImplicitAPI):
2582
2636
  # "maintainMarginRate": "0.1"
2583
2637
  # }
2584
2638
  #
2639
+ # uta
2640
+ #
2641
+ # {
2642
+ # "tier": "1",
2643
+ # "minTierValue": "0",
2644
+ # "maxTierValue": "150000",
2645
+ # "leverage": "125",
2646
+ # "mmr": "0.004"
2647
+ # }
2648
+ #
2585
2649
  tiers = []
2586
2650
  minNotional = 0
2587
2651
  for i in range(0, len(info)):
2588
2652
  item = info[i]
2589
- minimumNotional = self.safe_number(item, 'startUnit')
2653
+ minimumNotional = self.safe_number_2(item, 'startUnit', 'minTierValue')
2590
2654
  if minimumNotional is not None:
2591
2655
  minNotional = minimumNotional
2592
- maxNotional = self.safe_number_n(item, ['endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount'])
2656
+ maxNotional = self.safe_number_n(item, ['endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount', 'maxTierValue'])
2593
2657
  marginCurrency = self.safe_string_2(item, 'coin', 'baseCoin')
2594
2658
  currencyId = marginCurrency if (marginCurrency is not None) else market['base']
2595
2659
  marketId = self.safe_string(item, 'symbol')
@@ -2599,7 +2663,7 @@ class bitget(Exchange, ImplicitAPI):
2599
2663
  'currency': self.safe_currency_code(currencyId),
2600
2664
  'minNotional': minNotional,
2601
2665
  'maxNotional': maxNotional,
2602
- 'maintenanceMarginRate': self.safe_number_2(item, 'keepMarginRate', 'maintainMarginRate'),
2666
+ 'maintenanceMarginRate': self.safe_number_n(item, ['keepMarginRate', 'maintainMarginRate', 'mmr']),
2603
2667
  'maxLeverage': self.safe_number(item, 'leverage'),
2604
2668
  'info': item,
2605
2669
  })
@@ -2941,10 +3005,12 @@ class bitget(Exchange, ImplicitAPI):
2941
3005
 
2942
3006
  https://www.bitget.com/api-doc/spot/market/Get-Orderbook
2943
3007
  https://www.bitget.com/api-doc/contract/market/Get-Merge-Depth
3008
+ https://www.bitget.com/api-doc/uta/public/OrderBook
2944
3009
 
2945
3010
  :param str symbol: unified symbol of the market to fetch the order book for
2946
3011
  :param int [limit]: the maximum amount of order book entries to return
2947
3012
  :param dict [params]: extra parameters specific to the exchange API endpoint
3013
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
2948
3014
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
2949
3015
  """
2950
3016
  self.load_markets()
@@ -2954,12 +3020,17 @@ class bitget(Exchange, ImplicitAPI):
2954
3020
  }
2955
3021
  if limit is not None:
2956
3022
  request['limit'] = limit
3023
+ productType = None
3024
+ productType, params = self.handle_product_type_and_params(market, params)
2957
3025
  response = None
2958
- if market['spot']:
3026
+ uta = None
3027
+ uta, params = self.handle_option_and_params(params, 'fetchOrderBook', 'uta', False)
3028
+ if uta:
3029
+ request['category'] = productType
3030
+ response = self.publicUtaGetV3MarketOrderbook(self.extend(request, params))
3031
+ elif market['spot']:
2959
3032
  response = self.publicSpotGetV2SpotMarketOrderbook(self.extend(request, params))
2960
3033
  else:
2961
- productType = None
2962
- productType, params = self.handle_product_type_and_params(market, params)
2963
3034
  request['productType'] = productType
2964
3035
  response = self.publicMixGetV2MixMarketMergeDepth(self.extend(request, params))
2965
3036
  #
@@ -2974,9 +3045,24 @@ class bitget(Exchange, ImplicitAPI):
2974
3045
  # }
2975
3046
  # }
2976
3047
  #
3048
+ # uta
3049
+ #
3050
+ # {
3051
+ # "code": "00000",
3052
+ # "msg": "success",
3053
+ # "requestTime": 1750329437753,
3054
+ # "data": {
3055
+ # "a": [[104992.60, 0.018411]],
3056
+ # "b":[[104927.40, 0.229914]],
3057
+ # "ts": "1750329437763"
3058
+ # }
3059
+ # }
3060
+ #
2977
3061
  data = self.safe_value(response, 'data', {})
3062
+ bidsKey = 'b' if uta else 'bids'
3063
+ asksKey = 'a' if uta else 'asks'
2978
3064
  timestamp = self.safe_integer(data, 'ts')
2979
- return self.parse_order_book(data, market['symbol'], timestamp)
3065
+ return self.parse_order_book(data, market['symbol'], timestamp, bidsKey, asksKey)
2980
3066
 
2981
3067
  def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
2982
3068
  #
@@ -2988,7 +3074,7 @@ class bitget(Exchange, ImplicitAPI):
2988
3074
  # "ts": "1695793390482"
2989
3075
  # }
2990
3076
  #
2991
- # spot: fetchTicker, fetchTickers
3077
+ # spot
2992
3078
  #
2993
3079
  # {
2994
3080
  # "open": "37202.46",
@@ -3009,90 +3095,115 @@ class bitget(Exchange, ImplicitAPI):
3009
3095
  # "change24h": "0.00321"
3010
3096
  # }
3011
3097
  #
3012
- # swap and future: fetchTicker
3098
+ # swap and future
3013
3099
  #
3014
3100
  # {
3015
3101
  # "symbol": "BTCUSDT",
3016
- # "lastPr": "37577.2",
3017
- # "askPr": "37577.3",
3018
- # "bidPr": "37577.2",
3019
- # "bidSz": "3.679",
3020
- # "askSz": "0.02",
3021
- # "high24h": "37765",
3022
- # "low24h": "36628.9",
3023
- # "ts": "1700533070359",
3024
- # "change24h": "0.00288",
3025
- # "baseVolume": "108606.181",
3026
- # "quoteVolume": "4051316303.9608",
3027
- # "usdtVolume": "4051316303.9608",
3028
- # "openUtc": "37451.5",
3029
- # "changeUtc24h": "0.00336",
3030
- # "indexPrice": "37574.489253",
3031
- # "fundingRate": "0.0001",
3032
- # "holdingAmount": "53464.529",
3102
+ # "lastPr": "104823.8",
3103
+ # "askPr": "104823.8",
3104
+ # "bidPr": "104823.5",
3105
+ # "bidSz": "0.703",
3106
+ # "askSz": "13.894",
3107
+ # "high24h": "105289.3",
3108
+ # "low24h": "103447.9",
3109
+ # "ts": "1750332210370",
3110
+ # "change24h": "0.00471",
3111
+ # "baseVolume": "79089.5675",
3112
+ # "quoteVolume": "8274870921.80485",
3113
+ # "usdtVolume": "8274870921.80485",
3114
+ # "openUtc": "104833",
3115
+ # "changeUtc24h": "-0.00009",
3116
+ # "indexPrice": "104881.953125",
3117
+ # "fundingRate": "-0.000014",
3118
+ # "holdingAmount": "7452.6421",
3033
3119
  # "deliveryStartTime": null,
3034
3120
  # "deliveryTime": null,
3035
3121
  # "deliveryStatus": "",
3036
- # "open24h": "37235.7"
3122
+ # "open24h": "104332.3",
3123
+ # "markPrice": "104824.2"
3124
+ # }
3125
+ #
3126
+ # spot uta
3127
+ #
3128
+ # {
3129
+ # "category": "SPOT",
3130
+ # "symbol": "BTCUSDT",
3131
+ # "ts": "1750330651972",
3132
+ # "lastPrice": "104900.2",
3133
+ # "openPrice24h": "104321.2",
3134
+ # "highPrice24h": "107956.8",
3135
+ # "lowPrice24h": "103600.1",
3136
+ # "ask1Price": "104945.8",
3137
+ # "bid1Price": "104880.6",
3138
+ # "bid1Size": "0.266534",
3139
+ # "ask1Size": "0.014001",
3140
+ # "price24hPcnt": "0.00555",
3141
+ # "volume24h": "355.941109",
3142
+ # "turnover24h": "37302936.008134"
3037
3143
  # }
3038
3144
  #
3039
- # swap and future: fetchTickers
3145
+ # swap and future uta
3040
3146
  #
3041
3147
  # {
3042
- # "open": "14.9776",
3043
- # "symbol": "LINKUSDT",
3044
- # "high24h": "15.3942",
3045
- # "low24h": "14.3457",
3046
- # "lastPr": "14.3748",
3047
- # "quoteVolume": "7008612.4299",
3048
- # "baseVolume": "469908.8523",
3049
- # "usdtVolume": "7008612.42986561",
3050
- # "ts": "1700533772309",
3051
- # "bidPr": "14.375",
3052
- # "askPr": "14.3769",
3053
- # "bidSz": "50.004",
3054
- # "askSz": "0.7647",
3055
- # "openUtc": "14.478",
3056
- # "changeUtc24h": "-0.00713",
3057
- # "change24h": "-0.04978"
3148
+ # "category": "USDT-FUTURES",
3149
+ # "symbol": "BTCUSDT",
3150
+ # "ts": "1750332730472",
3151
+ # "lastPrice": "104738",
3152
+ # "openPrice24h": "104374",
3153
+ # "highPrice24h": "105289.3",
3154
+ # "lowPrice24h": "103447.9",
3155
+ # "ask1Price": "104738",
3156
+ # "bid1Price": "104737.7",
3157
+ # "bid1Size": "2.036",
3158
+ # "ask1Size": "8.094",
3159
+ # "price24hPcnt": "0.00349",
3160
+ # "volume24h": "79101.6477",
3161
+ # "turnover24h": "8276293391.45973",
3162
+ # "indexPrice": "104785.956168",
3163
+ # "markPrice": "104738",
3164
+ # "fundingRate": "-0.000007",
3165
+ # "openInterest": "7465.5938",
3166
+ # "deliveryStartTime": "",
3167
+ # "deliveryTime": "",
3168
+ # "deliveryStatus": ""
3058
3169
  # }
3059
3170
  #
3060
3171
  marketId = self.safe_string(ticker, 'symbol')
3061
- close = self.safe_string(ticker, 'lastPr')
3172
+ close = self.safe_string_2(ticker, 'lastPr', 'lastPrice')
3062
3173
  timestamp = self.safe_integer_omit_zero(ticker, 'ts') # exchange bitget provided 0
3063
3174
  change = self.safe_string(ticker, 'change24h')
3064
- open24 = self.safe_string_2(ticker, 'open24', 'open24h')
3065
- open = self.safe_string(ticker, 'open')
3066
- symbol: str
3067
- openValue: str
3068
- if open is None:
3069
- symbol = self.safe_symbol(marketId, market, None, 'contract')
3070
- openValue = open24
3175
+ category = self.safe_string(ticker, 'category')
3176
+ markPrice = self.safe_string(ticker, 'markPrice')
3177
+ marketType: str
3178
+ if (markPrice is not None) and (category != 'SPOT'):
3179
+ marketType = 'contract'
3071
3180
  else:
3072
- symbol = self.safe_symbol(marketId, market, None, 'spot')
3073
- openValue = open
3181
+ marketType = 'spot'
3182
+ percentage = self.safe_string(ticker, 'price24hPcnt')
3183
+ if percentage is None:
3184
+ percentage = Precise.string_mul(change, '100')
3074
3185
  return self.safe_ticker({
3075
- 'symbol': symbol,
3186
+ 'symbol': self.safe_symbol(marketId, market, None, marketType),
3076
3187
  'timestamp': timestamp,
3077
3188
  'datetime': self.iso8601(timestamp),
3078
- 'high': self.safe_string(ticker, 'high24h'),
3079
- 'low': self.safe_string(ticker, 'low24h'),
3080
- 'bid': self.safe_string(ticker, 'bidPr'),
3081
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
3082
- 'ask': self.safe_string(ticker, 'askPr'),
3083
- 'askVolume': self.safe_string(ticker, 'askSz'),
3189
+ 'high': self.safe_string_2(ticker, 'high24h', 'highPrice24h'),
3190
+ 'low': self.safe_string_2(ticker, 'low24h', 'lowPrice24h'),
3191
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
3192
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
3193
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
3194
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
3084
3195
  'vwap': None,
3085
- 'open': openValue,
3196
+ 'open': self.safe_string_n(ticker, ['open', 'open24h', 'openPrice24h']),
3086
3197
  'close': close,
3087
3198
  'last': close,
3088
3199
  'previousClose': None,
3089
3200
  'change': change,
3090
- 'percentage': Precise.string_mul(change, '100'),
3201
+ 'percentage': percentage,
3091
3202
  'average': None,
3092
- 'baseVolume': self.safe_string(ticker, 'baseVolume'),
3093
- 'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
3203
+ 'baseVolume': self.safe_string_2(ticker, 'baseVolume', 'volume24h'),
3204
+ 'quoteVolume': self.safe_string_2(ticker, 'quoteVolume', 'turnover24h'),
3094
3205
  'indexPrice': self.safe_string(ticker, 'indexPrice'),
3095
- 'markPrice': self.safe_string(ticker, 'markPrice'),
3206
+ 'markPrice': markPrice,
3096
3207
  'info': ticker,
3097
3208
  }, market)
3098
3209
 
@@ -3102,9 +3213,11 @@ class bitget(Exchange, ImplicitAPI):
3102
3213
 
3103
3214
  https://www.bitget.com/api-doc/spot/market/Get-Tickers
3104
3215
  https://www.bitget.com/api-doc/contract/market/Get-Ticker
3216
+ https://www.bitget.com/api-doc/uta/public/Tickers
3105
3217
 
3106
3218
  :param str symbol: unified symbol of the market to fetch the ticker for
3107
3219
  :param dict [params]: extra parameters specific to the exchange API endpoint
3220
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3108
3221
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
3109
3222
  """
3110
3223
  self.load_markets()
@@ -3112,12 +3225,17 @@ class bitget(Exchange, ImplicitAPI):
3112
3225
  request: dict = {
3113
3226
  'symbol': market['id'],
3114
3227
  }
3228
+ productType = None
3229
+ productType, params = self.handle_product_type_and_params(market, params)
3115
3230
  response = None
3116
- if market['spot']:
3231
+ uta = None
3232
+ uta, params = self.handle_option_and_params(params, 'fetchTicker', 'uta', False)
3233
+ if uta:
3234
+ request['category'] = productType
3235
+ response = self.publicUtaGetV3MarketTickers(self.extend(request, params))
3236
+ elif market['spot']:
3117
3237
  response = self.publicSpotGetV2SpotMarketTickers(self.extend(request, params))
3118
3238
  else:
3119
- productType = None
3120
- productType, params = self.handle_product_type_and_params(market, params)
3121
3239
  request['productType'] = productType
3122
3240
  response = self.publicMixGetV2MixMarketTicker(self.extend(request, params))
3123
3241
  #
@@ -3151,34 +3269,94 @@ class bitget(Exchange, ImplicitAPI):
3151
3269
  #
3152
3270
  # swap and future
3153
3271
  #
3154
- # {
3272
+ # {
3155
3273
  # "code": "00000",
3156
3274
  # "msg": "success",
3157
- # "requestTime": 1700533070357,
3275
+ # "requestTime": 1750332210369,
3158
3276
  # "data": [
3159
3277
  # {
3160
3278
  # "symbol": "BTCUSDT",
3161
- # "lastPr": "37577.2",
3162
- # "askPr": "37577.3",
3163
- # "bidPr": "37577.2",
3164
- # "bidSz": "3.679",
3165
- # "askSz": "0.02",
3166
- # "high24h": "37765",
3167
- # "low24h": "36628.9",
3168
- # "ts": "1700533070359",
3169
- # "change24h": "0.00288",
3170
- # "baseVolume": "108606.181",
3171
- # "quoteVolume": "4051316303.9608",
3172
- # "usdtVolume": "4051316303.9608",
3173
- # "openUtc": "37451.5",
3174
- # "changeUtc24h": "0.00336",
3175
- # "indexPrice": "37574.489253",
3176
- # "fundingRate": "0.0001",
3177
- # "holdingAmount": "53464.529",
3279
+ # "lastPr": "104823.8",
3280
+ # "askPr": "104823.8",
3281
+ # "bidPr": "104823.5",
3282
+ # "bidSz": "0.703",
3283
+ # "askSz": "13.894",
3284
+ # "high24h": "105289.3",
3285
+ # "low24h": "103447.9",
3286
+ # "ts": "1750332210370",
3287
+ # "change24h": "0.00471",
3288
+ # "baseVolume": "79089.5675",
3289
+ # "quoteVolume": "8274870921.80485",
3290
+ # "usdtVolume": "8274870921.80485",
3291
+ # "openUtc": "104833",
3292
+ # "changeUtc24h": "-0.00009",
3293
+ # "indexPrice": "104881.953125",
3294
+ # "fundingRate": "-0.000014",
3295
+ # "holdingAmount": "7452.6421",
3178
3296
  # "deliveryStartTime": null,
3179
3297
  # "deliveryTime": null,
3180
3298
  # "deliveryStatus": "",
3181
- # "open24h": "37235.7"
3299
+ # "open24h": "104332.3",
3300
+ # "markPrice": "104824.2"
3301
+ # }
3302
+ # ]
3303
+ # }
3304
+ #
3305
+ # spot uta
3306
+ #
3307
+ # {
3308
+ # "code": "00000",
3309
+ # "msg": "success",
3310
+ # "requestTime": 1750330653575,
3311
+ # "data": [
3312
+ # {
3313
+ # "category": "SPOT",
3314
+ # "symbol": "BTCUSDT",
3315
+ # "ts": "1750330651972",
3316
+ # "lastPrice": "104900.2",
3317
+ # "openPrice24h": "104321.2",
3318
+ # "highPrice24h": "107956.8",
3319
+ # "lowPrice24h": "103600.1",
3320
+ # "ask1Price": "104945.8",
3321
+ # "bid1Price": "104880.6",
3322
+ # "bid1Size": "0.266534",
3323
+ # "ask1Size": "0.014001",
3324
+ # "price24hPcnt": "0.00555",
3325
+ # "volume24h": "355.941109",
3326
+ # "turnover24h": "37302936.008134"
3327
+ # }
3328
+ # ]
3329
+ # }
3330
+ #
3331
+ # swap and future uta
3332
+ #
3333
+ # {
3334
+ # "code": "00000",
3335
+ # "msg": "success",
3336
+ # "requestTime": 1750332731203,
3337
+ # "data": [
3338
+ # {
3339
+ # "category": "USDT-FUTURES",
3340
+ # "symbol": "BTCUSDT",
3341
+ # "ts": "1750332730472",
3342
+ # "lastPrice": "104738",
3343
+ # "openPrice24h": "104374",
3344
+ # "highPrice24h": "105289.3",
3345
+ # "lowPrice24h": "103447.9",
3346
+ # "ask1Price": "104738",
3347
+ # "bid1Price": "104737.7",
3348
+ # "bid1Size": "2.036",
3349
+ # "ask1Size": "8.094",
3350
+ # "price24hPcnt": "0.00349",
3351
+ # "volume24h": "79101.6477",
3352
+ # "turnover24h": "8276293391.45973",
3353
+ # "indexPrice": "104785.956168",
3354
+ # "markPrice": "104738",
3355
+ # "fundingRate": "-0.000007",
3356
+ # "openInterest": "7465.5938",
3357
+ # "deliveryStartTime": "",
3358
+ # "deliveryTime": "",
3359
+ # "deliveryStatus": ""
3182
3360
  # }
3183
3361
  # ]
3184
3362
  # }
@@ -3218,9 +3396,11 @@ class bitget(Exchange, ImplicitAPI):
3218
3396
 
3219
3397
  https://www.bitget.com/api-doc/spot/market/Get-Tickers
3220
3398
  https://www.bitget.com/api-doc/contract/market/Get-All-Symbol-Ticker
3399
+ https://www.bitget.com/api-doc/uta/public/Tickers
3221
3400
 
3222
3401
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
3223
3402
  :param dict [params]: extra parameters specific to the exchange API endpoint
3403
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3224
3404
  :param str [params.subType]: *contract only* 'linear', 'inverse'
3225
3405
  :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
3226
3406
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -3241,7 +3421,15 @@ class bitget(Exchange, ImplicitAPI):
3241
3421
  productType = None
3242
3422
  productType, params = self.handle_product_type_and_params(market, params)
3243
3423
  # only if passedSubType and productType is None, then use spot
3244
- if type == 'spot' and passedSubType is None:
3424
+ uta = None
3425
+ uta, params = self.handle_option_and_params(params, 'fetchTickers', 'uta', False)
3426
+ if uta:
3427
+ symbolsLength = len(symbols)
3428
+ if (symbols is not None) and (symbolsLength == 1):
3429
+ request['symbol'] = market['id']
3430
+ request['category'] = productType
3431
+ response = self.publicUtaGetV3MarketTickers(self.extend(request, params))
3432
+ elif type == 'spot' and passedSubType is None:
3245
3433
  response = self.publicSpotGetV2SpotMarketTickers(self.extend(request, params))
3246
3434
  else:
3247
3435
  request['productType'] = productType
@@ -3303,6 +3491,65 @@ class bitget(Exchange, ImplicitAPI):
3303
3491
  # ]
3304
3492
  # }
3305
3493
  #
3494
+ # spot uta
3495
+ #
3496
+ # {
3497
+ # "code": "00000",
3498
+ # "msg": "success",
3499
+ # "requestTime": 1750330653575,
3500
+ # "data": [
3501
+ # {
3502
+ # "category": "SPOT",
3503
+ # "symbol": "BTCUSDT",
3504
+ # "ts": "1750330651972",
3505
+ # "lastPrice": "104900.2",
3506
+ # "openPrice24h": "104321.2",
3507
+ # "highPrice24h": "107956.8",
3508
+ # "lowPrice24h": "103600.1",
3509
+ # "ask1Price": "104945.8",
3510
+ # "bid1Price": "104880.6",
3511
+ # "bid1Size": "0.266534",
3512
+ # "ask1Size": "0.014001",
3513
+ # "price24hPcnt": "0.00555",
3514
+ # "volume24h": "355.941109",
3515
+ # "turnover24h": "37302936.008134"
3516
+ # }
3517
+ # ]
3518
+ # }
3519
+ #
3520
+ # swap and future uta
3521
+ #
3522
+ # {
3523
+ # "code": "00000",
3524
+ # "msg": "success",
3525
+ # "requestTime": 1750332731203,
3526
+ # "data": [
3527
+ # {
3528
+ # "category": "USDT-FUTURES",
3529
+ # "symbol": "BTCUSDT",
3530
+ # "ts": "1750332730472",
3531
+ # "lastPrice": "104738",
3532
+ # "openPrice24h": "104374",
3533
+ # "highPrice24h": "105289.3",
3534
+ # "lowPrice24h": "103447.9",
3535
+ # "ask1Price": "104738",
3536
+ # "bid1Price": "104737.7",
3537
+ # "bid1Size": "2.036",
3538
+ # "ask1Size": "8.094",
3539
+ # "price24hPcnt": "0.00349",
3540
+ # "volume24h": "79101.6477",
3541
+ # "turnover24h": "8276293391.45973",
3542
+ # "indexPrice": "104785.956168",
3543
+ # "markPrice": "104738",
3544
+ # "fundingRate": "-0.000007",
3545
+ # "openInterest": "7465.5938",
3546
+ # "deliveryStartTime": "",
3547
+ # "deliveryTime": "",
3548
+ # "deliveryStatus": ""
3549
+ # }
3550
+ # ]
3551
+ # }
3552
+ #
3306
3553
  data = self.safe_list(response, 'data', [])
3307
3554
  return self.parse_tickers(data, symbols)
3308
3555
 
@@ -3389,19 +3636,53 @@ class bitget(Exchange, ImplicitAPI):
3389
3636
  # "cTime": "1700720700342"
3390
3637
  # }
3391
3638
  #
3639
+ # uta fetchTrades
3640
+ #
3641
+ # {
3642
+ # "execId": "1319896716324937729",
3643
+ # "price": "105909.1",
3644
+ # "size": "6.3090",
3645
+ # "side": "sell",
3646
+ # "ts": "1750413820344"
3647
+ # }
3648
+ #
3649
+ # uta fetchMyTrades
3650
+ #
3651
+ # {
3652
+ # "execId": "1322441401010528257",
3653
+ # "orderId": "1322441400976261120",
3654
+ # "category": "USDT-FUTURES",
3655
+ # "symbol": "BTCUSDT",
3656
+ # "orderType": "market",
3657
+ # "side": "sell",
3658
+ # "execPrice": "107005.4",
3659
+ # "execQty": "0.0001",
3660
+ # "execValue": "10.7005",
3661
+ # "tradeScope": "taker",
3662
+ # "feeDetail": [{
3663
+ # "feeCoin": "USDT",
3664
+ # "fee":"0.00642032"
3665
+ # }],
3666
+ # "createdTime": "1751020520451",
3667
+ # "updatedTime": "1751020520458",
3668
+ # "execPnl": "0.00017"
3669
+ # }
3670
+ #
3392
3671
  marketId = self.safe_string(trade, 'symbol')
3393
3672
  symbol = self.safe_symbol(marketId, market)
3394
- timestamp = self.safe_integer_2(trade, 'cTime', 'ts')
3673
+ timestamp = self.safe_integer_n(trade, ['cTime', 'ts', 'createdTime'])
3395
3674
  fee = None
3396
3675
  feeDetail = self.safe_value(trade, 'feeDetail')
3397
3676
  posMode = self.safe_string(trade, 'posMode')
3398
- feeStructure = feeDetail[0] if (posMode is not None) else feeDetail
3677
+ category = self.safe_string(trade, 'category')
3678
+ isFeeStructure = (posMode is not None) or (category is not None)
3679
+ feeStructure = feeDetail[0] if isFeeStructure else feeDetail
3399
3680
  if feeStructure is not None:
3400
3681
  currencyCode = self.safe_currency_code(self.safe_string(feeStructure, 'feeCoin'))
3401
3682
  fee = {
3402
3683
  'currency': currencyCode,
3403
3684
  }
3404
- feeCostString = self.safe_string(feeStructure, 'totalFee')
3685
+ feeCostString = self.safe_string_2(feeStructure, 'totalFee', 'fee')
3405
3686
  deduction = self.safe_string(feeStructure, 'deduction') is True if 'yes' else False
3406
3687
  if deduction:
3407
3688
  fee['cost'] = feeCostString
@@ -3409,15 +3690,15 @@ class bitget(Exchange, ImplicitAPI):
3409
3690
  fee['cost'] = Precise.string_neg(feeCostString)
3410
3691
  return self.safe_trade({
3411
3692
  'info': trade,
3412
- 'id': self.safe_string(trade, 'tradeId'),
3693
+ 'id': self.safe_string_2(trade, 'tradeId', 'execId'),
3413
3694
  'order': self.safe_string(trade, 'orderId'),
3414
3695
  'symbol': symbol,
3415
3696
  'side': self.safe_string_lower(trade, 'side'),
3416
3697
  'type': self.safe_string(trade, 'orderType'),
3417
3698
  'takerOrMaker': self.safe_string(trade, 'tradeScope'),
3418
- 'price': self.safe_string_2(trade, 'priceAvg', 'price'),
3419
- 'amount': self.safe_string_2(trade, 'baseVolume', 'size'),
3420
- 'cost': self.safe_string_2(trade, 'quoteVolume', 'amount'),
3699
+ 'price': self.safe_string_n(trade, ['priceAvg', 'price', 'execPrice']),
3700
+ 'amount': self.safe_string_n(trade, ['baseVolume', 'size', 'execQty']),
3701
+ 'cost': self.safe_string_n(trade, ['quoteVolume', 'amount', 'execValue']),
3421
3702
  'timestamp': timestamp,
3422
3703
  'datetime': self.iso8601(timestamp),
3423
3704
  'fee': fee,
@@ -3431,11 +3712,13 @@ class bitget(Exchange, ImplicitAPI):
3431
3712
  https://www.bitget.com/api-doc/spot/market/Get-Market-Trades
3432
3713
  https://www.bitget.com/api-doc/contract/market/Get-Recent-Fills
3433
3714
  https://www.bitget.com/api-doc/contract/market/Get-Fills-History
3715
+ https://www.bitget.com/api-doc/uta/public/Fills
3434
3716
 
3435
3717
  :param str symbol: unified symbol of the market to fetch trades for
3436
3718
  :param int [since]: timestamp in ms of the earliest trade to fetch
3437
3719
  :param int [limit]: the maximum amount of trades to fetch
3438
3720
  :param dict [params]: extra parameters specific to the exchange API endpoint
3721
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3439
3722
  :param int [params.until]: *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* the latest time in ms to fetch trades for
3440
3723
  :param boolean [params.paginate]: *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* default False, when True will automatically paginate by calling self endpoint multiple times
3441
3724
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
@@ -3449,14 +3732,28 @@ class bitget(Exchange, ImplicitAPI):
3449
3732
  request: dict = {
3450
3733
  'symbol': market['id'],
3451
3734
  }
3735
+ uta = None
3736
+ uta, params = self.handle_option_and_params(params, 'fetchTrades', 'uta', False)
3452
3737
  if limit is not None:
3453
- if market['contract']:
3738
+ if uta:
3739
+ request['limit'] = min(limit, 100)
3740
+ elif market['contract']:
3454
3741
  request['limit'] = min(limit, 1000)
3455
3742
  else:
3456
3743
  request['limit'] = limit
3457
3744
  options = self.safe_value(self.options, 'fetchTrades', {})
3458
3745
  response = None
3459
- if market['spot']:
3746
+ productType = None
3747
+ productType, params = self.handle_product_type_and_params(market, params)
3748
+ if uta:
3749
+ if productType == 'SPOT':
3750
+ marginMode = None
3751
+ marginMode, params = self.handle_margin_mode_and_params('fetchTrades', params)
3752
+ if marginMode is not None:
3753
+ productType = 'MARGIN'
3754
+ request['category'] = productType
3755
+ response = self.publicUtaGetV3MarketFills(self.extend(request, params))
3756
+ elif market['spot']:
3460
3757
  spotOptions = self.safe_value(options, 'spot', {})
3461
3758
  defaultSpotMethod = self.safe_string(spotOptions, 'method', 'publicSpotGetV2SpotMarketFillsHistory')
3462
3759
  spotMethod = self.safe_string(params, 'method', defaultSpotMethod)
@@ -3473,8 +3770,6 @@ class bitget(Exchange, ImplicitAPI):
3473
3770
  defaultSwapMethod = self.safe_string(swapOptions, 'method', 'publicMixGetV2MixMarketFillsHistory')
3474
3771
  swapMethod = self.safe_string(params, 'method', defaultSwapMethod)
3475
3772
  params = self.omit(params, 'method')
3476
- productType = None
3477
- productType, params = self.handle_product_type_and_params(market, params)
3478
3773
  request['productType'] = productType
3479
3774
  if swapMethod == 'publicMixGetV2MixMarketFillsHistory':
3480
3775
  request, params = self.handle_until_option('endTime', request, params)
@@ -3520,6 +3815,23 @@ class bitget(Exchange, ImplicitAPI):
3520
3815
  # ]
3521
3816
  # }
3522
3817
  #
3818
+ # uta
3819
+ #
3820
+ # {
3821
+ # "code": "00000",
3822
+ # "msg": "success",
3823
+ # "requestTime": 1750413823980,
3824
+ # "data": [
3825
+ # {
3826
+ # "execId": "1319896716324937729",
3827
+ # "price": "105909.1",
3828
+ # "size": "6.3090",
3829
+ # "side": "sell",
3830
+ # "ts": "1750413820344"
3831
+ # }
3832
+ # ]
3833
+ # }
3834
+ #
3523
3835
  data = self.safe_list(response, 'data', [])
3524
3836
  return self.parse_trades(data, market, since, limit)
3525
3837
 
@@ -3701,13 +4013,15 @@ class bitget(Exchange, ImplicitAPI):
3701
4013
  # "1399132.341"
3702
4014
  # ]
3703
4015
  #
4016
+ inverse = self.safe_bool(market, 'inverse')
4017
+ volumeIndex = 6 if inverse else 5
3704
4018
  return [
3705
4019
  self.safe_integer(ohlcv, 0),
3706
4020
  self.safe_number(ohlcv, 1),
3707
4021
  self.safe_number(ohlcv, 2),
3708
4022
  self.safe_number(ohlcv, 3),
3709
4023
  self.safe_number(ohlcv, 4),
3710
- self.safe_number(ohlcv, 5),
4024
+ self.safe_number(ohlcv, volumeIndex),
3711
4025
  ]
3712
4026
 
3713
4027
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
@@ -3720,12 +4034,14 @@ class bitget(Exchange, ImplicitAPI):
3720
4034
  https://www.bitget.com/api-doc/contract/market/Get-History-Candle-Data
3721
4035
  https://www.bitget.com/api-doc/contract/market/Get-History-Index-Candle-Data
3722
4036
  https://www.bitget.com/api-doc/contract/market/Get-History-Mark-Candle-Data
4037
+ https://www.bitget.com/api-doc/uta/public/Get-Candle-Data
3723
4038
 
3724
4039
  :param str symbol: unified symbol of the market to fetch OHLCV data for
3725
4040
  :param str timeframe: the length of time each candle represents
3726
4041
  :param int [since]: timestamp in ms of the earliest candle to fetch
3727
4042
  :param int [limit]: the maximum amount of candles to fetch
3728
4043
  :param dict [params]: extra parameters specific to the exchange API endpoint
4044
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
3729
4045
  :param int [params.until]: timestamp in ms of the latest candle to fetch
3730
4046
  :param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
3731
4047
  :param boolean [params.useHistoryEndpointForPagination]: whether to force to use historical endpoint for pagination(default True)
@@ -3745,12 +4061,20 @@ class bitget(Exchange, ImplicitAPI):
3745
4061
  limitForPagination = maxLimitForHistoryEndpoint if useHistoryEndpointForPagination else maxLimitForRecentEndpoint
3746
4062
  return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, limitForPagination)
3747
4063
  market = self.market(symbol)
3748
- marketType = 'spot' if market['spot'] else 'swap'
3749
- timeframes = self.options['timeframes'][marketType]
3750
4064
  request: dict = {
3751
4065
  'symbol': market['id'],
3752
- 'granularity': self.safe_string(timeframes, timeframe, timeframe),
3753
4066
  }
4067
+ marketType = None
4068
+ timeframes = None
4069
+ uta = None
4070
+ uta, params = self.handle_option_and_params(params, 'fetchOHLCV', 'uta', False)
4071
+ if uta:
4072
+ timeframes = self.options['timeframes']['uta']
4073
+ request['interval'] = self.safe_string(timeframes, timeframe, timeframe)
4074
+ else:
4075
+ marketType = 'spot' if market['spot'] else 'swap'
4076
+ timeframes = self.options['timeframes'][marketType]
4077
+ request['granularity'] = self.safe_string(timeframes, timeframe, timeframe)
3754
4078
  msInDay = 86400000
3755
4079
  now = self.milliseconds()
3756
4080
  duration = self.parse_timeframe(timeframe) * 1000
@@ -3811,7 +4135,19 @@ class bitget(Exchange, ImplicitAPI):
3811
4135
  request['limit'] = limit
3812
4136
  # make request
3813
4137
  response = None
3814
- if market['spot']:
4138
+ productType = None
4139
+ priceType = None
4140
+ priceType, params = self.handle_param_string(params, 'price')
4141
+ productType, params = self.handle_product_type_and_params(market, params)
4142
+ if uta:
4143
+ if priceType is not None:
4144
+ if priceType == 'mark':
4145
+ request['type'] = 'MARK'
4146
+ elif priceType == 'index':
4147
+ request['type'] = 'INDEX'
4148
+ request['category'] = productType
4149
+ response = self.publicUtaGetV3MarketCandles(self.extend(request, params))
4150
+ elif market['spot']:
3815
4151
  # checks if we need history endpoint
3816
4152
  if historicalEndpointNeeded:
3817
4153
  response = self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
@@ -3821,10 +4157,6 @@ class bitget(Exchange, ImplicitAPI):
3821
4157
  limit = 1000
3822
4158
  response = self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3823
4159
  else:
3824
- priceType = None
3825
- priceType, params = self.handle_param_string(params, 'price')
3826
- productType = None
3827
- productType, params = self.handle_product_type_and_params(market, params)
3828
4160
  request['productType'] = productType
3829
4161
  extended = self.extend(request, params)
3830
4162
  if not historicalEndpointNeeded and (priceType == 'mark' or priceType == 'index'):
@@ -3862,9 +4194,11 @@ class bitget(Exchange, ImplicitAPI):
3862
4194
  https://www.bitget.com/api-doc/margin/isolated/account/Get-Isolated-Assets
3863
4195
  https://bitgetlimited.github.io/apidoc/en/margin/#get-cross-assets
3864
4196
  https://bitgetlimited.github.io/apidoc/en/margin/#get-isolated-assets
4197
+ https://www.bitget.com/api-doc/uta/account/Get-Account
3865
4198
 
3866
4199
  :param dict [params]: extra parameters specific to the exchange API endpoint
3867
4200
  :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
4201
+ :param str [params.uta]: set to True for the unified trading account(uta), defaults to False
3868
4202
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
3869
4203
  """
3870
4204
  self.load_markets()
@@ -3872,9 +4206,16 @@ class bitget(Exchange, ImplicitAPI):
3872
4206
  marketType = None
3873
4207
  marginMode = None
3874
4208
  response = None
4209
+ uta = None
4210
+ uta, params = self.handle_option_and_params(params, 'fetchBalance', 'uta', False)
3875
4211
  marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
3876
4212
  marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
3877
- if (marketType == 'swap') or (marketType == 'future'):
4213
+ if uta:
4214
+ response = self.privateUtaGetV3AccountAssets(self.extend(request, params))
4215
+ results = self.safe_dict(response, 'data', {})
4216
+ assets = self.safe_list(results, 'assets', [])
4217
+ return self.parse_uta_balance(assets)
4218
+ elif (marketType == 'swap') or (marketType == 'future'):
3878
4219
  productType = None
3879
4220
  productType, params = self.handle_product_type_and_params(None, params)
3880
4221
  request['productType'] = productType
@@ -3974,9 +4315,66 @@ class bitget(Exchange, ImplicitAPI):
3974
4315
  # ]
3975
4316
  # }
3976
4317
  #
4318
+ # uta
4319
+ #
4320
+ # {
4321
+ # "code": "00000",
4322
+ # "msg": "success",
4323
+ # "requestTime": 1749980065089,
4324
+ # "data": {
4325
+ # "accountEquity": "11.13919278",
4326
+ # "usdtEquity": "11.13921165",
4327
+ # "btcEquity": "0.00011256",
4328
+ # "unrealisedPnl": "0",
4329
+ # "usdtUnrealisedPnl": "0",
4330
+ # "btcUnrealizedPnl": "0",
4331
+ # "effEquity": "6.19299777",
4332
+ # "mmr": "0",
4333
+ # "imr": "0",
4334
+ # "mgnRatio": "0",
4335
+ # "positionMgnRatio": "0",
4336
+ # "assets": [
4337
+ # {
4338
+ # "coin": "USDT",
4339
+ # "equity": "6.19300826",
4340
+ # "usdValue": "6.19299777",
4341
+ # "balance": "6.19300826",
4342
+ # "available": "6.19300826",
4343
+ # "debt": "0",
4344
+ # "locked": "0"
4345
+ # }
4346
+ # ]
4347
+ # }
4348
+ # }
4349
+ #
3977
4350
  data = self.safe_value(response, 'data', [])
3978
4351
  return self.parse_balance(data)
3979
4352
 
4353
+ def parse_uta_balance(self, balance) -> Balances:
4354
+ result: dict = {'info': balance}
4355
+ #
4356
+ # {
4357
+ # "coin": "USDT",
4358
+ # "equity": "6.19300826",
4359
+ # "usdValue": "6.19299777",
4360
+ # "balance": "6.19300826",
4361
+ # "available": "6.19300826",
4362
+ # "debt": "0",
4363
+ # "locked": "0"
4364
+ # }
4365
+ #
4366
+ for i in range(0, len(balance)):
4367
+ entry = balance[i]
4368
+ account = self.account()
4369
+ currencyId = self.safe_string(entry, 'coin')
4370
+ code = self.safe_currency_code(currencyId)
4371
+ account['debt'] = self.safe_string(entry, 'debt')
4372
+ account['used'] = self.safe_string(entry, 'locked')
4373
+ account['free'] = self.safe_string(entry, 'available')
4374
+ account['total'] = self.safe_string(entry, 'balance')
4375
+ result[code] = account
4376
+ return self.safe_balance(result)
4377
+
3980
4378
  def parse_balance(self, balance) -> Balances:
3981
4379
  result: dict = {'info': balance}
3982
4380
  #
@@ -4110,7 +4508,7 @@ class bitget(Exchange, ImplicitAPI):
4110
4508
  # },
4111
4509
  # ]
4112
4510
  #
4113
- # spot, swap, future and spot margin: cancelOrder, cancelOrders
4511
+ # spot, swap, future, spot margin and uta: cancelOrder, cancelOrders, cancelAllOrders
4114
4512
  #
4115
4513
  # {
4116
4514
  # "orderId": "1098758604547850241",
@@ -4239,6 +4637,66 @@ class bitget(Exchange, ImplicitAPI):
4239
4637
  # "stopLossTriggerType": "fill_price",
4240
4638
  # }
4241
4639
  #
4640
+ # uta: fetchOrder, fetchOpenOrders, fetchCanceledAndClosedOrders
4641
+ #
4642
+ # {
4643
+ # "orderId": "1320244799629316096",
4644
+ # "clientOid": "1320244799633510400",
4645
+ # "category": "USDT-FUTURES",
4646
+ # "symbol": "BTCUSDT",
4647
+ # "orderType": "limit",
4648
+ # "side": "buy",
4649
+ # "price": "50000",
4650
+ # "qty": "0.001",
4651
+ # "amount": "0",
4652
+ # "cumExecQty": "0",
4653
+ # "cumExecValue": "0",
4654
+ # "avgPrice": "0",
4655
+ # "timeInForce": "gtc",
4656
+ # "orderStatus": "live",
4657
+ # "posSide": "long",
4658
+ # "holdMode": "hedge_mode",
4659
+ # "reduceOnly": "NO",
4660
+ # "feeDetail": [{
4661
+ # "feeCoin": "",
4662
+ # "fee": ""
4663
+ # }],
4664
+ # "createdTime": "1750496809871",
4665
+ # "updatedTime": "1750496809886",
4666
+ # "cancelReason": "",
4667
+ # "execType": "normal",
4668
+ # "stpMode": "none",
4669
+ # "tpTriggerBy": null,
4670
+ # "slTriggerBy": null,
4671
+ # "takeProfit": null,
4672
+ # "stopLoss": null,
4673
+ # "tpOrderType": null,
4674
+ # "slOrderType": null,
4675
+ # "tpLimitPrice": null,
4676
+ # "slLimitPrice": null
4677
+ # }
4678
+ #
4679
+ # uta trigger: fetchClosedOrders, fetchCanceledOrders
4680
+ #
4681
+ # {
4682
+ # "orderId": "1330984742276198400",
4683
+ # "clientOid": "1330984742276198400",
4684
+ # "symbol": "BTCUSDT",
4685
+ # "category": "USDT-FUTURES",
4686
+ # "qty": "0.001",
4687
+ # "posSide": "long",
4688
+ # "tpTriggerBy": "market",
4689
+ # "slTriggerBy": "mark",
4690
+ # "takeProfit": "",
4691
+ # "stopLoss": "112000",
4692
+ # "tpOrderType": "market",
4693
+ # "slOrderType": "limit",
4694
+ # "tpLimitPrice": "",
4695
+ # "slLimitPrice": "111000",
4696
+ # "createdTime": "1753057411736",
4697
+ # "updatedTime": "1753058267412"
4698
+ # }
4699
+ #
4242
4700
  errorMessage = self.safe_string(order, 'errorMsg')
4243
4701
  if errorMessage is not None:
4244
4702
  return self.safe_order({
@@ -4247,16 +4705,16 @@ class bitget(Exchange, ImplicitAPI):
4247
4705
  'clientOrderId': self.safe_string_2(order, 'clientOrderId', 'clientOid'),
4248
4706
  'status': 'rejected',
4249
4707
  }, market)
4250
- isContractOrder = ('posSide' in order)
4708
+ posSide = self.safe_string(order, 'posSide')
4709
+ isContractOrder = (posSide is not None)
4251
4710
  marketType = 'contract' if isContractOrder else 'spot'
4252
4711
  if market is not None:
4253
4712
  marketType = market['type']
4254
4713
  marketId = self.safe_string(order, 'symbol')
4255
4714
  market = self.safe_market(marketId, market, None, marketType)
4256
- timestamp = self.safe_integer_2(order, 'cTime', 'ctime')
4257
- updateTimestamp = self.safe_integer(order, 'uTime')
4258
- rawStatus = self.safe_string_2(order, 'status', 'state')
4259
- rawStatus = self.safe_string(order, 'planStatus', rawStatus)
4715
+ timestamp = self.safe_integer_n(order, ['cTime', 'ctime', 'createdTime'])
4716
+ updateTimestamp = self.safe_integer_2(order, 'uTime', 'updatedTime')
4717
+ rawStatus = self.safe_string_n(order, ['status', 'state', 'orderStatus', 'planStatus'])
4260
4718
  fee = None
4261
4719
  feeCostString = self.safe_string(order, 'fee')
4262
4720
  if feeCostString is not None:
@@ -4266,21 +4724,30 @@ class bitget(Exchange, ImplicitAPI):
4266
4724
  'currency': market['settle'],
4267
4725
  }
4268
4726
  feeDetail = self.safe_value(order, 'feeDetail')
4269
- if feeDetail is not None:
4270
- parsedFeeDetail = json.loads(feeDetail)
4271
- feeValues = list(parsedFeeDetail.values())
4272
- feeObject = None
4273
- for i in range(0, len(feeValues)):
4274
- feeValue = feeValues[i]
4275
- if self.safe_value(feeValue, 'feeCoinCode') is not None:
4276
- feeObject = feeValue
4277
- break
4727
+ uta = self.safe_string(order, 'category') is not None
4728
+ if uta:
4729
+ feeResult = self.safe_dict(feeDetail, 0, {})
4730
+ utaFee = self.safe_string(feeResult, 'fee')
4278
4731
  fee = {
4279
- 'cost': self.parse_number(Precise.string_neg(self.safe_string(feeObject, 'totalFee'))),
4280
- 'currency': self.safe_currency_code(self.safe_string(feeObject, 'feeCoinCode')),
4732
+ 'cost': self.parse_number(Precise.string_neg(utaFee)),
4733
+ 'currency': market['settle'],
4281
4734
  }
4735
+ else:
4736
+ if feeDetail is not None:
4737
+ parsedFeeDetail = json.loads(feeDetail)
4738
+ feeValues = list(parsedFeeDetail.values())
4739
+ feeObject = None
4740
+ for i in range(0, len(feeValues)):
4741
+ feeValue = feeValues[i]
4742
+ if self.safe_value(feeValue, 'feeCoinCode') is not None:
4743
+ feeObject = feeValue
4744
+ break
4745
+ fee = {
4746
+ 'cost': self.parse_number(Precise.string_neg(self.safe_string(feeObject, 'totalFee'))),
4747
+ 'currency': self.safe_currency_code(self.safe_string(feeObject, 'feeCoinCode')),
4748
+ }
4282
4749
  postOnly = None
4283
- timeInForce = self.safe_string_upper(order, 'force')
4750
+ timeInForce = self.safe_string_upper_2(order, 'force', 'timeInForce')
4284
4751
  if timeInForce == 'POST_ONLY':
4285
4752
  postOnly = True
4286
4753
  timeInForce = 'PO'
@@ -4296,7 +4763,7 @@ class bitget(Exchange, ImplicitAPI):
4296
4763
  price = self.safe_string(order, 'priceAvg')
4297
4764
  average = self.safe_string(order, 'basePrice')
4298
4765
  else:
4299
- price = self.safe_string_2(order, 'price', 'executePrice')
4766
+ price = self.safe_string_n(order, ['price', 'executePrice', 'slLimitPrice', 'tpLimitPrice'])
4300
4767
  average = self.safe_string(order, 'priceAvg')
4301
4768
  size = None
4302
4769
  filled = None
@@ -4306,8 +4773,8 @@ class bitget(Exchange, ImplicitAPI):
4306
4773
  size = baseSize
4307
4774
  filled = self.safe_string(order, 'size')
4308
4775
  else:
4309
- size = self.safe_string(order, 'size')
4310
- filled = self.safe_string(order, 'baseVolume')
4776
+ size = self.safe_string_2(order, 'size', 'qty')
4777
+ filled = self.safe_string_2(order, 'baseVolume', 'cumExecQty')
4311
4778
  side = self.safe_string(order, 'side')
4312
4779
  posMode = self.safe_string(order, 'posMode')
4313
4780
  if posMode == 'hedge_mode' and reduceOnly:
@@ -4340,8 +4807,8 @@ class bitget(Exchange, ImplicitAPI):
4340
4807
  'postOnly': postOnly,
4341
4808
  'reduceOnly': reduceOnly,
4342
4809
  'triggerPrice': self.safe_number(order, 'triggerPrice'),
4343
- 'takeProfitPrice': self.safe_number_2(order, 'presetStopSurplusPrice', 'stopSurplusTriggerPrice'),
4344
- 'stopLossPrice': self.safe_number_2(order, 'presetStopLossPrice', 'stopLossTriggerPrice'),
4810
+ 'takeProfitPrice': self.safe_number_n(order, ['presetStopSurplusPrice', 'stopSurplusTriggerPrice', 'takeProfit']),
4811
+ 'stopLossPrice': self.safe_number_n(order, ['presetStopLossPrice', 'stopLossTriggerPrice', 'stopLoss']),
4345
4812
  'status': self.parse_order_status(rawStatus),
4346
4813
  'fee': fee,
4347
4814
  'trades': None,
@@ -4380,6 +4847,8 @@ class bitget(Exchange, ImplicitAPI):
4380
4847
  https://www.bitget.com/api-doc/contract/plan/Place-Plan-Order
4381
4848
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Place-Order
4382
4849
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
4850
+ https://www.bitget.com/api-doc/uta/trade/Place-Order
4851
+ https://www.bitget.com/api-doc/uta/strategy/Place-Strategy-Order
4383
4852
 
4384
4853
  :param str symbol: unified symbol of the market to create an order in
4385
4854
  :param str type: 'market' or 'limit'
@@ -4409,6 +4878,8 @@ class bitget(Exchange, ImplicitAPI):
4409
4878
  :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
4410
4879
  :param bool [params.hedged]: *swap and future only* True for hedged mode, False for one way mode, default is False
4411
4880
  :param bool [params.reduceOnly]: True or False whether the order is reduce-only
4881
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4882
+ :param str [params.posSide]: *uta only* hedged two-way position side, long or short
4412
4883
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4413
4884
  """
4414
4885
  self.load_markets()
@@ -4424,24 +4895,33 @@ class bitget(Exchange, ImplicitAPI):
4424
4895
  isStopLossTriggerOrder = stopLossTriggerPrice is not None
4425
4896
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
4426
4897
  isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
4427
- request = self.create_order_request(symbol, type, side, amount, price, params)
4428
4898
  response = None
4429
- if market['spot']:
4430
- if isTriggerOrder:
4431
- response = self.privateSpotPostV2SpotTradePlacePlanOrder(request)
4432
- elif marginMode == 'isolated':
4433
- response = self.privateMarginPostV2MarginIsolatedPlaceOrder(request)
4434
- elif marginMode == 'cross':
4435
- response = self.privateMarginPostV2MarginCrossedPlaceOrder(request)
4899
+ uta = None
4900
+ uta, params = self.handle_option_and_params(params, 'createOrder', 'uta', False)
4901
+ if uta:
4902
+ request = self.create_uta_order_request(symbol, type, side, amount, price, params)
4903
+ if isStopLossOrTakeProfitTrigger:
4904
+ response = self.privateUtaPostV3TradePlaceStrategyOrder(request)
4436
4905
  else:
4437
- response = self.privateSpotPostV2SpotTradePlaceOrder(request)
4906
+ response = self.privateUtaPostV3TradePlaceOrder(request)
4438
4907
  else:
4439
- if isTriggerOrder or isTrailingPercentOrder:
4440
- response = self.privateMixPostV2MixOrderPlacePlanOrder(request)
4441
- elif isStopLossOrTakeProfitTrigger:
4442
- response = self.privateMixPostV2MixOrderPlaceTpslOrder(request)
4908
+ request = self.create_order_request(symbol, type, side, amount, price, params)
4909
+ if market['spot']:
4910
+ if isTriggerOrder:
4911
+ response = self.privateSpotPostV2SpotTradePlacePlanOrder(request)
4912
+ elif marginMode == 'isolated':
4913
+ response = self.privateMarginPostV2MarginIsolatedPlaceOrder(request)
4914
+ elif marginMode == 'cross':
4915
+ response = self.privateMarginPostV2MarginCrossedPlaceOrder(request)
4916
+ else:
4917
+ response = self.privateSpotPostV2SpotTradePlaceOrder(request)
4443
4918
  else:
4444
- response = self.privateMixPostV2MixOrderPlaceOrder(request)
4919
+ if isTriggerOrder or isTrailingPercentOrder:
4920
+ response = self.privateMixPostV2MixOrderPlacePlanOrder(request)
4921
+ elif isStopLossOrTakeProfitTrigger:
4922
+ response = self.privateMixPostV2MixOrderPlaceTpslOrder(request)
4923
+ else:
4924
+ response = self.privateMixPostV2MixOrderPlaceOrder(request)
4445
4925
  #
4446
4926
  # {
4447
4927
  # "code": "00000",
@@ -4456,24 +4936,124 @@ class bitget(Exchange, ImplicitAPI):
4456
4936
  data = self.safe_dict(response, 'data', {})
4457
4937
  return self.parse_order(data, market)
4458
4938
 
4459
- def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
4939
+ def create_uta_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
4460
4940
  market = self.market(symbol)
4461
- marketType = None
4462
- marginMode = None
4463
- marketType, params = self.handle_market_type_and_params('createOrder', market, params)
4464
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
4941
+ productType = None
4942
+ productType, params = self.handle_product_type_and_params(market, params)
4943
+ if productType == 'SPOT':
4944
+ marginMode = None
4945
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
4946
+ if marginMode is not None:
4947
+ productType = 'MARGIN'
4465
4948
  request: dict = {
4949
+ 'category': productType,
4466
4950
  'symbol': market['id'],
4467
- 'orderType': type,
4951
+ 'qty': self.amount_to_precision(symbol, amount),
4952
+ 'side': side,
4468
4953
  }
4469
- isMarketOrder = type == 'market'
4470
- triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
4471
- stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
4472
- takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
4954
+ clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
4955
+ if clientOrderId is not None:
4956
+ request['clientOid'] = clientOrderId
4957
+ params = self.omit(params, 'clientOrderId')
4958
+ stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
4959
+ takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
4473
4960
  stopLoss = self.safe_value(params, 'stopLoss')
4474
4961
  takeProfit = self.safe_value(params, 'takeProfit')
4475
- isTriggerOrder = triggerPrice is not None
4476
- isStopLossTriggerOrder = stopLossTriggerPrice is not None
4962
+ isStopLoss = stopLoss is not None
4963
+ isTakeProfit = takeProfit is not None
4964
+ isStopLossTrigger = stopLossTriggerPrice is not None
4965
+ isTakeProfitTrigger = takeProfitTriggerPrice is not None
4966
+ isStopLossOrTakeProfitTrigger = isStopLossTrigger or isTakeProfitTrigger
4967
+ if isStopLossOrTakeProfitTrigger:
4968
+ if isStopLossTrigger:
4969
+ slType = self.safe_string(params, 'slTriggerBy', 'mark')
4970
+ request['slTriggerBy'] = slType
4971
+ request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
4972
+ if price is not None:
4973
+ request['slLimitPrice'] = self.price_to_precision(symbol, price)
4974
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
4975
+ else:
4976
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
4977
+ elif isTakeProfitTrigger:
4978
+ tpType = self.safe_string(params, 'tpTriggerBy', 'mark')
4979
+ request['tpTriggerBy'] = tpType
4980
+ request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
4981
+ if price is not None:
4982
+ request['tpLimitPrice'] = self.price_to_precision(symbol, price)
4983
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
4984
+ else:
4985
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
4986
+ params = self.omit(params, ['stopLossPrice', 'takeProfitPrice'])
4987
+ else:
4988
+ if isStopLoss:
4989
+ slTriggerPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'stopPrice')
4990
+ slLimitPrice = self.safe_number(stopLoss, 'price')
4991
+ request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
4992
+ if slLimitPrice is not None:
4993
+ request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
4994
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
4995
+ else:
4996
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
4997
+ if isTakeProfit:
4998
+ tpTriggerPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'stopPrice')
4999
+ tpLimitPrice = self.safe_number(takeProfit, 'price')
5000
+ request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
5001
+ if tpLimitPrice is not None:
5002
+ request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
5003
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
5004
+ else:
5005
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
5006
+ isMarketOrder = type == 'market'
5007
+ if not isMarketOrder:
5008
+ request['price'] = self.price_to_precision(symbol, price)
5009
+ request['orderType'] = type
5010
+ exchangeSpecificTifParam = self.safe_string(params, 'timeInForce')
5011
+ postOnly = None
5012
+ postOnly, params = self.handle_post_only(isMarketOrder, exchangeSpecificTifParam == 'post_only', params)
5013
+ defaultTimeInForce = self.safe_string_upper(self.options, 'defaultTimeInForce')
5014
+ timeInForce = self.safe_string_upper(params, 'timeInForce', defaultTimeInForce)
5015
+ if postOnly:
5016
+ request['timeInForce'] = 'post_only'
5017
+ elif timeInForce == 'GTC':
5018
+ request['timeInForce'] = 'gtc'
5019
+ elif timeInForce == 'FOK':
5020
+ request['timeInForce'] = 'fok'
5021
+ elif timeInForce == 'IOC':
5022
+ request['timeInForce'] = 'ioc'
5023
+ reduceOnly = self.safe_bool(params, 'reduceOnly', False)
5024
+ hedged = None
5025
+ hedged, params = self.handle_param_bool(params, 'hedged', False)
5026
+ if reduceOnly:
5027
+ if hedged or isStopLossOrTakeProfitTrigger:
5028
+ reduceOnlyPosSide = 'long' if (side == 'sell') else 'short'
5029
+ request['posSide'] = reduceOnlyPosSide
5030
+ elif not isStopLossOrTakeProfitTrigger:
5031
+ request['reduceOnly'] = 'yes'
5032
+ else:
5033
+ if hedged:
5034
+ posSide = 'long' if (side == 'buy') else 'short'
5035
+ request['posSide'] = posSide
5036
+ params = self.omit(params, ['stopLoss', 'takeProfit', 'postOnly', 'reduceOnly', 'hedged'])
5037
+ return self.extend(request, params)
5038
+
5039
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5040
+ market = self.market(symbol)
5041
+ marketType = None
5042
+ marginMode = None
5043
+ marketType, params = self.handle_market_type_and_params('createOrder', market, params)
5044
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
5045
+ request: dict = {
5046
+ 'symbol': market['id'],
5047
+ 'orderType': type,
5048
+ }
5049
+ isMarketOrder = type == 'market'
5050
+ triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
5051
+ stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
5052
+ takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
5053
+ stopLoss = self.safe_value(params, 'stopLoss')
5054
+ takeProfit = self.safe_value(params, 'takeProfit')
5055
+ isTriggerOrder = triggerPrice is not None
5056
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
4477
5057
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
4478
5058
  isStopLoss = stopLoss is not None
4479
5059
  isTakeProfit = takeProfit is not None
@@ -4527,16 +5107,16 @@ class bitget(Exchange, ImplicitAPI):
4527
5107
  if price is not None:
4528
5108
  request['executePrice'] = self.price_to_precision(symbol, price)
4529
5109
  if isStopLoss:
4530
- slTriggerPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'stopPrice')
5110
+ slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice')
4531
5111
  request['stopLossTriggerPrice'] = self.price_to_precision(symbol, slTriggerPrice)
4532
- slPrice = self.safe_number(stopLoss, 'price')
5112
+ slPrice = self.safe_string(stopLoss, 'price')
4533
5113
  request['stopLossExecutePrice'] = self.price_to_precision(symbol, slPrice)
4534
5114
  slType = self.safe_string(stopLoss, 'type', 'mark_price')
4535
5115
  request['stopLossTriggerType'] = slType
4536
5116
  if isTakeProfit:
4537
- tpTriggerPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'stopPrice')
5117
+ tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice')
4538
5118
  request['stopSurplusTriggerPrice'] = self.price_to_precision(symbol, tpTriggerPrice)
4539
- tpPrice = self.safe_number(takeProfit, 'price')
5119
+ tpPrice = self.safe_string(takeProfit, 'price')
4540
5120
  request['stopSurplusExecutePrice'] = self.price_to_precision(symbol, tpPrice)
4541
5121
  tpType = self.safe_string(takeProfit, 'type', 'mark_price')
4542
5122
  request['stopSurplusTriggerType'] = tpType
@@ -4629,6 +5209,52 @@ class bitget(Exchange, ImplicitAPI):
4629
5209
  raise NotSupported(self.id + ' createOrder() does not support ' + marketType + ' orders')
4630
5210
  return self.extend(request, params)
4631
5211
 
5212
+ def create_uta_orders(self, orders: List[OrderRequest], params={}):
5213
+ self.load_markets()
5214
+ ordersRequests = []
5215
+ symbol = None
5216
+ marginMode = None
5217
+ for i in range(0, len(orders)):
5218
+ rawOrder = orders[i]
5219
+ marketId = self.safe_string(rawOrder, 'symbol')
5220
+ if symbol is None:
5221
+ symbol = marketId
5222
+ else:
5223
+ if symbol != marketId:
5224
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
5225
+ type = self.safe_string(rawOrder, 'type')
5226
+ side = self.safe_string(rawOrder, 'side')
5227
+ amount = self.safe_value(rawOrder, 'amount')
5228
+ price = self.safe_value(rawOrder, 'price')
5229
+ orderParams = self.safe_value(rawOrder, 'params', {})
5230
+ marginResult = self.handle_margin_mode_and_params('createOrders', orderParams)
5231
+ currentMarginMode = marginResult[0]
5232
+ if currentMarginMode is not None:
5233
+ if marginMode is None:
5234
+ marginMode = currentMarginMode
5235
+ else:
5236
+ if marginMode != currentMarginMode:
5237
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same margin mode(isolated or cross)')
5238
+ orderRequest = self.create_uta_order_request(marketId, type, side, amount, price, orderParams)
5239
+ ordersRequests.append(orderRequest)
5240
+ market = self.market(symbol)
5241
+ response = self.privateUtaPostV3TradePlaceBatch(ordersRequests)
5242
+ #
5243
+ # {
5244
+ # "code": "00000",
5245
+ # "msg": "success",
5246
+ # "requestTime": 1752810184560,
5247
+ # "data": [
5248
+ # {
5249
+ # "orderId": "1329947796441513984",
5250
+ # "clientOid": "1329947796483457024"
5251
+ # },
5252
+ # ]
5253
+ # }
5254
+ #
5255
+ data = self.safe_list(response, 'data', [])
5256
+ return self.parse_orders(data, market)
5257
+
4632
5258
  def create_orders(self, orders: List[OrderRequest], params={}):
4633
5259
  """
4634
5260
  create a list of trade orders(all orders should be of the same symbol)
@@ -4637,12 +5263,18 @@ class bitget(Exchange, ImplicitAPI):
4637
5263
  https://www.bitget.com/api-doc/contract/trade/Batch-Order
4638
5264
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Order
4639
5265
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Order
5266
+ https://www.bitget.com/api-doc/uta/trade/Place-Batch
4640
5267
 
4641
5268
  :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
4642
5269
  :param dict [params]: extra parameters specific to the api endpoint
5270
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4643
5271
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4644
5272
  """
4645
5273
  self.load_markets()
5274
+ uta = None
5275
+ uta, params = self.handle_option_and_params(params, 'createOrders', 'uta', False)
5276
+ if uta:
5277
+ return self.create_uta_orders(orders, params)
4646
5278
  ordersRequests = []
4647
5279
  symbol = None
4648
5280
  marginMode = None
@@ -4728,6 +5360,8 @@ class bitget(Exchange, ImplicitAPI):
4728
5360
  https://www.bitget.com/api-doc/contract/trade/Modify-Order
4729
5361
  https://www.bitget.com/api-doc/contract/plan/Modify-Tpsl-Order
4730
5362
  https://www.bitget.com/api-doc/contract/plan/Modify-Plan-Order
5363
+ https://www.bitget.com/api-doc/uta/trade/Modify-Order
5364
+ https://www.bitget.com/api-doc/uta/strategy/Modify-Strategy-Order
4731
5365
 
4732
5366
  :param str id: cancel order id
4733
5367
  :param str symbol: unified symbol of the market to create an order in
@@ -4750,6 +5384,7 @@ class bitget(Exchange, ImplicitAPI):
4750
5384
  :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
4751
5385
  :param str [params.trailingTriggerPrice]: *swap and future only* the price to trigger a trailing stop order, default uses the price argument
4752
5386
  :param str [params.newTriggerType]: *swap and future only* 'fill_price', 'mark_price' or 'index_price'
5387
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4753
5388
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4754
5389
  """
4755
5390
  self.load_markets()
@@ -4778,7 +5413,39 @@ class bitget(Exchange, ImplicitAPI):
4778
5413
  request['clientOid'] = clientOrderId
4779
5414
  params = self.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent'])
4780
5415
  response = None
4781
- if market['spot']:
5416
+ productType = None
5417
+ uta = None
5418
+ productType, params = self.handle_product_type_and_params(market, params)
5419
+ uta, params = self.handle_option_and_params(params, 'editOrder', 'uta', False)
5420
+ if uta:
5421
+ if amount is not None:
5422
+ request['qty'] = self.amount_to_precision(symbol, amount)
5423
+ if isStopLossOrder or isTakeProfitOrder:
5424
+ if isStopLossOrder:
5425
+ slType = self.safe_string(params, 'slTriggerBy', 'mark')
5426
+ request['slTriggerBy'] = slType
5427
+ request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
5428
+ if price is not None:
5429
+ request['slLimitPrice'] = self.price_to_precision(symbol, price)
5430
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'limit')
5431
+ else:
5432
+ request['slOrderType'] = self.safe_string(params, 'slOrderType', 'market')
5433
+ elif isTakeProfitOrder:
5434
+ tpType = self.safe_string(params, 'tpTriggerBy', 'mark')
5435
+ request['tpTriggerBy'] = tpType
5436
+ request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
5437
+ if price is not None:
5438
+ request['tpLimitPrice'] = self.price_to_precision(symbol, price)
5439
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'limit')
5440
+ else:
5441
+ request['tpOrderType'] = self.safe_string(params, 'tpOrderType', 'market')
5442
+ params = self.omit(params, ['stopLossPrice', 'takeProfitPrice'])
5443
+ response = self.privateUtaPostV3TradeModifyStrategyOrder(self.extend(request, params))
5444
+ else:
5445
+ if price is not None:
5446
+ request['price'] = self.price_to_precision(symbol, price)
5447
+ response = self.privateUtaPostV3TradeModifyOrder(self.extend(request, params))
5448
+ elif market['spot']:
4782
5449
  if triggerPrice is None:
4783
5450
  raise NotSupported(self.id + ' editOrder() only supports plan/trigger spot orders')
4784
5451
  editMarketBuyOrderRequiresPrice = self.safe_bool(self.options, 'editMarketBuyOrderRequiresPrice', True)
@@ -4800,8 +5467,6 @@ class bitget(Exchange, ImplicitAPI):
4800
5467
  if (not market['swap']) and (not market['future']):
4801
5468
  raise NotSupported(self.id + ' editOrder() does not support ' + market['type'] + ' orders')
4802
5469
  request['symbol'] = market['id']
4803
- productType = None
4804
- productType, params = self.handle_product_type_and_params(market, params)
4805
5470
  request['productType'] = productType
4806
5471
  if not isTakeProfitOrder and not isStopLossOrder:
4807
5472
  request['newSize'] = self.amount_to_precision(symbol, amount)
@@ -4877,6 +5542,8 @@ class bitget(Exchange, ImplicitAPI):
4877
5542
  https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
4878
5543
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Cancel-Order
4879
5544
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Cancel-Order
5545
+ https://www.bitget.com/api-doc/uta/trade/Cancel-Order
5546
+ https://www.bitget.com/api-doc/uta/strategy/Cancel-Strategy-Order
4880
5547
 
4881
5548
  :param str id: order id
4882
5549
  :param str symbol: unified symbol of the market the order was made in
@@ -4885,6 +5552,7 @@ class bitget(Exchange, ImplicitAPI):
4885
5552
  :param boolean [params.trigger]: set to True for canceling trigger orders
4886
5553
  :param str [params.planType]: *swap only* either profit_plan, loss_plan, normal_plan, pos_profit, pos_loss, moving_plan or track_plan
4887
5554
  :param boolean [params.trailing]: set to True if you want to cancel a trailing order
5555
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
4888
5556
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4889
5557
  """
4890
5558
  if symbol is None:
@@ -4902,7 +5570,15 @@ class bitget(Exchange, ImplicitAPI):
4902
5570
  request['symbol'] = market['id']
4903
5571
  if not ((market['swap'] or market['future']) and trigger):
4904
5572
  request['orderId'] = id
4905
- if (market['swap']) or (market['future']):
5573
+ uta = None
5574
+ uta, params = self.handle_option_and_params(params, 'cancelOrder', 'uta', False)
5575
+ if uta:
5576
+ request['orderId'] = id
5577
+ if trigger:
5578
+ response = self.privateUtaPostV3TradeCancelStrategyOrder(self.extend(request, params))
5579
+ else:
5580
+ response = self.privateUtaPostV3TradeCancelOrder(self.extend(request, params))
5581
+ elif (market['swap']) or (market['future']):
4906
5582
  productType = None
4907
5583
  productType, params = self.handle_product_type_and_params(market, params)
4908
5584
  request['productType'] = productType
@@ -4975,15 +5651,60 @@ class bitget(Exchange, ImplicitAPI):
4975
5651
  # }
4976
5652
  # }
4977
5653
  #
5654
+ # uta trigger
5655
+ #
5656
+ # {
5657
+ # "code": "00000",
5658
+ # "msg": "success",
5659
+ # "requestTime": "1753058267399",
5660
+ # "data": null
5661
+ # }
5662
+ #
4978
5663
  data = self.safe_value(response, 'data', {})
4979
5664
  order = None
4980
- if (market['swap'] or market['future']) and trigger:
5665
+ if (market['swap'] or market['future']) and trigger and not uta:
4981
5666
  orderInfo = self.safe_value(data, 'successList', [])
4982
5667
  order = orderInfo[0]
4983
5668
  else:
4984
- order = data
5669
+ if uta and trigger:
5670
+ order = response
5671
+ else:
5672
+ order = data
4985
5673
  return self.parse_order(order, market)
4986
5674
 
5675
+ def cancel_uta_orders(self, ids, symbol: Str = None, params={}):
5676
+ if symbol is None:
5677
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
5678
+ self.load_markets()
5679
+ market = self.market(symbol)
5680
+ productType = None
5681
+ productType, params = self.handle_product_type_and_params(market, params)
5682
+ requestList = []
5683
+ for i in range(0, len(ids)):
5684
+ individualId = ids[i]
5685
+ order: dict = {
5686
+ 'orderId': individualId,
5687
+ 'symbol': market['id'],
5688
+ 'category': productType,
5689
+ }
5690
+ requestList.append(order)
5691
+ response = self.privateUtaPostV3TradeCancelBatch(requestList)
5692
+ #
5693
+ # {
5694
+ # "code": "00000",
5695
+ # "msg": "success",
5696
+ # "requestTime": 1752813731517,
5697
+ # "data": [
5698
+ # {
5699
+ # "orderId": "1329948909442023424",
5700
+ # "clientOid": "1329948909446217728"
5701
+ # },
5702
+ # ]
5703
+ # }
5704
+ #
5705
+ data = self.safe_list(response, 'data', [])
5706
+ return self.parse_orders(data, market)
5707
+
4987
5708
  def cancel_orders(self, ids, symbol: Str = None, params={}):
4988
5709
  """
4989
5710
  cancel multiple orders
@@ -4993,18 +5714,24 @@ class bitget(Exchange, ImplicitAPI):
4993
5714
  https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
4994
5715
  https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Cancel-Order
4995
5716
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Cancel-Orders
5717
+ https://www.bitget.com/api-doc/uta/trade/Cancel-Batch
4996
5718
 
4997
5719
  :param str[] ids: order ids
4998
5720
  :param str symbol: unified market symbol, default is None
4999
5721
  :param dict [params]: extra parameters specific to the exchange API endpoint
5000
5722
  :param str [params.marginMode]: 'isolated' or 'cross' for spot margin trading
5001
5723
  :param boolean [params.trigger]: *contract only* set to True for canceling trigger orders
5724
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5002
5725
  :returns dict: an array of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5003
5726
  """
5004
5727
  if symbol is None:
5005
5728
  raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
5006
5729
  self.load_markets()
5007
5730
  market = self.market(symbol)
5731
+ uta = None
5732
+ uta, params = self.handle_option_and_params(params, 'cancelOrders', 'uta', False)
5733
+ if uta:
5734
+ return self.cancel_uta_orders(ids, symbol, params)
5008
5735
  marginMode = None
5009
5736
  marginMode, params = self.handle_margin_mode_and_params('cancelOrders', params)
5010
5737
  trigger = self.safe_value_2(params, 'stop', 'trigger')
@@ -5069,11 +5796,13 @@ class bitget(Exchange, ImplicitAPI):
5069
5796
  https://www.bitget.com/api-doc/contract/trade/Batch-Cancel-Orders
5070
5797
  https://bitgetlimited.github.io/apidoc/en/margin/#isolated-batch-cancel-orders
5071
5798
  https://bitgetlimited.github.io/apidoc/en/margin/#cross-batch-cancel-order
5799
+ https://www.bitget.com/api-doc/uta/trade/Cancel-All-Order
5072
5800
 
5073
5801
  :param str symbol: unified market symbol
5074
5802
  :param dict [params]: extra parameters specific to the exchange API endpoint
5075
5803
  :param str [params.marginMode]: 'isolated' or 'cross' for spot margin trading
5076
5804
  :param boolean [params.trigger]: *contract only* set to True for canceling trigger orders
5805
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5077
5806
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5078
5807
  """
5079
5808
  if symbol is None:
@@ -5082,13 +5811,38 @@ class bitget(Exchange, ImplicitAPI):
5082
5811
  market = self.market(symbol)
5083
5812
  marginMode = None
5084
5813
  marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
5814
+ productType = None
5815
+ productType, params = self.handle_product_type_and_params(market, params)
5085
5816
  request: dict = {
5086
5817
  'symbol': market['id'],
5087
5818
  }
5088
5819
  trigger = self.safe_bool_2(params, 'stop', 'trigger')
5089
5820
  params = self.omit(params, ['stop', 'trigger'])
5090
5821
  response = None
5091
- if market['spot']:
5822
+ uta = None
5823
+ uta, params = self.handle_option_and_params(params, 'cancelAllOrders', 'uta', False)
5824
+ if uta:
5825
+ if productType == 'SPOT':
5826
+ if marginMode is not None:
5827
+ productType = 'MARGIN'
5828
+ request['category'] = productType
5829
+ response = self.privateUtaPostV3TradeCancelSymbolOrder(self.extend(request, params))
5830
+ #
5831
+ # {
5832
+ # "code": "00000",
5833
+ # "msg": "success",
5834
+ # "requestTime": 1750751578138,
5835
+ # "data": {
5836
+ # "list": [
5837
+ # {
5838
+ # "orderId": "1321313242969427968",
5839
+ # "clientOid": "1321313242969427969"
5840
+ # }
5841
+ # ]
5842
+ # }
5843
+ # }
5844
+ #
5845
+ elif market['spot']:
5092
5846
  if marginMode is not None:
5093
5847
  if marginMode == 'cross':
5094
5848
  response = self.privateMarginPostMarginV1CrossOrderBatchCancelOrder(self.extend(request, params))
@@ -5140,8 +5894,6 @@ class bitget(Exchange, ImplicitAPI):
5140
5894
  }),
5141
5895
  ]
5142
5896
  else:
5143
- productType = None
5144
- productType, params = self.handle_product_type_and_params(market, params)
5145
5897
  request['productType'] = productType
5146
5898
  if trigger:
5147
5899
  response = self.privateMixPostV2MixOrderCancelPlanOrder(self.extend(request, params))
@@ -5162,9 +5914,13 @@ class bitget(Exchange, ImplicitAPI):
5162
5914
  # }
5163
5915
  # }
5164
5916
  data = self.safe_dict(response, 'data')
5165
- resultList = self.safe_list_2(data, 'resultList', 'successList')
5917
+ resultList = self.safe_list_n(data, ['resultList', 'successList', 'list'])
5166
5918
  failureList = self.safe_list_2(data, 'failure', 'failureList')
5167
- responseList = self.array_concat(resultList, failureList)
5919
+ responseList = None
5920
+ if (resultList is not None) and (failureList is not None):
5921
+ responseList = self.array_concat(resultList, failureList)
5922
+ else:
5923
+ responseList = resultList
5168
5924
  return self.parse_orders(responseList)
5169
5925
 
5170
5926
  def fetch_order(self, id: str, symbol: Str = None, params={}):
@@ -5173,10 +5929,12 @@ class bitget(Exchange, ImplicitAPI):
5173
5929
 
5174
5930
  https://www.bitget.com/api-doc/spot/trade/Get-Order-Info
5175
5931
  https://www.bitget.com/api-doc/contract/trade/Get-Order-Details
5932
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-Details
5176
5933
 
5177
5934
  :param str id: the order id
5178
5935
  :param str symbol: unified symbol of the market the order was made in
5179
5936
  :param dict [params]: extra parameters specific to the exchange API endpoint
5937
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5180
5938
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
5181
5939
  """
5182
5940
  if symbol is None:
@@ -5187,7 +5945,11 @@ class bitget(Exchange, ImplicitAPI):
5187
5945
  'orderId': id,
5188
5946
  }
5189
5947
  response = None
5190
- if market['spot']:
5948
+ uta = None
5949
+ uta, params = self.handle_option_and_params(params, 'fetchOrder', 'uta', False)
5950
+ if uta:
5951
+ response = self.privateUtaGetV3TradeOrderInfo(self.extend(request, params))
5952
+ elif market['spot']:
5191
5953
  response = self.privateSpotGetV2SpotTradeOrderInfo(self.extend(request, params))
5192
5954
  elif market['swap'] or market['future']:
5193
5955
  request['symbol'] = market['id']
@@ -5264,13 +6026,60 @@ class bitget(Exchange, ImplicitAPI):
5264
6026
  # }
5265
6027
  # }
5266
6028
  #
5267
- if isinstance(response, str):
6029
+ # uta
6030
+ #
6031
+ # {
6032
+ # "code": "00000",
6033
+ # "msg": "success",
6034
+ # "requestTime": 1750496858333,
6035
+ # "data": {
6036
+ # "orderId": "1320244799629316096",
6037
+ # "clientOid": "1320244799633510400",
6038
+ # "category": "USDT-FUTURES",
6039
+ # "symbol": "BTCUSDT",
6040
+ # "orderType": "limit",
6041
+ # "side": "buy",
6042
+ # "price": "50000",
6043
+ # "qty": "0.001",
6044
+ # "amount": "0",
6045
+ # "cumExecQty": "0",
6046
+ # "cumExecValue": "0",
6047
+ # "avgPrice": "0",
6048
+ # "timeInForce": "gtc",
6049
+ # "orderStatus": "live",
6050
+ # "posSide": "long",
6051
+ # "holdMode": "hedge_mode",
6052
+ # "reduceOnly": "NO",
6053
+ # "feeDetail": [{
6054
+ # "feeCoin": "",
6055
+ # "fee": ""
6056
+ # }],
6057
+ # "createdTime": "1750496809871",
6058
+ # "updatedTime": "1750496809886",
6059
+ # "cancelReason": "",
6060
+ # "execType": "normal",
6061
+ # "stpMode": "none",
6062
+ # "tpTriggerBy": null,
6063
+ # "slTriggerBy": null,
6064
+ # "takeProfit": null,
6065
+ # "stopLoss": null,
6066
+ # "tpOrderType": null,
6067
+ # "slOrderType": null,
6068
+ # "tpLimitPrice": null,
6069
+ # "slLimitPrice": null
6070
+ # }
6071
+ # }
6072
+ #
6073
+ if not uta and (isinstance(response, str)):
5268
6074
  response = json.loads(response)
5269
6075
  data = self.safe_dict(response, 'data')
5270
6076
  if (data is not None):
5271
6077
  if not isinstance(data, list):
5272
6078
  return self.parse_order(data, market)
5273
6079
  dataList = self.safe_list(response, 'data', [])
6080
+ dataListLength = len(dataList)
6081
+ if dataListLength == 0:
6082
+ raise OrderNotFound(self.id + ' fetchOrder() could not find order id ' + id + ' in ' + self.json(response))
5274
6083
  first = self.safe_dict(dataList, 0, {})
5275
6084
  return self.parse_order(first, market)
5276
6085
  # first = self.safe_dict(data, 0, data)
@@ -5286,6 +6095,7 @@ class bitget(Exchange, ImplicitAPI):
5286
6095
  https://www.bitget.com/api-doc/contract/plan/get-orders-plan-pending
5287
6096
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Open-Orders
5288
6097
  https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Open-Orders
6098
+ https://www.bitget.com/api-doc/uta/strategy/Get-Unfilled-Strategy-Orders
5289
6099
 
5290
6100
  :param str symbol: unified market symbol
5291
6101
  :param int [since]: the earliest time in ms to fetch open orders for
@@ -5297,6 +6107,7 @@ class bitget(Exchange, ImplicitAPI):
5297
6107
  :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)
5298
6108
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5299
6109
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
6110
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5300
6111
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5301
6112
  """
5302
6113
  self.load_markets()
@@ -5305,6 +6116,8 @@ class bitget(Exchange, ImplicitAPI):
5305
6116
  request: dict = {}
5306
6117
  marginMode = None
5307
6118
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
6119
+ uta = None
6120
+ uta, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'uta', False)
5308
6121
  if symbol is not None:
5309
6122
  market = self.market(symbol)
5310
6123
  request['symbol'] = market['id']
@@ -5318,58 +6131,71 @@ class bitget(Exchange, ImplicitAPI):
5318
6131
  paginate, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'paginate')
5319
6132
  if paginate:
5320
6133
  cursorReceived = None
5321
- if type == 'spot':
6134
+ cursorSent = None
6135
+ if uta:
6136
+ cursorReceived = 'cursor'
6137
+ cursorSent = 'cursor'
6138
+ elif type == 'spot':
5322
6139
  if marginMode is not None:
5323
6140
  cursorReceived = 'minId'
6141
+ cursorSent = 'idLessThan'
5324
6142
  else:
5325
6143
  cursorReceived = 'endId'
5326
- return self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, 'idLessThan')
6144
+ cursorSent = 'idLessThan'
6145
+ return self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, cursorSent)
5327
6146
  response = None
5328
6147
  trailing = self.safe_bool(params, 'trailing')
5329
6148
  trigger = self.safe_bool_2(params, 'stop', 'trigger')
5330
6149
  planTypeDefined = self.safe_string(params, 'planType') is not None
5331
6150
  isTrigger = (trigger or planTypeDefined)
5332
- params = self.omit(params, ['stop', 'trigger', 'trailing'])
5333
6151
  request, params = self.handle_until_option('endTime', request, params)
5334
6152
  if since is not None:
5335
6153
  request['startTime'] = since
5336
6154
  if limit is not None:
5337
6155
  request['limit'] = limit
5338
- if (type == 'swap') or (type == 'future') or (marginMode is not None):
6156
+ if not uta and ((type == 'swap') or (type == 'future') or (marginMode is not None)):
5339
6157
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
5340
6158
  params = self.omit(params, 'clientOrderId')
5341
6159
  if clientOrderId is not None:
5342
6160
  request['clientOid'] = clientOrderId
5343
- query = None
5344
- query = self.omit(params, ['type'])
5345
- if type == 'spot':
6161
+ productType = None
6162
+ productType, params = self.handle_product_type_and_params(market, params)
6163
+ params = self.omit(params, ['type', 'stop', 'trigger', 'trailing'])
6164
+ if uta:
6165
+ if type == 'spot':
6166
+ if marginMode is not None:
6167
+ productType = 'MARGIN'
6168
+ request['category'] = productType
6169
+ if trigger:
6170
+ response = self.privateUtaGetV3TradeUnfilledStrategyOrders(self.extend(request, params))
6171
+ else:
6172
+ response = self.privateUtaGetV3TradeUnfilledOrders(self.extend(request, params))
6173
+ elif type == 'spot':
5346
6174
  if marginMode is not None:
5347
6175
  if since is None:
5348
6176
  since = self.milliseconds() - 7776000000
5349
6177
  request['startTime'] = since
5350
6178
  if marginMode == 'isolated':
5351
- response = self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, query))
6179
+ response = self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, params))
5352
6180
  elif marginMode == 'cross':
5353
- response = self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, query))
6181
+ response = self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, params))
5354
6182
  else:
5355
6183
  if trigger:
5356
- response = self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, query))
6184
+ response = self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, params))
5357
6185
  else:
5358
- response = self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, query))
6186
+ response = self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, params))
5359
6187
  else:
5360
- productType = None
5361
- productType, query = self.handle_product_type_and_params(market, query)
5362
6188
  request['productType'] = productType
5363
6189
  if trailing:
5364
6190
  planType = self.safe_string(params, 'planType', 'track_plan')
5365
6191
  request['planType'] = planType
5366
- response = self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, query))
6192
+ response = self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, params))
5367
6193
  elif isTrigger:
5368
- planType = self.safe_string(query, 'planType', 'normal_plan')
6194
+ planType = self.safe_string(params, 'planType', 'normal_plan')
5369
6195
  request['planType'] = planType
5370
- response = self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, query))
6196
+ response = self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, params))
5371
6197
  else:
5372
- response = self.privateMixGetV2MixOrderOrdersPending(self.extend(request, query))
6198
+ response = self.privateMixGetV2MixOrderOrdersPending(self.extend(request, params))
5373
6199
  #
5374
6200
  # spot
5375
6201
  #
@@ -5545,8 +6371,92 @@ class bitget(Exchange, ImplicitAPI):
5545
6371
  # }
5546
6372
  # }
5547
6373
  #
6374
+ # uta
6375
+ #
6376
+ # {
6377
+ # "code": "00000",
6378
+ # "msg": "success",
6379
+ # "requestTime": 1750753395850,
6380
+ # "data": {
6381
+ # "list": [
6382
+ # {
6383
+ # "orderId": "1321320757371228160",
6384
+ # "clientOid": "1321320757371228161",
6385
+ # "category": "USDT-FUTURES",
6386
+ # "symbol": "BTCUSDT",
6387
+ # "orderType": "limit",
6388
+ # "side": "buy",
6389
+ # "price": "50000",
6390
+ # "qty": "0.001",
6391
+ # "amount": "0",
6392
+ # "cumExecQty": "0",
6393
+ # "cumExecValue": "0",
6394
+ # "avgPrice": "0",
6395
+ # "timeInForce": "gtc",
6396
+ # "orderStatus": "live",
6397
+ # "posSide": "long",
6398
+ # "holdMode": "hedge_mode",
6399
+ # "reduceOnly": "NO",
6400
+ # "feeDetail": [
6401
+ # {
6402
+ # "feeCoin": "",
6403
+ # "fee": ""
6404
+ # }
6405
+ # ],
6406
+ # "createdTime": "1750753338186",
6407
+ # "updatedTime": "1750753338203",
6408
+ # "stpMode": "none",
6409
+ # "tpTriggerBy": null,
6410
+ # "slTriggerBy": null,
6411
+ # "takeProfit": null,
6412
+ # "stopLoss": null,
6413
+ # "tpOrderType": null,
6414
+ # "slOrderType": null,
6415
+ # "tpLimitPrice": null,
6416
+ # "slLimitPrice": null
6417
+ # }
6418
+ # ],
6419
+ # "cursor": "1321320757371228160"
6420
+ # }
6421
+ # }
6422
+ #
6423
+ # uta trigger
6424
+ #
6425
+ # {
6426
+ # "code": "00000",
6427
+ # "msg": "success",
6428
+ # "requestTime": 1753057527060,
6429
+ # "data": [
6430
+ # {
6431
+ # "orderId": "1330984742276198400",
6432
+ # "clientOid": "1330984742276198400",
6433
+ # "symbol": "BTCUSDT",
6434
+ # "category": "USDT-FUTURES",
6435
+ # "qty": "0.001",
6436
+ # "posSide": "long",
6437
+ # "tpTriggerBy": "market",
6438
+ # "slTriggerBy": "mark",
6439
+ # "takeProfit": "",
6440
+ # "stopLoss":"114000",
6441
+ # "tpOrderType": "market",
6442
+ # "slOrderType": "limit",
6443
+ # "tpLimitPrice": "",
6444
+ # "slLimitPrice": "113000",
6445
+ # "createdTime": "1753057411736",
6446
+ # "updatedTime": "1753057411747"
6447
+ # }
6448
+ # ]
6449
+ # }
6450
+ #
5548
6451
  data = self.safe_value(response, 'data')
5549
- if type == 'spot':
6452
+ if uta:
6453
+ result = None
6454
+ if trigger:
6455
+ result = self.safe_list(response, 'data', [])
6456
+ else:
6457
+ result = self.safe_list(data, 'list', [])
6458
+ return self.parse_orders(result, market, since, limit)
6459
+ elif type == 'spot':
5550
6460
  if (marginMode is not None) or trigger:
5551
6461
  resultList = self.safe_list(data, 'orderList', [])
5552
6462
  return self.parse_orders(resultList, market, since, limit)
@@ -5565,6 +6475,7 @@ class bitget(Exchange, ImplicitAPI):
5565
6475
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5566
6476
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5567
6477
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6478
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
5568
6479
 
5569
6480
  :param str symbol: unified market symbol of the closed orders
5570
6481
  :param int [since]: timestamp in ms of the earliest order
@@ -5592,6 +6503,7 @@ class bitget(Exchange, ImplicitAPI):
5592
6503
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5593
6504
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5594
6505
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6506
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
5595
6507
 
5596
6508
  :param str symbol: unified market symbol of the canceled orders
5597
6509
  :param int [since]: timestamp in ms of the earliest order
@@ -5618,6 +6530,8 @@ class bitget(Exchange, ImplicitAPI):
5618
6530
  https://www.bitget.com/api-doc/contract/plan/orders-plan-history
5619
6531
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
5620
6532
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
6533
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-History
6534
+ https://www.bitget.com/api-doc/uta/strategy/Get-History-Strategy-Orders
5621
6535
 
5622
6536
  fetches information on multiple canceled and closed orders made by the user
5623
6537
  :param str symbol: unified market symbol of the market orders were made in
@@ -5630,8 +6544,13 @@ class bitget(Exchange, ImplicitAPI):
5630
6544
  :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)
5631
6545
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5632
6546
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
6547
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
5633
6548
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
5634
6549
  """
6550
+ uta = None
6551
+ uta, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'uta', False)
6552
+ if uta:
6553
+ return self.fetch_uta_canceled_and_closed_orders(symbol, since, limit, params)
5635
6554
  self.load_markets()
5636
6555
  market = None
5637
6556
  request: dict = {}
@@ -5893,42 +6812,160 @@ class bitget(Exchange, ImplicitAPI):
5893
6812
  orders = self.safe_list(response, 'data', [])
5894
6813
  return self.parse_orders(orders, market, since, limit)
5895
6814
 
5896
- def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
5897
- """
5898
- fetch the history of changes, actions done by the user or operations that altered the balance of the user
5899
-
5900
- https://www.bitget.com/api-doc/spot/account/Get-Account-Bills
5901
- https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
5902
-
5903
- :param str [code]: unified currency code, default is None
5904
- :param int [since]: timestamp in ms of the earliest ledger entry, default is None
5905
- :param int [limit]: max number of ledger entries to return, default is None
5906
- :param dict [params]: extra parameters specific to the exchange API endpoint
5907
- :param int [params.until]: end time in ms
5908
- :param str [params.symbol]: *contract only* unified market symbol
5909
- :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
5910
- :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)
5911
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
5912
- """
6815
+ def fetch_uta_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5913
6816
  self.load_markets()
5914
- symbol = self.safe_string(params, 'symbol')
5915
- params = self.omit(params, 'symbol')
5916
6817
  market = None
5917
6818
  if symbol is not None:
5918
6819
  market = self.market(symbol)
5919
- marketType = None
5920
- marketType, params = self.handle_market_type_and_params('fetchLedger', market, params)
6820
+ productType = None
6821
+ productType, params = self.handle_product_type_and_params(market, params)
6822
+ if productType == 'SPOT':
6823
+ marginMode = None
6824
+ marginMode, params = self.handle_margin_mode_and_params('fetchCanceledAndClosedOrders', params)
6825
+ if marginMode is not None:
6826
+ productType = 'MARGIN'
6827
+ request: dict = {
6828
+ 'category': productType,
6829
+ }
5921
6830
  paginate = False
5922
- paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
6831
+ paginate, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'paginate')
5923
6832
  if paginate:
5924
- cursorReceived = None
5925
- if marketType != 'spot':
5926
- cursorReceived = 'endId'
5927
- return self.fetch_paginated_call_cursor('fetchLedger', symbol, since, limit, params, cursorReceived, 'idLessThan')
5928
- currency = None
5929
- request: dict = {}
5930
- if code is not None:
5931
- currency = self.currency(code)
6833
+ return self.fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, 'cursor', 'cursor')
6834
+ request, params = self.handle_until_option('endTime', request, params)
6835
+ if since is not None:
6836
+ request['startTime'] = since
6837
+ if limit is not None:
6838
+ request['limit'] = limit
6839
+ response = None
6840
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
6841
+ params = self.omit(params, ['stop', 'trigger'])
6842
+ if trigger:
6843
+ response = self.privateUtaGetV3TradeHistoryStrategyOrders(self.extend(request, params))
6844
+ else:
6845
+ response = self.privateUtaGetV3TradeHistoryOrders(self.extend(request, params))
6846
+ #
6847
+ # uta
6848
+ #
6849
+ # {
6850
+ # "code": "00000",
6851
+ # "msg": "success",
6852
+ # "requestTime": 1752531592855,
6853
+ # "data": {
6854
+ # "list": [
6855
+ # {
6856
+ # "orderId": "1322441400976261120",
6857
+ # "clientOid": "1322441400976261121",
6858
+ # "category": "USDT-FUTURES",
6859
+ # "symbol": "BTCUSDT",
6860
+ # "orderType": "market",
6861
+ # "side": "sell",
6862
+ # "price": "0",
6863
+ # "qty": "0.0001",
6864
+ # "amount": "0",
6865
+ # "cumExecQty": "0.0001",
6866
+ # "cumExecValue": "10.7005",
6867
+ # "avgPrice": "107005.4",
6868
+ # "timeInForce": "gtc",
6869
+ # "orderStatus": "filled",
6870
+ # "posSide": "long",
6871
+ # "holdMode": "hedge_mode",
6872
+ # "reduceOnly": "NO",
6873
+ # "feeDetail": [
6874
+ # {
6875
+ # "feeCoin": "USDT",
6876
+ # "fee": "0.00642032"
6877
+ # }
6878
+ # ],
6879
+ # "createdTime": "1751020520442",
6880
+ # "updatedTime": "1751020520457",
6881
+ # "cancelReason": "",
6882
+ # "execType": "normal",
6883
+ # "stpMode": "none",
6884
+ # "tpTriggerBy": null,
6885
+ # "slTriggerBy": null,
6886
+ # "takeProfit": null,
6887
+ # "stopLoss": null,
6888
+ # "tpOrderType": null,
6889
+ # "slOrderType": null,
6890
+ # "tpLimitPrice": null,
6891
+ # "slLimitPrice": null
6892
+ # },
6893
+ # ],
6894
+ # "cursor": "1322441328637100035"
6895
+ # }
6896
+ # }
6897
+ #
6898
+ # uta trigger
6899
+ #
6900
+ # {
6901
+ # "code": "00000",
6902
+ # "msg": "success",
6903
+ # "requestTime": 1753058447920,
6904
+ # "data": {
6905
+ # "list": [
6906
+ # {
6907
+ # "orderId": "1330984742276198400",
6908
+ # "clientOid": "1330984742276198400",
6909
+ # "symbol": "BTCUSDT",
6910
+ # "category": "USDT-FUTURES",
6911
+ # "qty": "0.001",
6912
+ # "posSide": "long",
6913
+ # "tpTriggerBy": "market",
6914
+ # "slTriggerBy": "mark",
6915
+ # "takeProfit": "",
6916
+ # "stopLoss": "112000",
6917
+ # "tpOrderType": "market",
6918
+ # "slOrderType": "limit",
6919
+ # "tpLimitPrice": "",
6920
+ # "slLimitPrice": "111000",
6921
+ # "createdTime": "1753057411736",
6922
+ # "updatedTime": "1753058267412"
6923
+ # },
6924
+ # ],
6925
+ # "cursor": 1330960754317619202
6926
+ # }
6927
+ # }
6928
+ #
6929
+ data = self.safe_dict(response, 'data', {})
6930
+ orders = self.safe_list(data, 'list', [])
6931
+ return self.parse_orders(orders, market, since, limit)
6932
+
6933
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
6934
+ """
6935
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
6936
+
6937
+ https://www.bitget.com/api-doc/spot/account/Get-Account-Bills
6938
+ https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
6939
+
6940
+ :param str [code]: unified currency code, default is None
6941
+ :param int [since]: timestamp in ms of the earliest ledger entry, default is None
6942
+ :param int [limit]: max number of ledger entries to return, default is None
6943
+ :param dict [params]: extra parameters specific to the exchange API endpoint
6944
+ :param int [params.until]: end time in ms
6945
+ :param str [params.symbol]: *contract only* unified market symbol
6946
+ :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
6947
+ :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)
6948
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
6949
+ """
6950
+ self.load_markets()
6951
+ symbol = self.safe_string(params, 'symbol')
6952
+ params = self.omit(params, 'symbol')
6953
+ market = None
6954
+ if symbol is not None:
6955
+ market = self.market(symbol)
6956
+ marketType = None
6957
+ marketType, params = self.handle_market_type_and_params('fetchLedger', market, params)
6958
+ paginate = False
6959
+ paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
6960
+ if paginate:
6961
+ cursorReceived = None
6962
+ if marketType != 'spot':
6963
+ cursorReceived = 'endId'
6964
+ return self.fetch_paginated_call_cursor('fetchLedger', symbol, since, limit, params, cursorReceived, 'idLessThan')
6965
+ currency = None
6966
+ request: dict = {}
6967
+ if code is not None:
6968
+ currency = self.currency(code)
5932
6969
  request['coin'] = currency['id']
5933
6970
  request, params = self.handle_until_option('endTime', request, params)
5934
6971
  if since is not None:
@@ -6108,55 +7145,67 @@ class bitget(Exchange, ImplicitAPI):
6108
7145
  https://www.bitget.com/api-doc/contract/trade/Get-Order-Fills
6109
7146
  https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-Fills
6110
7147
  https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Transaction-Details
7148
+ https://www.bitget.com/api-doc/uta/trade/Get-Order-Fills
6111
7149
 
6112
7150
  :param str symbol: unified market symbol
6113
7151
  :param int [since]: the earliest time in ms to fetch trades for
6114
7152
  :param int [limit]: the maximum number of trades structures to retrieve
6115
7153
  :param dict [params]: extra parameters specific to the exchange API endpoint
6116
7154
  :param int [params.until]: the latest time in ms to fetch trades for
7155
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6117
7156
  :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)
6118
7157
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
6119
7158
  """
6120
- if symbol is None:
7159
+ uta = None
7160
+ uta, params = self.handle_option_and_params(params, 'fetchMyTrades', 'uta', False)
7161
+ if not uta and (symbol is None):
6121
7162
  raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
6122
7163
  self.load_markets()
6123
7164
  market = self.market(symbol)
6124
- marginMode = None
6125
- marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
7165
+ request: dict = {}
7166
+ request, params = self.handle_until_option('endTime', request, params)
7167
+ if since is not None:
7168
+ request['startTime'] = since
7169
+ if limit is not None:
7170
+ request['limit'] = limit
6126
7171
  paginate = False
7172
+ marginMode = None
6127
7173
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
7174
+ marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
6128
7175
  if paginate:
6129
7176
  cursorReceived = None
6130
- if market['spot']:
7177
+ cursorSent = None
7178
+ if uta:
7179
+ cursorReceived = 'cursor'
7180
+ cursorSent = 'cursor'
7181
+ elif market['spot']:
6131
7182
  if marginMode is not None:
6132
7183
  cursorReceived = 'minId'
7184
+ cursorSent = 'idLessThan'
6133
7185
  else:
6134
7186
  cursorReceived = 'endId'
6135
- return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, cursorReceived, 'idLessThan')
7187
+ cursorSent = 'idLessThan'
7188
+ return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, cursorReceived, cursorSent)
6136
7189
  response = None
6137
- request: dict = {
6138
- 'symbol': market['id'],
6139
- }
6140
- request, params = self.handle_until_option('endTime', request, params)
6141
- if since is not None:
6142
- request['startTime'] = since
6143
- if limit is not None:
6144
- request['limit'] = limit
6145
- if market['spot']:
6146
- if marginMode is not None:
6147
- if since is None:
6148
- request['startTime'] = self.milliseconds() - 7776000000
6149
- if marginMode == 'isolated':
6150
- response = self.privateMarginGetV2MarginIsolatedFills(self.extend(request, params))
6151
- elif marginMode == 'cross':
6152
- response = self.privateMarginGetV2MarginCrossedFills(self.extend(request, params))
6153
- else:
6154
- response = self.privateSpotGetV2SpotTradeFills(self.extend(request, params))
7190
+ if uta:
7191
+ response = self.privateUtaGetV3TradeFills(self.extend(request, params))
6155
7192
  else:
6156
- productType = None
6157
- productType, params = self.handle_product_type_and_params(market, params)
6158
- request['productType'] = productType
6159
- response = self.privateMixGetV2MixOrderFills(self.extend(request, params))
7193
+ request['symbol'] = market['id']
7194
+ if market['spot']:
7195
+ if marginMode is not None:
7196
+ if since is None:
7197
+ request['startTime'] = self.milliseconds() - 7776000000
7198
+ if marginMode == 'isolated':
7199
+ response = self.privateMarginGetV2MarginIsolatedFills(self.extend(request, params))
7200
+ elif marginMode == 'cross':
7201
+ response = self.privateMarginGetV2MarginCrossedFills(self.extend(request, params))
7202
+ else:
7203
+ response = self.privateSpotGetV2SpotTradeFills(self.extend(request, params))
7204
+ else:
7205
+ productType = None
7206
+ productType, params = self.handle_product_type_and_params(market, params)
7207
+ request['productType'] = productType
7208
+ response = self.privateMixGetV2MixOrderFills(self.extend(request, params))
6160
7209
  #
6161
7210
  # spot
6162
7211
  #
@@ -6256,10 +7305,45 @@ class bitget(Exchange, ImplicitAPI):
6256
7305
  # }
6257
7306
  # }
6258
7307
  #
7308
+ # uta
7309
+ #
7310
+ # {
7311
+ # "code": "00000",
7312
+ # "msg": "success",
7313
+ # "requestTime": 1751099666579,
7314
+ # "data": {
7315
+ # "list": [
7316
+ # {
7317
+ # "execId": "1322441401010528257",
7318
+ # "orderId": "1322441400976261120",
7319
+ # "category": "USDT-FUTURES",
7320
+ # "symbol": "BTCUSDT",
7321
+ # "orderType": "market",
7322
+ # "side": "sell",
7323
+ # "execPrice": "107005.4",
7324
+ # "execQty": "0.0001",
7325
+ # "execValue": "10.7005",
7326
+ # "tradeScope": "taker",
7327
+ # "feeDetail": [{
7328
+ # "feeCoin": "USDT",
7329
+ # "fee":"0.00642032"
7330
+ # }],
7331
+ # "createdTime": "1751020520451",
7332
+ # "updatedTime": "1751020520458",
7333
+ # "execPnl": "0.00017"
7334
+ # },
7335
+ # ],
7336
+ # "cursor": "1322061241878880257"
7337
+ # }
7338
+ # }
7339
+ #
6259
7340
  data = self.safe_value(response, 'data')
6260
- if (market['swap']) or (market['future']):
6261
- fillList = self.safe_list(data, 'fillList', [])
6262
- return self.parse_trades(fillList, market, since, limit)
7341
+ if uta:
7342
+ fills = self.safe_list(data, 'list', [])
7343
+ return self.parse_trades(fills, market, since, limit)
7344
+ elif (market['swap'] or (market['future'])):
7345
+ fills = self.safe_list(data, 'fillList', [])
7346
+ return self.parse_trades(fills, market, since, limit)
6263
7347
  elif marginMode is not None:
6264
7348
  fills = self.safe_list(data, 'fills', [])
6265
7349
  return self.parse_trades(fills, market, since, limit)
@@ -6270,9 +7354,11 @@ class bitget(Exchange, ImplicitAPI):
6270
7354
  fetch data on a single open contract trade position
6271
7355
 
6272
7356
  https://www.bitget.com/api-doc/contract/position/get-single-position
7357
+ https://www.bitget.com/api-doc/uta/trade/Get-Position
6273
7358
 
6274
7359
  :param str symbol: unified market symbol of the market the position is held in
6275
7360
  :param dict [params]: extra parameters specific to the exchange API endpoint
7361
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6276
7362
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
6277
7363
  """
6278
7364
  self.load_markets()
@@ -6281,42 +7367,90 @@ class bitget(Exchange, ImplicitAPI):
6281
7367
  productType, params = self.handle_product_type_and_params(market, params)
6282
7368
  request: dict = {
6283
7369
  'symbol': market['id'],
6284
- 'marginCoin': market['settleId'],
6285
- 'productType': productType,
6286
7370
  }
6287
- response = self.privateMixGetV2MixPositionSinglePosition(self.extend(request, params))
6288
- #
6289
- # {
6290
- # "code": "00000",
6291
- # "msg": "success",
6292
- # "requestTime": 1700807531673,
6293
- # "data": [
6294
- # {
6295
- # "marginCoin": "USDT",
6296
- # "symbol": "BTCUSDT",
6297
- # "holdSide": "long",
6298
- # "openDelegateSize": "0",
6299
- # "marginSize": "3.73555",
6300
- # "available": "0.002",
6301
- # "locked": "0",
6302
- # "total": "0.002",
6303
- # "leverage": "20",
6304
- # "achievedProfits": "0",
6305
- # "openPriceAvg": "37355.5",
6306
- # "marginMode": "crossed",
6307
- # "posMode": "hedge_mode",
6308
- # "unrealizedPL": "0.007",
6309
- # "liquidationPrice": "31724.970702417",
6310
- # "keepMarginRate": "0.004",
6311
- # "markPrice": "37359",
6312
- # "marginRatio": "0.029599540355",
6313
- # "cTime": "1700807507275"
6314
- # }
6315
- # ]
6316
- # }
6317
- #
6318
- data = self.safe_list(response, 'data', [])
6319
- first = self.safe_dict(data, 0, {})
7371
+ response = None
7372
+ uta = None
7373
+ result = None
7374
+ uta, params = self.handle_option_and_params(params, 'fetchPosition', 'uta', False)
7375
+ if uta:
7376
+ request['category'] = productType
7377
+ response = self.privateUtaGetV3PositionCurrentPosition(self.extend(request, params))
7378
+ #
7379
+ # {
7380
+ # "code": "00000",
7381
+ # "msg": "success",
7382
+ # "requestTime": 1750929905423,
7383
+ # "data": {
7384
+ # "list": [
7385
+ # {
7386
+ # "category": "USDT-FUTURES",
7387
+ # "symbol": "BTCUSDT",
7388
+ # "marginCoin": "USDT",
7389
+ # "holdMode": "hedge_mode",
7390
+ # "posSide": "long",
7391
+ # "marginMode": "crossed",
7392
+ # "positionBalance": "5.435199",
7393
+ # "available": "0.001",
7394
+ # "frozen": "0",
7395
+ # "total": "0.001",
7396
+ # "leverage": "20",
7397
+ # "curRealisedPnl": "0",
7398
+ # "avgPrice": "107410.3",
7399
+ # "positionStatus": "normal",
7400
+ # "unrealisedPnl": "0.0047",
7401
+ # "liquidationPrice": "0",
7402
+ # "mmr": "0.004",
7403
+ # "profitRate": "0.0008647337475591",
7404
+ # "markPrice": "107415.3",
7405
+ # "breakEvenPrice": "107539.2",
7406
+ # "totalFunding": "0",
7407
+ # "openFeeTotal": "-0.06444618",
7408
+ # "closeFeeTotal": "0",
7409
+ # "createdTime": "1750495670699",
7410
+ # "updatedTime": "1750929883465"
7411
+ # }
7412
+ # ]
7413
+ # }
7414
+ # }
7415
+ #
7416
+ data = self.safe_dict(response, 'data', {})
7417
+ result = self.safe_list(data, 'list', [])
7418
+ else:
7419
+ request['marginCoin'] = market['settleId']
7420
+ request['productType'] = productType
7421
+ response = self.privateMixGetV2MixPositionSinglePosition(self.extend(request, params))
7422
+ #
7423
+ # {
7424
+ # "code": "00000",
7425
+ # "msg": "success",
7426
+ # "requestTime": 1700807531673,
7427
+ # "data": [
7428
+ # {
7429
+ # "marginCoin": "USDT",
7430
+ # "symbol": "BTCUSDT",
7431
+ # "holdSide": "long",
7432
+ # "openDelegateSize": "0",
7433
+ # "marginSize": "3.73555",
7434
+ # "available": "0.002",
7435
+ # "locked": "0",
7436
+ # "total": "0.002",
7437
+ # "leverage": "20",
7438
+ # "achievedProfits": "0",
7439
+ # "openPriceAvg": "37355.5",
7440
+ # "marginMode": "crossed",
7441
+ # "posMode": "hedge_mode",
7442
+ # "unrealizedPL": "0.007",
7443
+ # "liquidationPrice": "31724.970702417",
7444
+ # "keepMarginRate": "0.004",
7445
+ # "markPrice": "37359",
7446
+ # "marginRatio": "0.029599540355",
7447
+ # "cTime": "1700807507275"
7448
+ # }
7449
+ # ]
7450
+ # }
7451
+ #
7452
+ result = self.safe_list(response, 'data', [])
7453
+ first = self.safe_dict(result, 0, {})
6320
7454
  return self.parse_position(first, market)
6321
7455
 
6322
7456
  def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
@@ -6479,6 +7613,36 @@ class bitget(Exchange, ImplicitAPI):
6479
7613
  # "cTime": "1700807507275"
6480
7614
  # }
6481
7615
  #
7616
+ # uta: fetchPosition
7617
+ #
7618
+ # {
7619
+ # "category": "USDT-FUTURES",
7620
+ # "symbol": "BTCUSDT",
7621
+ # "marginCoin": "USDT",
7622
+ # "holdMode": "hedge_mode",
7623
+ # "posSide": "long",
7624
+ # "marginMode": "crossed",
7625
+ # "positionBalance": "5.435199",
7626
+ # "available": "0.001",
7627
+ # "frozen": "0",
7628
+ # "total": "0.001",
7629
+ # "leverage": "20",
7630
+ # "curRealisedPnl": "0",
7631
+ # "avgPrice": "107410.3",
7632
+ # "positionStatus": "normal",
7633
+ # "unrealisedPnl": "0.0047",
7634
+ # "liquidationPrice": "0",
7635
+ # "mmr": "0.004",
7636
+ # "profitRate": "0.0008647337475591",
7637
+ # "markPrice": "107415.3",
7638
+ # "breakEvenPrice": "107539.2",
7639
+ # "totalFunding": "0",
7640
+ # "openFeeTotal": "-0.06444618",
7641
+ # "closeFeeTotal": "0",
7642
+ # "createdTime": "1750495670699",
7643
+ # "updatedTime": "1750929883465"
7644
+ # }
7645
+ #
6482
7646
  # fetchPositions: privateMixGetV2MixPositionAllPosition
6483
7647
  #
6484
7648
  # {
@@ -6530,32 +7694,55 @@ class bitget(Exchange, ImplicitAPI):
6530
7694
  # "clientOid": "1120923953904893956"
6531
7695
  # }
6532
7696
  #
7697
+ # uta: fetchPositionsHistory
7698
+ #
7699
+ # {
7700
+ # "positionId": "1322441328637100049",
7701
+ # "category": "USDT-FUTURES",
7702
+ # "symbol": "BTCUSDT",
7703
+ # "marginCoin": "USDT",
7704
+ # "holdMode": "hedge_mode",
7705
+ # "posSide": "long",
7706
+ # "marginMode": "crossed",
7707
+ # "openPriceAvg": "107003.7",
7708
+ # "closePriceAvg": "107005.4",
7709
+ # "openTotalPos": "0.0001",
7710
+ # "closeTotalPos": "0.0001",
7711
+ # "cumRealisedPnl": "0.00017",
7712
+ # "netProfit": "-0.01267055",
7713
+ # "totalFunding": "0",
7714
+ # "openFeeTotal": "-0.00642022",
7715
+ # "closeFeeTotal": "-0.00642032",
7716
+ # "createdTime": "1751020503195",
7717
+ # "updatedTime": "1751020520458"
7718
+ # }
7719
+ #
6533
7720
  marketId = self.safe_string(position, 'symbol')
6534
7721
  market = self.safe_market(marketId, market, None, 'contract')
6535
7722
  symbol = market['symbol']
6536
- timestamp = self.safe_integer_2(position, 'cTime', 'ctime')
7723
+ timestamp = self.safe_integer_n(position, ['cTime', 'ctime', 'createdTime'])
6537
7724
  marginMode = self.safe_string(position, 'marginMode')
6538
7725
  collateral = None
6539
7726
  initialMargin = None
6540
- unrealizedPnl = self.safe_string(position, 'unrealizedPL')
6541
- rawCollateral = self.safe_string(position, 'marginSize')
7727
+ unrealizedPnl = self.safe_string_2(position, 'unrealizedPL', 'unrealisedPnl')
7728
+ rawCollateral = self.safe_string_2(position, 'marginSize', 'positionBalance')
6542
7729
  if marginMode == 'isolated':
6543
7730
  collateral = Precise.string_add(rawCollateral, unrealizedPnl)
6544
7731
  elif marginMode == 'crossed':
6545
7732
  marginMode = 'cross'
6546
7733
  initialMargin = rawCollateral
6547
- holdMode = self.safe_string(position, 'posMode')
7734
+ holdMode = self.safe_string_2(position, 'posMode', 'holdMode')
6548
7735
  hedged = None
6549
7736
  if holdMode == 'hedge_mode':
6550
7737
  hedged = True
6551
7738
  elif holdMode == 'one_way_mode':
6552
7739
  hedged = False
6553
- side = self.safe_string(position, 'holdSide')
7740
+ side = self.safe_string_2(position, 'holdSide', 'posSide')
6554
7741
  leverage = self.safe_string(position, 'leverage')
6555
7742
  contractSizeNumber = self.safe_value(market, 'contractSize')
6556
7743
  contractSize = self.number_to_string(contractSizeNumber)
6557
- baseAmount = self.safe_string(position, 'total')
6558
- entryPrice = self.safe_string_2(position, 'openPriceAvg', 'openAvgPrice')
7744
+ baseAmount = self.safe_string_2(position, 'total', 'openTotalPos')
7745
+ entryPrice = self.safe_string_n(position, ['openPriceAvg', 'openAvgPrice', 'avgPrice'])
6559
7746
  maintenanceMarginPercentage = self.safe_string(position, 'keepMarginRate')
6560
7747
  openNotional = Precise.string_mul(entryPrice, baseAmount)
6561
7748
  if initialMargin is None:
@@ -6587,31 +7774,31 @@ class bitget(Exchange, ImplicitAPI):
6587
7774
  percentage = Precise.string_mul(Precise.string_div(unrealizedPnl, initialMargin, 4), '100')
6588
7775
  return self.safe_position({
6589
7776
  'info': position,
6590
- 'id': self.safe_string(position, 'orderId'),
7777
+ 'id': self.safe_string_2(position, 'orderId', 'positionId'),
6591
7778
  'symbol': symbol,
6592
7779
  'notional': self.parse_number(notional),
6593
7780
  'marginMode': marginMode,
6594
7781
  'liquidationPrice': liquidationPrice,
6595
7782
  'entryPrice': self.parse_number(entryPrice),
6596
7783
  'unrealizedPnl': self.parse_number(unrealizedPnl),
6597
- 'realizedPnl': self.safe_number(position, 'pnl'),
7784
+ 'realizedPnl': self.safe_number_n(position, ['pnl', 'curRealisedPnl', 'cumRealisedPnl']),
6598
7785
  'percentage': self.parse_number(percentage),
6599
7786
  'contracts': contracts,
6600
7787
  'contractSize': contractSizeNumber,
6601
7788
  'markPrice': self.parse_number(markPrice),
6602
- 'lastPrice': self.safe_number(position, 'closeAvgPrice'),
7789
+ 'lastPrice': self.safe_number_2(position, 'closeAvgPrice', 'closePriceAvg'),
6603
7790
  'side': side,
6604
7791
  'hedged': hedged,
6605
7792
  'timestamp': timestamp,
6606
7793
  'datetime': self.iso8601(timestamp),
6607
- 'lastUpdateTimestamp': self.safe_integer(position, 'utime'),
7794
+ 'lastUpdateTimestamp': self.safe_integer_2(position, 'utime', 'updatedTime'),
6608
7795
  'maintenanceMargin': self.parse_number(maintenanceMargin),
6609
7796
  'maintenanceMarginPercentage': self.parse_number(maintenanceMarginPercentage),
6610
7797
  'collateral': self.parse_number(collateral),
6611
7798
  'initialMargin': self.parse_number(initialMargin),
6612
7799
  'initialMarginPercentage': self.parse_number(initialMarginPercentage),
6613
7800
  'leverage': self.parse_number(leverage),
6614
- 'marginRatio': self.safe_number(position, 'marginRatio'),
7801
+ 'marginRatio': self.safe_number_2(position, 'marginRatio', 'mmr'),
6615
7802
  'stopLossPrice': None,
6616
7803
  'takeProfitPrice': None,
6617
7804
  })
@@ -6621,54 +7808,82 @@ class bitget(Exchange, ImplicitAPI):
6621
7808
  fetches historical funding rate prices
6622
7809
 
6623
7810
  https://www.bitget.com/api-doc/contract/market/Get-History-Funding-Rate
7811
+ https://www.bitget.com/api-doc/uta/public/Get-History-Funding-Rate
6624
7812
 
6625
7813
  :param str symbol: unified symbol of the market to fetch the funding rate history for
6626
7814
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
6627
7815
  :param int [limit]: the maximum amount of funding rate structures to fetch
6628
7816
  :param dict [params]: extra parameters specific to the exchange API endpoint
7817
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6629
7818
  :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)
6630
7819
  :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
6631
7820
  """
6632
7821
  if symbol is None:
6633
7822
  raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
6634
7823
  self.load_markets()
6635
- paginate = False
6636
- paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
6637
- if paginate:
6638
- return self.fetch_paginated_call_incremental('fetchFundingRateHistory', symbol, since, limit, params, 'pageNo', 100)
6639
7824
  market = self.market(symbol)
6640
- productType = None
6641
- productType, params = self.handle_product_type_and_params(market, params)
6642
7825
  request: dict = {
6643
7826
  'symbol': market['id'],
6644
- 'productType': productType,
6645
- # 'pageSize': limit, # default 20
6646
- # 'pageNo': 1,
6647
7827
  }
6648
- if limit is not None:
6649
- request['pageSize'] = limit
6650
- response = self.publicMixGetV2MixMarketHistoryFundRate(self.extend(request, params))
6651
- #
6652
- # {
6653
- # "code": "00000",
6654
- # "msg": "success",
6655
- # "requestTime": 1652406728393,
6656
- # "data": [
6657
- # {
6658
- # "symbol": "BTCUSDT",
6659
- # "fundingRate": "-0.0003",
6660
- # "fundingTime": "1652396400000"
6661
- # },
6662
- # ]
6663
- # }
6664
- #
6665
- data = self.safe_value(response, 'data', [])
7828
+ productType = None
7829
+ uta = None
7830
+ response = None
7831
+ result = None
7832
+ productType, params = self.handle_product_type_and_params(market, params)
7833
+ uta, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'uta', False)
7834
+ if uta:
7835
+ if limit is not None:
7836
+ request['limit'] = limit
7837
+ request['category'] = productType
7838
+ response = self.publicUtaGetV3MarketHistoryFundRate(self.extend(request, params))
7839
+ #
7840
+ # {
7841
+ # "code": "00000",
7842
+ # "msg": "success",
7843
+ # "requestTime": 1750435113658,
7844
+ # "data": {
7845
+ # "resultList": [
7846
+ # {
7847
+ # "symbol": "BTCUSDT",
7848
+ # "fundingRate": "-0.000017",
7849
+ # "fundingRateTimestamp": "1750431600000"
7850
+ # },
7851
+ # ]
7852
+ # }
7853
+ # }
7854
+ #
7855
+ data = self.safe_dict(response, 'data', {})
7856
+ result = self.safe_list(data, 'resultList', [])
7857
+ else:
7858
+ paginate = False
7859
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
7860
+ if paginate:
7861
+ return self.fetch_paginated_call_incremental('fetchFundingRateHistory', symbol, since, limit, params, 'pageNo', 100)
7862
+ if limit is not None:
7863
+ request['pageSize'] = limit
7864
+ request['productType'] = productType
7865
+ response = self.publicMixGetV2MixMarketHistoryFundRate(self.extend(request, params))
7866
+ #
7867
+ # {
7868
+ # "code": "00000",
7869
+ # "msg": "success",
7870
+ # "requestTime": 1652406728393,
7871
+ # "data": [
7872
+ # {
7873
+ # "symbol": "BTCUSDT",
7874
+ # "fundingRate": "-0.0003",
7875
+ # "fundingTime": "1652396400000"
7876
+ # },
7877
+ # ]
7878
+ # }
7879
+ #
7880
+ result = self.safe_list(response, 'data', [])
6666
7881
  rates = []
6667
- for i in range(0, len(data)):
6668
- entry = data[i]
7882
+ for i in range(0, len(result)):
7883
+ entry = result[i]
6669
7884
  marketId = self.safe_string(entry, 'symbol')
6670
7885
  symbolInner = self.safe_symbol(marketId, market)
6671
- timestamp = self.safe_integer(entry, 'fundingTime')
7886
+ timestamp = self.safe_integer_2(entry, 'fundingTime', 'fundingRateTimestamp')
6672
7887
  rates.append({
6673
7888
  'info': entry,
6674
7889
  'symbol': symbolInner,
@@ -6685,9 +7900,11 @@ class bitget(Exchange, ImplicitAPI):
6685
7900
 
6686
7901
  https://www.bitget.com/api-doc/contract/market/Get-Current-Funding-Rate
6687
7902
  https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
7903
+ https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
6688
7904
 
6689
7905
  :param str symbol: unified market symbol
6690
7906
  :param dict [params]: extra parameters specific to the exchange API endpoint
7907
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
6691
7908
  :param str [params.method]: either(default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
6692
7909
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
6693
7910
  """
@@ -6699,46 +7916,68 @@ class bitget(Exchange, ImplicitAPI):
6699
7916
  productType, params = self.handle_product_type_and_params(market, params)
6700
7917
  request: dict = {
6701
7918
  'symbol': market['id'],
6702
- 'productType': productType,
6703
7919
  }
6704
- method = None
6705
- method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
7920
+ uta = None
6706
7921
  response = None
6707
- if method == 'publicMixGetV2MixMarketCurrentFundRate':
6708
- response = self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
7922
+ uta, params = self.handle_option_and_params(params, 'fetchFundingRate', 'uta', False)
7923
+ if uta:
7924
+ response = self.publicUtaGetV3MarketCurrentFundRate(self.extend(request, params))
6709
7925
  #
6710
7926
  # {
6711
7927
  # "code": "00000",
6712
7928
  # "msg": "success",
6713
- # "requestTime": 1745500709429,
7929
+ # "requestTime": 1750897372153,
6714
7930
  # "data": [
6715
7931
  # {
6716
7932
  # "symbol": "BTCUSDT",
6717
- # "fundingRate": "-0.000013",
7933
+ # "fundingRate": "0.00001",
6718
7934
  # "fundingRateInterval": "8",
6719
- # "nextUpdate": "1745510400000",
7935
+ # "nextUpdate": "1750924800000",
6720
7936
  # "minFundingRate": "-0.003",
6721
7937
  # "maxFundingRate": "0.003"
6722
7938
  # }
6723
7939
  # ]
6724
7940
  # }
6725
7941
  #
6726
- elif method == 'publicMixGetV2MixMarketFundingTime':
6727
- response = self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
6728
- #
6729
- # {
6730
- # "code": "00000",
6731
- # "msg": "success",
6732
- # "requestTime": 1745402092428,
6733
- # "data": [
6734
- # {
6735
- # "symbol": "BTCUSDT",
6736
- # "nextFundingTime": "1745424000000",
6737
- # "ratePeriod": "8"
6738
- # }
6739
- # ]
6740
- # }
6741
- #
7942
+ else:
7943
+ request['productType'] = productType
7944
+ method = None
7945
+ method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
7946
+ if method == 'publicMixGetV2MixMarketCurrentFundRate':
7947
+ response = self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
7948
+ #
7949
+ # {
7950
+ # "code": "00000",
7951
+ # "msg": "success",
7952
+ # "requestTime": 1745500709429,
7953
+ # "data": [
7954
+ # {
7955
+ # "symbol": "BTCUSDT",
7956
+ # "fundingRate": "-0.000013",
7957
+ # "fundingRateInterval": "8",
7958
+ # "nextUpdate": "1745510400000",
7959
+ # "minFundingRate": "-0.003",
7960
+ # "maxFundingRate": "0.003"
7961
+ # }
7962
+ # ]
7963
+ # }
7964
+ #
7965
+ elif method == 'publicMixGetV2MixMarketFundingTime':
7966
+ response = self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
7967
+ #
7968
+ # {
7969
+ # "code": "00000",
7970
+ # "msg": "success",
7971
+ # "requestTime": 1745402092428,
7972
+ # "data": [
7973
+ # {
7974
+ # "symbol": "BTCUSDT",
7975
+ # "nextFundingTime": "1745424000000",
7976
+ # "ratePeriod": "8"
7977
+ # }
7978
+ # ]
7979
+ # }
7980
+ #
6742
7981
  data = self.safe_list(response, 'data', [])
6743
7982
  return self.parse_funding_rate(data[0], market)
6744
7983
 
@@ -6802,7 +8041,7 @@ class bitget(Exchange, ImplicitAPI):
6802
8041
 
6803
8042
  def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
6804
8043
  #
6805
- # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate
8044
+ # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate, publicUtaGetV3MarketCurrentFundRate
6806
8045
  #
6807
8046
  # {
6808
8047
  # "symbol": "BTCUSDT",
@@ -7148,11 +8387,14 @@ class bitget(Exchange, ImplicitAPI):
7148
8387
  set the level of leverage for a market
7149
8388
 
7150
8389
  https://www.bitget.com/api-doc/contract/account/Change-Leverage
8390
+ https://www.bitget.com/api-doc/uta/account/Change-Leverage
7151
8391
 
7152
8392
  :param int leverage: the rate of leverage
7153
8393
  :param str symbol: unified market symbol
7154
8394
  :param dict [params]: extra parameters specific to the exchange API endpoint
7155
8395
  :param str [params.holdSide]: *isolated only* position direction, 'long' or 'short'
8396
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8397
+ :param boolean [params.posSide]: required for uta isolated margin, long or short
7156
8398
  :returns dict: response from the exchange
7157
8399
  """
7158
8400
  if symbol is None:
@@ -7163,27 +8405,47 @@ class bitget(Exchange, ImplicitAPI):
7163
8405
  productType, params = self.handle_product_type_and_params(market, params)
7164
8406
  request: dict = {
7165
8407
  'symbol': market['id'],
7166
- 'marginCoin': market['settleId'],
7167
8408
  'leverage': self.number_to_string(leverage),
7168
- 'productType': productType,
7169
- # 'holdSide': 'long',
7170
8409
  }
7171
- response = self.privateMixPostV2MixAccountSetLeverage(self.extend(request, params))
7172
- #
7173
- # {
7174
- # "code": "00000",
7175
- # "msg": "success",
7176
- # "requestTime": 1700864711517,
7177
- # "data": {
7178
- # "symbol": "BTCUSDT",
7179
- # "marginCoin": "USDT",
7180
- # "longLeverage": "25",
7181
- # "shortLeverage": "25",
7182
- # "crossMarginLeverage": "25",
7183
- # "marginMode": "crossed"
7184
- # }
7185
- # }
7186
- #
8410
+ uta = None
8411
+ response = None
8412
+ uta, params = self.handle_option_and_params(params, 'setLeverage', 'uta', False)
8413
+ if uta:
8414
+ if productType == 'SPOT':
8415
+ marginMode = None
8416
+ marginMode, params = self.handle_margin_mode_and_params('fetchTrades', params)
8417
+ if marginMode is not None:
8418
+ productType = 'MARGIN'
8419
+ request['coin'] = market['settleId']
8420
+ request['category'] = productType
8421
+ response = self.privateUtaPostV3AccountSetLeverage(self.extend(request, params))
8422
+ #
8423
+ # {
8424
+ # "code": "00000",
8425
+ # "msg": "success",
8426
+ # "requestTime": 1752815940833,
8427
+ # "data": "success"
8428
+ # }
8429
+ #
8430
+ else:
8431
+ request['marginCoin'] = market['settleId']
8432
+ request['productType'] = productType
8433
+ response = self.privateMixPostV2MixAccountSetLeverage(self.extend(request, params))
8434
+ #
8435
+ # {
8436
+ # "code": "00000",
8437
+ # "msg": "success",
8438
+ # "requestTime": 1700864711517,
8439
+ # "data": {
8440
+ # "symbol": "BTCUSDT",
8441
+ # "marginCoin": "USDT",
8442
+ # "longLeverage": "25",
8443
+ # "shortLeverage": "25",
8444
+ # "crossMarginLeverage": "25",
8445
+ # "marginMode": "crossed"
8446
+ # }
8447
+ # }
8448
+ #
7187
8449
  return response
7188
8450
 
7189
8451
  def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
@@ -7236,35 +8498,51 @@ class bitget(Exchange, ImplicitAPI):
7236
8498
  set hedged to True or False for a market
7237
8499
 
7238
8500
  https://www.bitget.com/api-doc/contract/account/Change-Hold-Mode
8501
+ https://www.bitget.com/api-doc/uta/account/Change-Position-Mode
7239
8502
 
7240
8503
  :param bool hedged: set to True to use dualSidePosition
7241
8504
  :param str symbol: not used by bitget setPositionMode()
7242
8505
  :param dict [params]: extra parameters specific to the exchange API endpoint
7243
- :param str [params.productType]: required if symbol is None: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
8506
+ :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'
8507
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
7244
8508
  :returns dict: response from the exchange
7245
8509
  """
7246
8510
  self.load_markets()
7247
8511
  posMode = 'hedge_mode' if hedged else 'one_way_mode'
8512
+ request: dict = {}
7248
8513
  market = None
7249
8514
  if symbol is not None:
7250
8515
  market = self.market(symbol)
7251
8516
  productType = None
8517
+ uta = None
8518
+ response = None
7252
8519
  productType, params = self.handle_product_type_and_params(market, params)
7253
- request: dict = {
7254
- 'posMode': posMode,
7255
- 'productType': productType,
7256
- }
7257
- response = self.privateMixPostV2MixAccountSetPositionMode(self.extend(request, params))
7258
- #
7259
- # {
7260
- # "code": "00000",
7261
- # "msg": "success",
7262
- # "requestTime": 1700865608009,
7263
- # "data": {
7264
- # "posMode": "hedge_mode"
7265
- # }
7266
- # }
7267
- #
8520
+ uta, params = self.handle_option_and_params(params, 'setPositionMode', 'uta', False)
8521
+ if uta:
8522
+ request['holdMode'] = posMode
8523
+ response = self.privateUtaPostV3AccountSetHoldMode(self.extend(request, params))
8524
+ #
8525
+ # {
8526
+ # "code": "00000",
8527
+ # "msg": "success",
8528
+ # "requestTime": 1752816734592,
8529
+ # "data": "success"
8530
+ # }
8531
+ #
8532
+ else:
8533
+ request['posMode'] = posMode
8534
+ request['productType'] = productType
8535
+ response = self.privateMixPostV2MixAccountSetPositionMode(self.extend(request, params))
8536
+ #
8537
+ # {
8538
+ # "code": "00000",
8539
+ # "msg": "success",
8540
+ # "requestTime": 1700865608009,
8541
+ # "data": {
8542
+ # "posMode": "hedge_mode"
8543
+ # }
8544
+ # }
8545
+ #
7268
8546
  return response
7269
8547
 
7270
8548
  def fetch_open_interest(self, symbol: str, params={}):
@@ -7272,9 +8550,11 @@ class bitget(Exchange, ImplicitAPI):
7272
8550
  retrieves the open interest of a contract trading pair
7273
8551
 
7274
8552
  https://www.bitget.com/api-doc/contract/market/Get-Open-Interest
8553
+ https://www.bitget.com/api-doc/uta/public/Get-Open-Interest
7275
8554
 
7276
8555
  :param str symbol: unified CCXT market symbol
7277
8556
  :param dict [params]: exchange specific parameters
8557
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
7278
8558
  :returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
7279
8559
  """
7280
8560
  self.load_markets()
@@ -7285,29 +8565,54 @@ class bitget(Exchange, ImplicitAPI):
7285
8565
  productType, params = self.handle_product_type_and_params(market, params)
7286
8566
  request: dict = {
7287
8567
  'symbol': market['id'],
7288
- 'productType': productType,
7289
8568
  }
7290
- response = self.publicMixGetV2MixMarketOpenInterest(self.extend(request, params))
7291
- #
7292
- # {
7293
- # "code": "00000",
7294
- # "msg": "success",
7295
- # "requestTime": 1700866041022,
7296
- # "data": {
7297
- # "openInterestList": [
7298
- # {
7299
- # "symbol": "BTCUSDT",
7300
- # "size": "52234.134"
7301
- # }
7302
- # ],
7303
- # "ts": "1700866041023"
7304
- # }
7305
- # }
7306
- #
8569
+ uta = None
8570
+ response = None
8571
+ uta, params = self.handle_option_and_params(params, 'fetchOpenInterest', 'uta', False)
8572
+ if uta:
8573
+ request['category'] = productType
8574
+ response = self.publicUtaGetV3MarketOpenInterest(self.extend(request, params))
8575
+ #
8576
+ # {
8577
+ # "code": "00000",
8578
+ # "msg": "success",
8579
+ # "requestTime": 1751101221545,
8580
+ # "data": {
8581
+ # "list": [
8582
+ # {
8583
+ # "symbol": "BTCUSDT",
8584
+ # "openInterest": "18166.3583"
8585
+ # }
8586
+ # ],
8587
+ # "ts": "1751101220993"
8588
+ # }
8589
+ # }
8590
+ #
8591
+ else:
8592
+ request['productType'] = productType
8593
+ response = self.publicMixGetV2MixMarketOpenInterest(self.extend(request, params))
8594
+ #
8595
+ # {
8596
+ # "code": "00000",
8597
+ # "msg": "success",
8598
+ # "requestTime": 1700866041022,
8599
+ # "data": {
8600
+ # "openInterestList": [
8601
+ # {
8602
+ # "symbol": "BTCUSDT",
8603
+ # "size": "52234.134"
8604
+ # }
8605
+ # ],
8606
+ # "ts": "1700866041023"
8607
+ # }
8608
+ # }
8609
+ #
7307
8610
  data = self.safe_dict(response, 'data', {})
7308
8611
  return self.parse_open_interest(data, market)
7309
8612
 
7310
8613
  def parse_open_interest(self, interest, market: Market = None):
8614
+ #
8615
+ # default
7311
8616
  #
7312
8617
  # {
7313
8618
  # "openInterestList": [
@@ -7319,12 +8624,24 @@ class bitget(Exchange, ImplicitAPI):
7319
8624
  # "ts": "1700866041023"
7320
8625
  # }
7321
8626
  #
7322
- data = self.safe_value(interest, 'openInterestList', [])
8627
+ # uta
8628
+ #
8629
+ # {
8630
+ # "list": [
8631
+ # {
8632
+ # "symbol": "BTCUSDT",
8633
+ # "openInterest": "18166.3583"
8634
+ # }
8635
+ # ],
8636
+ # "ts": "1751101220993"
8637
+ # }
8638
+ #
8639
+ data = self.safe_list_2(interest, 'openInterestList', 'list', [])
7323
8640
  timestamp = self.safe_integer(interest, 'ts')
7324
8641
  marketId = self.safe_string(data[0], 'symbol')
7325
8642
  return self.safe_open_interest({
7326
8643
  'symbol': self.safe_symbol(marketId, market, None, 'contract'),
7327
- 'openInterestAmount': self.safe_number(data[0], 'size'),
8644
+ 'openInterestAmount': self.safe_number_2(data[0], 'size', 'openInterest'),
7328
8645
  'openInterestValue': None,
7329
8646
  'timestamp': timestamp,
7330
8647
  'datetime': self.iso8601(timestamp),
@@ -8047,10 +9364,11 @@ class bitget(Exchange, ImplicitAPI):
8047
9364
  fetch the rate of interest to borrow a currency for margin trading
8048
9365
 
8049
9366
  https://www.bitget.com/api-doc/margin/cross/account/Get-Cross-Margin-Interest-Rate-And-Borrowable
9367
+ https://www.bitget.com/api-doc/uta/public/Get-Margin-Loans
8050
9368
 
8051
9369
  :param str code: unified currency code
8052
9370
  :param dict [params]: extra parameters specific to the exchange API endpoint
8053
- :param str [params.symbol]: required for isolated margin
9371
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8054
9372
  :returns dict: a `borrow rate structure <https://github.com/ccxt/ccxt/wiki/Manual#borrow-rate-structure>`
8055
9373
  """
8056
9374
  self.load_markets()
@@ -8058,40 +9376,62 @@ class bitget(Exchange, ImplicitAPI):
8058
9376
  request: dict = {
8059
9377
  'coin': currency['id'],
8060
9378
  }
8061
- response = self.privateMarginGetV2MarginCrossedInterestRateAndLimit(self.extend(request, params))
8062
- #
8063
- # {
8064
- # "code": "00000",
8065
- # "msg": "success",
8066
- # "requestTime": 1700879047861,
8067
- # "data": [
8068
- # {
8069
- # "coin": "BTC",
8070
- # "leverage": "3",
8071
- # "transferable": True,
8072
- # "borrowable": True,
8073
- # "dailyInterestRate": "0.00007",
8074
- # "annualInterestRate": "0.02555",
8075
- # "maxBorrowableAmount": "26",
8076
- # "vipList": [
8077
- # {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
8078
- # {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
8079
- # {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
8080
- # {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
8081
- # {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
8082
- # {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
8083
- # ]
8084
- # }
8085
- # ]
8086
- # }
8087
- #
9379
+ uta = None
9380
+ response = None
9381
+ result = None
9382
+ uta, params = self.handle_option_and_params(params, 'fetchCrossBorrowRate', 'uta', False)
9383
+ if uta:
9384
+ response = self.publicUtaGetV3MarketMarginLoans(self.extend(request, params))
9385
+ #
9386
+ # {
9387
+ # "code": "00000",
9388
+ # "msg": "success",
9389
+ # "requestTime": 1752817798893,
9390
+ # "data": {
9391
+ # "dailyInterest": "0.00100008",
9392
+ # "annualInterest": "0.3650292",
9393
+ # "limit": "100"
9394
+ # }
9395
+ # }
9396
+ #
9397
+ result = self.safe_dict(response, 'data', {})
9398
+ else:
9399
+ response = self.privateMarginGetV2MarginCrossedInterestRateAndLimit(self.extend(request, params))
9400
+ #
9401
+ # {
9402
+ # "code": "00000",
9403
+ # "msg": "success",
9404
+ # "requestTime": 1700879047861,
9405
+ # "data": [
9406
+ # {
9407
+ # "coin": "BTC",
9408
+ # "leverage": "3",
9409
+ # "transferable": True,
9410
+ # "borrowable": True,
9411
+ # "dailyInterestRate": "0.00007",
9412
+ # "annualInterestRate": "0.02555",
9413
+ # "maxBorrowableAmount": "26",
9414
+ # "vipList": [
9415
+ # {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
9416
+ # {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
9417
+ # {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
9418
+ # {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
9419
+ # {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
9420
+ # {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
9421
+ # ]
9422
+ # }
9423
+ # ]
9424
+ # }
9425
+ #
9426
+ data = self.safe_value(response, 'data', [])
9427
+ result = self.safe_value(data, 0, {})
8088
9428
  timestamp = self.safe_integer(response, 'requestTime')
8089
- data = self.safe_value(response, 'data', [])
8090
- first = self.safe_value(data, 0, {})
8091
- first['timestamp'] = timestamp
8092
- return self.parse_borrow_rate(first, currency)
9429
+ result['timestamp'] = timestamp
9430
+ return self.parse_borrow_rate(result, currency)
8093
9431
 
8094
9432
  def parse_borrow_rate(self, info, currency: Currency = None):
9433
+ #
9434
+ # default
8095
9435
  #
8096
9436
  # {
8097
9437
  # "coin": "BTC",
@@ -8111,11 +9451,19 @@ class bitget(Exchange, ImplicitAPI):
8111
9451
  # ]
8112
9452
  # }
8113
9453
  #
9454
+ # uta
9455
+ #
9456
+ # {
9457
+ # "dailyInterest": "0.00100008",
9458
+ # "annualInterest": "0.3650292",
9459
+ # "limit": "100"
9460
+ # }
9461
+ #
8114
9462
  currencyId = self.safe_string(info, 'coin')
8115
9463
  timestamp = self.safe_integer(info, 'timestamp')
8116
9464
  return {
8117
9465
  'currency': self.safe_currency_code(currencyId, currency),
8118
- 'rate': self.safe_number(info, 'dailyInterestRate'),
9466
+ 'rate': self.safe_number_2(info, 'dailyInterestRate', 'dailyInterest'),
8119
9467
  'period': 86400000, # 1-Day
8120
9468
  'timestamp': timestamp,
8121
9469
  'datetime': self.iso8601(timestamp),
@@ -8271,42 +9619,68 @@ class bitget(Exchange, ImplicitAPI):
8271
9619
  closes an open position for a market
8272
9620
 
8273
9621
  https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
9622
+ https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
8274
9623
 
8275
9624
  :param str symbol: unified CCXT market symbol
8276
9625
  :param str [side]: one-way mode: 'buy' or 'sell', hedge-mode: 'long' or 'short'
8277
9626
  :param dict [params]: extra parameters specific to the exchange API endpoint
9627
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8278
9628
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
8279
9629
  """
8280
9630
  self.load_markets()
8281
9631
  market = self.market(symbol)
8282
- productType = None
8283
- productType, params = self.handle_product_type_and_params(market, params)
8284
9632
  request: dict = {
8285
9633
  'symbol': market['id'],
8286
- 'productType': productType,
8287
9634
  }
8288
- if side is not None:
8289
- request['holdSide'] = side
8290
- response = self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
8291
- #
8292
- # {
8293
- # "code": "00000",
8294
- # "msg": "success",
8295
- # "requestTime": 1702975017017,
8296
- # "data": {
8297
- # "successList": [
8298
- # {
8299
- # "orderId": "1120923953904893955",
8300
- # "clientOid": "1120923953904893956"
8301
- # }
8302
- # ],
8303
- # "failureList": [],
8304
- # "result": False
8305
- # }
8306
- # }
8307
- #
9635
+ productType = None
9636
+ uta = None
9637
+ response = None
9638
+ productType, params = self.handle_product_type_and_params(market, params)
9639
+ uta, params = self.handle_option_and_params(params, 'closePosition', 'uta', False)
9640
+ if uta:
9641
+ if side is not None:
9642
+ request['posSide'] = side
9643
+ request['category'] = productType
9644
+ response = self.privateUtaPostV3TradeClosePositions(self.extend(request, params))
9645
+ #
9646
+ # {
9647
+ # "code": "00000",
9648
+ # "msg": "success",
9649
+ # "requestTime": 1751020218384,
9650
+ # "data": {
9651
+ # "list": [
9652
+ # {
9653
+ # "orderId": "1322440134099320832",
9654
+ # "clientOid": "1322440134099320833"
9655
+ # }
9656
+ # ]
9657
+ # }
9658
+ # }
9659
+ #
9660
+ else:
9661
+ if side is not None:
9662
+ request['holdSide'] = side
9663
+ request['productType'] = productType
9664
+ response = self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
9665
+ #
9666
+ # {
9667
+ # "code": "00000",
9668
+ # "msg": "success",
9669
+ # "requestTime": 1702975017017,
9670
+ # "data": {
9671
+ # "successList": [
9672
+ # {
9673
+ # "orderId": "1120923953904893955",
9674
+ # "clientOid": "1120923953904893956"
9675
+ # }
9676
+ # ],
9677
+ # "failureList": [],
9678
+ # "result": False
9679
+ # }
9680
+ # }
9681
+ #
8308
9682
  data = self.safe_value(response, 'data', {})
8309
- order = self.safe_list(data, 'successList', [])
9683
+ order = self.safe_list_2(data, 'successList', 'list', [])
8310
9684
  return self.parse_order(order[0], market)
8311
9685
 
8312
9686
  def close_all_positions(self, params={}) -> List[Position]:
@@ -8314,37 +9688,60 @@ class bitget(Exchange, ImplicitAPI):
8314
9688
  closes all open positions for a market type
8315
9689
 
8316
9690
  https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
9691
+ https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
8317
9692
 
8318
9693
  :param dict [params]: extra parameters specific to the exchange API endpoint
8319
9694
  :param str [params.productType]: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
9695
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8320
9696
  :returns dict[]: A list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
8321
9697
  """
8322
9698
  self.load_markets()
9699
+ request: dict = {}
8323
9700
  productType = None
9701
+ uta = None
9702
+ response = None
8324
9703
  productType, params = self.handle_product_type_and_params(None, params)
8325
- request: dict = {
8326
- 'productType': productType,
8327
- }
8328
- response = self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
8329
- #
8330
- # {
8331
- # "code": "00000",
8332
- # "msg": "success",
8333
- # "requestTime": 1702975017017,
8334
- # "data": {
8335
- # "successList": [
8336
- # {
8337
- # "orderId": "1120923953904893955",
8338
- # "clientOid": "1120923953904893956"
8339
- # }
8340
- # ],
8341
- # "failureList": [],
8342
- # "result": False
8343
- # }
8344
- # }
8345
- #
9704
+ uta, params = self.handle_option_and_params(params, 'closeAllPositions', 'uta', False)
9705
+ if uta:
9706
+ request['category'] = productType
9707
+ response = self.privateUtaPostV3TradeClosePositions(self.extend(request, params))
9708
+ #
9709
+ # {
9710
+ # "code": "00000",
9711
+ # "msg": "success",
9712
+ # "requestTime": 1751020218384,
9713
+ # "data": {
9714
+ # "list": [
9715
+ # {
9716
+ # "orderId": "1322440134099320832",
9717
+ # "clientOid": "1322440134099320833"
9718
+ # }
9719
+ # ]
9720
+ # }
9721
+ # }
9722
+ #
9723
+ else:
9724
+ request['productType'] = productType
9725
+ response = self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
9726
+ #
9727
+ # {
9728
+ # "code": "00000",
9729
+ # "msg": "success",
9730
+ # "requestTime": 1702975017017,
9731
+ # "data": {
9732
+ # "successList": [
9733
+ # {
9734
+ # "orderId": "1120923953904893955",
9735
+ # "clientOid": "1120923953904893956"
9736
+ # }
9737
+ # ],
9738
+ # "failureList": [],
9739
+ # "result": False
9740
+ # }
9741
+ # }
9742
+ #
8346
9743
  data = self.safe_value(response, 'data', {})
8347
- orderInfo = self.safe_list(data, 'successList', [])
9744
+ orderInfo = self.safe_list_2(data, 'successList', 'list', [])
8348
9745
  return self.parse_positions(orderInfo, None, params)
8349
9746
 
8350
9747
  def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
@@ -8412,21 +9809,23 @@ class bitget(Exchange, ImplicitAPI):
8412
9809
  fetches historical positions
8413
9810
 
8414
9811
  https://www.bitget.com/api-doc/contract/position/Get-History-Position
9812
+ https://www.bitget.com/api-doc/uta/trade/Get-Position-History
8415
9813
 
8416
9814
  :param str[] [symbols]: unified contract symbols
8417
9815
  :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
8418
9816
  :param int [limit]: the maximum amount of records to fetch, default=20, max=100
8419
9817
  :param dict params: extra parameters specific to the exchange api endpoint
8420
9818
  :param int [params.until]: timestamp in ms of the latest position to fetch, max range for params["until"] - since is 3 months
8421
-
8422
- EXCHANGE SPECIFIC PARAMETERS
8423
9819
  :param str [params.productType]: USDT-FUTURES(default), COIN-FUTURES, USDC-FUTURES, SUSDT-FUTURES, SCOIN-FUTURES, or SUSDC-FUTURES
9820
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8424
9821
  :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
8425
9822
  """
8426
9823
  self.load_markets()
8427
- until = self.safe_integer(params, 'until')
8428
- params = self.omit(params, 'until')
8429
9824
  request: dict = {}
9825
+ market = None
9826
+ productType = None
9827
+ uta = None
9828
+ response = None
8430
9829
  if symbols is not None:
8431
9830
  symbolsLength = len(symbols)
8432
9831
  if symbolsLength > 0:
@@ -8436,40 +9835,77 @@ class bitget(Exchange, ImplicitAPI):
8436
9835
  request['startTime'] = since
8437
9836
  if limit is not None:
8438
9837
  request['limit'] = limit
8439
- if until is not None:
8440
- request['endTime'] = until
8441
- response = self.privateMixGetV2MixPositionHistoryPosition(self.extend(request, params))
8442
- #
8443
- # {
8444
- # code: '00000',
8445
- # msg: 'success',
8446
- # requestTime: '1712794148791',
8447
- # data: {
8448
- # list: [
8449
- # {
8450
- # symbol: 'XRPUSDT',
8451
- # marginCoin: 'USDT',
8452
- # holdSide: 'long',
8453
- # openAvgPrice: '0.64967',
8454
- # closeAvgPrice: '0.58799',
8455
- # marginMode: 'isolated',
8456
- # openTotalPos: '10',
8457
- # closeTotalPos: '10',
8458
- # pnl: '-0.62976205',
8459
- # netProfit: '-0.65356802',
8460
- # totalFunding: '-0.01638',
8461
- # openFee: '-0.00389802',
8462
- # closeFee: '-0.00352794',
8463
- # ctime: '1709590322199',
8464
- # utime: '1709667583395'
8465
- # },
8466
- # ...
8467
- # ]
8468
- # }
8469
- # }
8470
- #
8471
- data = self.safe_dict(response, 'data')
8472
- responseList = self.safe_list(data, 'list')
9838
+ request, params = self.handle_until_option('endTime', request, params)
9839
+ productType, params = self.handle_product_type_and_params(market, params)
9840
+ uta, params = self.handle_option_and_params(params, 'fetchPositionsHistory', 'uta', False)
9841
+ if uta:
9842
+ request['category'] = productType
9843
+ response = self.privateUtaGetV3PositionHistoryPosition(self.extend(request, params))
9844
+ #
9845
+ # {
9846
+ # "code": "00000",
9847
+ # "msg": "success",
9848
+ # "requestTime": 1751020950427,
9849
+ # "data": {
9850
+ # "list": [
9851
+ # {
9852
+ # "positionId": "1322441328637100049",
9853
+ # "category": "USDT-FUTURES",
9854
+ # "symbol": "BTCUSDT",
9855
+ # "marginCoin": "USDT",
9856
+ # "holdMode": "hedge_mode",
9857
+ # "posSide": "long",
9858
+ # "marginMode": "crossed",
9859
+ # "openPriceAvg": "107003.7",
9860
+ # "closePriceAvg": "107005.4",
9861
+ # "openTotalPos": "0.0001",
9862
+ # "closeTotalPos": "0.0001",
9863
+ # "cumRealisedPnl": "0.00017",
9864
+ # "netProfit": "-0.01267055",
9865
+ # "totalFunding": "0",
9866
+ # "openFeeTotal": "-0.00642022",
9867
+ # "closeFeeTotal": "-0.00642032",
9868
+ # "createdTime": "1751020503195",
9869
+ # "updatedTime": "1751020520458"
9870
+ # },
9871
+ # ],
9872
+ # "cursor": "1322440134158041089"
9873
+ # }
9874
+ # }
9875
+ #
9876
+ else:
9877
+ response = self.privateMixGetV2MixPositionHistoryPosition(self.extend(request, params))
9878
+ #
9879
+ # {
9880
+ # code: '00000',
9881
+ # msg: 'success',
9882
+ # requestTime: '1712794148791',
9883
+ # data: {
9884
+ # list: [
9885
+ # {
9886
+ # symbol: 'XRPUSDT',
9887
+ # marginCoin: 'USDT',
9888
+ # holdSide: 'long',
9889
+ # openAvgPrice: '0.64967',
9890
+ # closeAvgPrice: '0.58799',
9891
+ # marginMode: 'isolated',
9892
+ # openTotalPos: '10',
9893
+ # closeTotalPos: '10',
9894
+ # pnl: '-0.62976205',
9895
+ # netProfit: '-0.65356802',
9896
+ # totalFunding: '-0.01638',
9897
+ # openFee: '-0.00389802',
9898
+ # closeFee: '-0.00352794',
9899
+ # ctime: '1709590322199',
9900
+ # utime: '1709667583395'
9901
+ # },
9902
+ # ...
9903
+ # ]
9904
+ # }
9905
+ # }
9906
+ #
9907
+ data = self.safe_dict(response, 'data', {})
9908
+ responseList = self.safe_list(data, 'list', [])
8473
9909
  positions = self.parse_positions(responseList, symbols, params)
8474
9910
  return self.filter_by_since_limit(positions, since, limit)
8475
9911
 
@@ -8741,9 +10177,11 @@ class bitget(Exchange, ImplicitAPI):
8741
10177
  fetch the current funding rate interval
8742
10178
 
8743
10179
  https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
10180
+ https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
8744
10181
 
8745
10182
  :param str symbol: unified market symbol
8746
10183
  :param dict [params]: extra parameters specific to the exchange API endpoint
10184
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
8747
10185
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
8748
10186
  """
8749
10187
  self.load_markets()
@@ -8752,23 +10190,46 @@ class bitget(Exchange, ImplicitAPI):
8752
10190
  productType, params = self.handle_product_type_and_params(market, params)
8753
10191
  request: dict = {
8754
10192
  'symbol': market['id'],
8755
- 'productType': productType,
8756
10193
  }
8757
- response = self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
8758
- #
8759
- # {
8760
- # "code": "00000",
8761
- # "msg": "success",
8762
- # "requestTime": 1727930153888,
8763
- # "data": [
8764
- # {
8765
- # "symbol": "BTCUSDT",
8766
- # "nextFundingTime": "1727942400000",
8767
- # "ratePeriod": "8"
8768
- # }
8769
- # ]
8770
- # }
8771
- #
10194
+ response = None
10195
+ uta = None
10196
+ uta, params = self.handle_option_and_params(params, 'fetchFundingInterval', 'uta', False)
10197
+ if uta:
10198
+ response = self.publicUtaGetV3MarketCurrentFundRate(self.extend(request, params))
10199
+ #
10200
+ # {
10201
+ # "code": "00000",
10202
+ # "msg": "success",
10203
+ # "requestTime": 1752880157959,
10204
+ # "data": [
10205
+ # {
10206
+ # "symbol": "BTCUSDT",
10207
+ # "fundingRate": "0.0001",
10208
+ # "fundingRateInterval": "8",
10209
+ # "nextUpdate": "1752883200000",
10210
+ # "minFundingRate": "-0.003",
10211
+ # "maxFundingRate": "0.003"
10212
+ # }
10213
+ # ]
10214
+ # }
10215
+ #
10216
+ else:
10217
+ request['productType'] = productType
10218
+ response = self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
10219
+ #
10220
+ # {
10221
+ # "code": "00000",
10222
+ # "msg": "success",
10223
+ # "requestTime": 1727930153888,
10224
+ # "data": [
10225
+ # {
10226
+ # "symbol": "BTCUSDT",
10227
+ # "nextFundingTime": "1727942400000",
10228
+ # "ratePeriod": "8"
10229
+ # }
10230
+ # ]
10231
+ # }
10232
+ #
8772
10233
  data = self.safe_list(response, 'data', [])
8773
10234
  first = self.safe_dict(data, 0, {})
8774
10235
  return self.parse_funding_rate(first, market)
@@ -8928,7 +10389,7 @@ class bitget(Exchange, ImplicitAPI):
8928
10389
  if method == 'POST':
8929
10390
  headers['Content-Type'] = 'application/json'
8930
10391
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
8931
- if sandboxMode and (path != 'v2/public/time'):
10392
+ if sandboxMode and (path != 'v2/public/time') and (path != 'v3/market/current-fund-rate'):
8932
10393
  # https://github.com/ccxt/ccxt/issues/25252#issuecomment-2662742336
8933
10394
  if headers is None:
8934
10395
  headers = {}