<?php

namespace ccxt\async;

// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code

use Exception; // a common import
use ccxt\async\abstract\bitget as Exchange;
use ccxt\ExchangeError;
use ccxt\ArgumentsRequired;
use ccxt\BadRequest;
use ccxt\BadSymbol;
use ccxt\InvalidOrder;
use ccxt\OrderNotFound;
use ccxt\NotSupported;
use ccxt\Precise;
use \React\Async;
use \React\Promise;
use \React\Promise\PromiseInterface;

class bitget extends Exchange {

    public function describe(): mixed {
        return $this->deep_extend(parent::describe(), array(
            'id' => 'bitget',
            'name' => 'Bitget',
            'countries' => array( 'SG' ),
            'version' => 'v2',
            'rateLimit' => 50, // up to 3000 requests per 5 minutes ≈ 600 requests per minute ≈ 10 requests per second ≈ 100 ms
            'certified' => true,
            'pro' => true,
            'has' => array(
                'CORS' => null,
                'spot' => true,
                'margin' => true,
                'swap' => true,
                'future' => true,
                'option' => false,
                'addMargin' => true,
                'borrowCrossMargin' => true,
                'borrowIsolatedMargin' => true,
                'cancelAllOrders' => true,
                'cancelOrder' => true,
                'cancelOrders' => true,
                'closeAllPositions' => true,
                'closePosition' => true,
                'createConvertTrade' => true,
                'createDepositAddress' => false,
                'createMarketBuyOrderWithCost' => true,
                'createMarketOrderWithCost' => false,
                'createMarketSellOrderWithCost' => false,
                'createOrder' => true,
                'createOrders' => true,
                'createOrderWithTakeProfitAndStopLoss' => true,
                'createPostOnlyOrder' => true,
                'createReduceOnlyOrder' => false,
                'createStopLimitOrder' => true,
                'createStopLossOrder' => true,
                'createStopMarketOrder' => true,
                'createStopOrder' => true,
                'createTakeProfitOrder' => true,
                'createTrailingAmountOrder' => false,
                'createTrailingPercentOrder' => true,
                'createTriggerOrder' => true,
                'editOrder' => true,
                'fetchAccounts' => false,
                'fetchBalance' => true,
                'fetchBorrowInterest' => true,
                'fetchBorrowRateHistories' => false,
                'fetchBorrowRateHistory' => false,
                'fetchCanceledAndClosedOrders' => true,
                'fetchCanceledOrders' => true,
                'fetchClosedOrders' => true,
                'fetchConvertCurrencies' => true,
                'fetchConvertQuote' => true,
                'fetchConvertTrade' => false,
                'fetchConvertTradeHistory' => true,
                'fetchCrossBorrowRate' => true,
                'fetchCrossBorrowRates' => false,
                'fetchCurrencies' => true,
                'fetchDeposit' => false,
                'fetchDepositAddress' => true,
                'fetchDepositAddresses' => false,
                'fetchDepositAddressesByNetwork' => false,
                'fetchDeposits' => true,
                'fetchDepositsWithdrawals' => false,
                'fetchDepositWithdrawFee' => 'emulated',
                'fetchDepositWithdrawFees' => true,
                'fetchFundingHistory' => true,
                'fetchFundingInterval' => true,
                'fetchFundingIntervals' => false,
                'fetchFundingRate' => true,
                'fetchFundingRateHistory' => true,
                'fetchFundingRates' => true,
                'fetchIndexOHLCV' => true,
                'fetchIsolatedBorrowRate' => true,
                'fetchIsolatedBorrowRates' => false,
                'fetchLedger' => true,
                'fetchLeverage' => true,
                'fetchLeverageTiers' => false,
                'fetchLiquidations' => false,
                'fetchLongShortRatio' => false,
                'fetchLongShortRatioHistory' => true,
                'fetchMarginAdjustmentHistory' => false,
                'fetchMarginMode' => true,
                'fetchMarketLeverageTiers' => true,
                'fetchMarkets' => true,
                'fetchMarkOHLCV' => true,
                'fetchMarkPrice' => true,
                'fetchMyLiquidations' => true,
                'fetchMyTrades' => true,
                'fetchOHLCV' => true,
                'fetchOpenInterest' => true,
                'fetchOpenInterestHistory' => false,
                'fetchOpenOrders' => true,
                'fetchOrder' => true,
                'fetchOrderBook' => true,
                'fetchOrderBooks' => false,
                'fetchOrders' => false,
                'fetchOrderTrades' => false,
                'fetchPosition' => true,
                'fetchPositionHistory' => 'emulated',
                'fetchPositionMode' => false,
                'fetchPositions' => true,
                'fetchPositionsHistory' => true,
                'fetchPositionsRisk' => false,
                'fetchPremiumIndexOHLCV' => false,
                'fetchStatus' => false,
                'fetchTicker' => true,
                'fetchTickers' => true,
                'fetchTime' => true,
                'fetchTrades' => true,
                'fetchTradingFee' => true,
                'fetchTradingFees' => true,
                'fetchTransactions' => false,
                'fetchTransfer' => false,
                'fetchTransfers' => true,
                'fetchWithdrawAddresses' => false,
                'fetchWithdrawal' => false,
                'fetchWithdrawals' => true,
                'reduceMargin' => true,
                'repayCrossMargin' => true,
                'repayIsolatedMargin' => true,
                'setLeverage' => true,
                'setMargin' => false,
                'setMarginMode' => true,
                'setPositionMode' => true,
                'signIn' => false,
                'transfer' => true,
                'withdraw' => true,
            ),
            'timeframes' => array(
                '1m' => '1m',
                '3m' => '3m',
                '5m' => '5m',
                '15m' => '15m',
                '30m' => '30m',
                '1h' => '1h',
                '2h' => '2h',
                '4h' => '4h',
                '6h' => '6h',
                '12h' => '12h',
                '1d' => '1d',
                '3d' => '3d',
                '1w' => '1w',
                '1M' => '1m',
            ),
            'hostname' => 'bitget.com',
            'urls' => array(
                'logo' => 'https://github.com/user-attachments/assets/fbaa10cc-a277-441d-a5b7-997dd9a87658',
                'api' => array(
                    'spot' => 'https://api.{hostname}',
                    'mix' => 'https://api.{hostname}',
                    'user' => 'https://api.{hostname}',
                    'p2p' => 'https://api.{hostname}',
                    'broker' => 'https://api.{hostname}',
                    'margin' => 'https://api.{hostname}',
                    'common' => 'https://api.{hostname}',
                    'tax' => 'https://api.{hostname}',
                    'convert' => 'https://api.{hostname}',
                    'copy' => 'https://api.{hostname}',
                    'earn' => 'https://api.{hostname}',
                    'uta' => 'https://api.{hostname}',
                ),
                'www' => 'https://www.bitget.com',
                'doc' => array(
                    'https://www.bitget.com/api-doc/common/intro',
                    'https://www.bitget.com/api-doc/spot/intro',
                    'https://www.bitget.com/api-doc/contract/intro',
                    'https://www.bitget.com/api-doc/broker/intro',
                    'https://www.bitget.com/api-doc/margin/intro',
                    'https://www.bitget.com/api-doc/copytrading/intro',
                    'https://www.bitget.com/api-doc/earn/intro',
                    'https://bitgetlimited.github.io/apidoc/en/mix',
                    'https://bitgetlimited.github.io/apidoc/en/spot',
                    'https://bitgetlimited.github.io/apidoc/en/broker',
                    'https://bitgetlimited.github.io/apidoc/en/margin',
                ),
                'fees' => 'https://www.bitget.cc/zh-CN/rate?tab=1',
                'referral' => 'https://www.bitget.com/expressly?languageType=0&channelCode=ccxt&vipCode=tg9j',
            ),
            'api' => array(
                'public' => array(
                    'common' => array(
                        'get' => array(
                            'v2/public/annoucements' => 1,
                            'v2/public/time' => 1,
                        ),
                    ),
                    'spot' => array(
                        'get' => array(
                            'spot/v1/notice/queryAllNotices' => 1, // 20 times/1s (IP) => 20/20 = 1
                            'spot/v1/public/time' => 1,
                            'spot/v1/public/currencies' => 6.6667, // 3 times/1s (IP) => 20/3 = 6.6667
                            'spot/v1/public/products' => 1,
                            'spot/v1/public/product' => 1,
                            'spot/v1/market/ticker' => 1,
                            'spot/v1/market/tickers' => 1,
                            'spot/v1/market/fills' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'spot/v1/market/fills-history' => 2,
                            'spot/v1/market/candles' => 1,
                            'spot/v1/market/depth' => 1,
                            'spot/v1/market/spot-vip-level' => 2,
                            'spot/v1/market/merge-depth' => 1,
                            'spot/v1/market/history-candles' => 1,
                            'spot/v1/public/loan/coinInfos' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'spot/v1/public/loan/hour-interest' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'v2/spot/public/coins' => 6.6667,
                            'v2/spot/public/symbols' => 1,
                            'v2/spot/market/vip-fee-rate' => 2,
                            'v2/spot/market/tickers' => 1,
                            'v2/spot/market/merge-depth' => 1,
                            'v2/spot/market/orderbook' => 1,
                            'v2/spot/market/candles' => 1,
                            'v2/spot/market/history-candles' => 1,
                            'v2/spot/market/fills' => 2,
                            'v2/spot/market/fills-history' => 2,
                        ),
                    ),
                    'mix' => array(
                        'get' => array(
                            'mix/v1/market/contracts' => 1,
                            'mix/v1/market/depth' => 1,
                            'mix/v1/market/ticker' => 1,
                            'mix/v1/market/tickers' => 1,
                            'mix/v1/market/contract-vip-level' => 2,
                            'mix/v1/market/fills' => 1,
                            'mix/v1/market/fills-history' => 2,
                            'mix/v1/market/candles' => 1,
                            'mix/v1/market/index' => 1,
                            'mix/v1/market/funding-time' => 1,
                            'mix/v1/market/history-fundRate' => 1,
                            'mix/v1/market/current-fundRate' => 1,
                            'mix/v1/market/open-interest' => 1,
                            'mix/v1/market/mark-price' => 1,
                            'mix/v1/market/symbol-leverage' => 1,
                            'mix/v1/market/queryPositionLever' => 1,
                            'mix/v1/market/open-limit' => 1,
                            'mix/v1/market/history-candles' => 1,
                            'mix/v1/market/history-index-candles' => 1,
                            'mix/v1/market/history-mark-candles' => 1,
                            'mix/v1/market/merge-depth' => 1,
                            'v2/mix/market/vip-fee-rate' => 2,
                            'v2/mix/market/merge-depth' => 1,
                            'v2/mix/market/ticker' => 1,
                            'v2/mix/market/tickers' => 1,
                            'v2/mix/market/fills' => 1,
                            'v2/mix/market/fills-history' => 2,
                            'v2/mix/market/candles' => 1,
                            'v2/mix/market/history-candles' => 1,
                            'v2/mix/market/history-index-candles' => 1,
                            'v2/mix/market/history-mark-candles' => 1,
                            'v2/mix/market/open-interest' => 1,
                            'v2/mix/market/funding-time' => 1,
                            'v2/mix/market/symbol-price' => 1,
                            'v2/mix/market/history-fund-rate' => 1,
                            'v2/mix/market/current-fund-rate' => 1,
                            'v2/mix/market/contracts' => 1,
                            'v2/mix/market/query-position-lever' => 2,
                            'v2/mix/market/account-long-short' => 20,
                        ),
                    ),
                    'margin' => array(
                        'get' => array(
                            'margin/v1/cross/public/interestRateAndLimit' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'margin/v1/isolated/public/interestRateAndLimit' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'margin/v1/cross/public/tierData' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'margin/v1/isolated/public/tierData' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'margin/v1/public/currencies' => 1, // 20 times/1s (IP) => 20/20 = 1
                            'v2/margin/currencies' => 2,
                            'v2/margin/market/long-short-ratio' => 20,
                        ),
                    ),
                    'earn' => array(
                        'get' => array(
                            'v2/earn/loan/public/coinInfos' => 2,
                            'v2/earn/loan/public/hour-interest' => 2,
                        ),
                    ),
                    'uta' => array(
                        'get' => array(
                            'v3/market/instruments' => 1,
                            'v3/market/tickers' => 1,
                            'v3/market/orderbook' => 1,
                            'v3/market/fills' => 1,
                            'v3/market/open-interest' => 1,
                            'v3/market/candles' => 1,
                            'v3/market/history-candles' => 1,
                            'v3/market/current-fund-rate' => 1,
                            'v3/market/history-fund-rate' => 1,
                            'v3/market/risk-reserve' => 1,
                            'v3/market/discount-rate' => 1,
                            'v3/market/margin-loans' => 1,
                            'v3/market/position-tier' => 1,
                            'v3/market/oi-limit' => 2,
                        ),
                    ),
                ),
                'private' => array(
                    'spot' => array(
                        'get' => array(
                            'spot/v1/wallet/deposit-address' => 4,
                            'spot/v1/wallet/withdrawal-list' => 1,
                            'spot/v1/wallet/deposit-list' => 1,
                            'spot/v1/account/getInfo' => 20,
                            'spot/v1/account/assets' => 2,
                            'spot/v1/account/assets-lite' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/account/transferRecords' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'spot/v1/convert/currencies' => 2,
                            'spot/v1/convert/convert-record' => 2,
                            'spot/v1/loan/ongoing-orders' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/repay-history' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/revise-history' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/borrow-history' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/debts' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/spot/trade/orderInfo' => 1,
                            'v2/spot/trade/unfilled-orders' => 1,
                            'v2/spot/trade/history-orders' => 1,
                            'v2/spot/trade/fills' => 2,
                            'v2/spot/trade/current-plan-order' => 1,
                            'v2/spot/trade/history-plan-order' => 1,
                            'v2/spot/account/info' => 20,
                            'v2/spot/account/assets' => 2,
                            'v2/spot/account/subaccount-assets' => 2,
                            'v2/spot/account/bills' => 2,
                            'v2/spot/account/transferRecords' => 1,
                            'v2/account/funding-assets' => 2,
                            'v2/account/bot-assets' => 2,
                            'v2/account/all-account-balance' => 20,
                            'v2/spot/wallet/deposit-address' => 2,
                            'v2/spot/wallet/deposit-records' => 2,
                            'v2/spot/wallet/withdrawal-records' => 2,
                        ),
                        'post' => array(
                            'spot/v1/wallet/transfer' => 4,
                            'spot/v1/wallet/transfer-v2' => 4,
                            'spot/v1/wallet/subTransfer' => 10,
                            'spot/v1/wallet/withdrawal' => 4,
                            'spot/v1/wallet/withdrawal-v2' => 4,
                            'spot/v1/wallet/withdrawal-inner' => 4,
                            'spot/v1/wallet/withdrawal-inner-v2' => 4,
                            'spot/v1/account/sub-account-spot-assets' => 200,
                            'spot/v1/account/bills' => 2,
                            'spot/v1/trade/orders' => 2,
                            'spot/v1/trade/batch-orders' => 4,
                            'spot/v1/trade/cancel-order' => 2,
                            'spot/v1/trade/cancel-order-v2' => 2,
                            'spot/v1/trade/cancel-symbol-order' => 2,
                            'spot/v1/trade/cancel-batch-orders' => 4,
                            'spot/v1/trade/cancel-batch-orders-v2' => 4,
                            'spot/v1/trade/orderInfo' => 1,
                            'spot/v1/trade/open-orders' => 1,
                            'spot/v1/trade/history' => 1,
                            'spot/v1/trade/fills' => 1,
                            'spot/v1/plan/placePlan' => 1,
                            'spot/v1/plan/modifyPlan' => 1,
                            'spot/v1/plan/cancelPlan' => 1,
                            'spot/v1/plan/currentPlan' => 1,
                            'spot/v1/plan/historyPlan' => 1,
                            'spot/v1/plan/batchCancelPlan' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/convert/quoted-price' => 4,
                            'spot/v1/convert/trade' => 4,
                            'spot/v1/loan/borrow' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/repay' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/loan/revise-pledge' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/orderCurrentList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/orderHistoryList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/closeTrackingOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/updateTpsl' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/followerEndOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/order/spotInfoList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/config/getTraderSettings' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/config/getFollowerSettings' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/user/myTraders' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/config/setFollowerConfig' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/user/myFollowers' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/config/setProductCode' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/user/removeTrader' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/getRemovableFollower' => 2,
                            'spot/v1/trace/user/removeFollower' => 2,
                            'spot/v1/trace/profit/totalProfitInfo' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/profit/totalProfitList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/profit/profitHisList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/profit/profitHisDetailList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/profit/waitProfitDetailList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'spot/v1/trace/user/getTraderInfo' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/spot/trade/place-order' => 2,
                            'v2/spot/trade/cancel-order' => 2,
                            'v2/spot/trade/batch-orders' => 20,
                            'v2/spot/trade/batch-cancel-order' => 2,
                            'v2/spot/trade/cancel-symbol-order' => 4,
                            'v2/spot/trade/place-plan-order' => 1,
                            'v2/spot/trade/modify-plan-order' => 1,
                            'v2/spot/trade/cancel-plan-order' => 1,
                            'v2/spot/trade/batch-cancel-plan-order' => 2,
                            'v2/spot/wallet/transfer' => 2,
                            'v2/spot/wallet/subaccount-transfer' => 2,
                            'v2/spot/wallet/withdrawal' => 2,
                            'v2/spot/wallet/cancel-withdrawal' => 2,
                            'v2/spot/wallet/modify-deposit-account' => 2,
                        ),
                    ),
                    'mix' => array(
                        'get' => array(
                            'mix/v1/account/account' => 2,
                            'mix/v1/account/accounts' => 2,
                            'mix/v1/position/singlePosition' => 2,
                            'mix/v1/position/singlePosition-v2' => 2,
                            'mix/v1/position/allPosition' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/position/allPosition-v2' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/position/history-position' => 1,
                            'mix/v1/account/accountBill' => 2,
                            'mix/v1/account/accountBusinessBill' => 4,
                            'mix/v1/order/current' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/order/marginCoinCurrent' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/order/history' => 2,
                            'mix/v1/order/historyProductType' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/order/detail' => 2,
                            'mix/v1/order/fills' => 2,
                            'mix/v1/order/allFills' => 2,
                            'mix/v1/plan/currentPlan' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/plan/historyPlan' => 2,
                            'mix/v1/trace/currentTrack' => 2,
                            'mix/v1/trace/followerOrder' => 2,
                            'mix/v1/trace/followerHistoryOrders' => 2,
                            'mix/v1/trace/historyTrack' => 2,
                            'mix/v1/trace/summary' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/trace/profitSettleTokenIdGroup' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/trace/profitDateGroupList' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/trade/profitDateList' => 2,
                            'mix/v1/trace/waitProfitDateList' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/trace/traderSymbols' => 1, // 20 times/1s (UID) => 20/20 = 1
                            'mix/v1/trace/traderList' => 2,
                            'mix/v1/trace/traderDetail' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/queryTraceConfig' => 2,
                            'v2/mix/account/account' => 2,
                            'v2/mix/account/accounts' => 2,
                            'v2/mix/account/sub-account-assets' => 200,
                            'v2/mix/account/open-count' => 2,
                            'v2/mix/account/bill' => 2,
                            'v2/mix/market/query-position-lever' => 2,
                            'v2/mix/position/single-position' => 2,
                            'v2/mix/position/all-position' => 4,
                            'v2/mix/position/history-position' => 1,
                            'v2/mix/order/detail' => 2,
                            'v2/mix/order/fills' => 2,
                            'v2/mix/order/fill-history' => 2,
                            'v2/mix/order/orders-pending' => 2,
                            'v2/mix/order/orders-history' => 2,
                            'v2/mix/order/orders-plan-pending' => 2,
                            'v2/mix/order/orders-plan-history' => 2,
                            'v2/mix/market/position-long-short' => 20,
                        ),
                        'post' => array(
                            'mix/v1/account/sub-account-contract-assets' => 200, // 0.1 times/1s (UID) => 20/0.1 = 200
                            'mix/v1/account/open-count' => 1,
                            'mix/v1/account/setLeverage' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/account/setMargin' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/account/setMarginMode' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/account/setPositionMode' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/order/placeOrder' => 2,
                            'mix/v1/order/batch-orders' => 2,
                            'mix/v1/order/cancel-order' => 2,
                            'mix/v1/order/cancel-batch-orders' => 2,
                            'mix/v1/order/modifyOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/order/cancel-symbol-orders' => 2,
                            'mix/v1/order/cancel-all-orders' => 2,
                            'mix/v1/order/close-all-positions' => 20,
                            'mix/v1/plan/placePlan' => 2,
                            'mix/v1/plan/modifyPlan' => 2,
                            'mix/v1/plan/modifyPlanPreset' => 2,
                            'mix/v1/plan/placeTPSL' => 2,
                            'mix/v1/plan/placeTrailStop' => 2,
                            'mix/v1/plan/placePositionsTPSL' => 2,
                            'mix/v1/plan/modifyTPSLPlan' => 2,
                            'mix/v1/plan/cancelPlan' => 2,
                            'mix/v1/plan/cancelSymbolPlan' => 2,
                            'mix/v1/plan/cancelAllPlan' => 2,
                            'mix/v1/trace/closeTrackOrder' => 2,
                            'mix/v1/trace/modifyTPSL' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/closeTrackOrderBySymbol' => 2,
                            'mix/v1/trace/setUpCopySymbols' => 2,
                            'mix/v1/trace/followerSetBatchTraceConfig' => 2,
                            'mix/v1/trace/followerCloseByTrackingNo' => 2,
                            'mix/v1/trace/followerCloseByAll' => 2,
                            'mix/v1/trace/followerSetTpsl' => 2,
                            'mix/v1/trace/cancelCopyTrader' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'mix/v1/trace/traderUpdateConfig' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/myTraderList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/myFollowerList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/removeFollower' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/public/getFollowerConfig' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/report/order/historyList' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'mix/v1/trace/report/order/currentList' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'mix/v1/trace/queryTraderTpslRatioConfig' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'mix/v1/trace/traderUpdateTpslRatioConfig' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/mix/account/set-leverage' => 4,
                            'v2/mix/account/set-margin' => 4,
                            'v2/mix/account/set-margin-mode' => 4,
                            'v2/mix/account/set-position-mode' => 4,
                            'v2/mix/order/place-order' => 2,
                            'v2/mix/order/click-backhand' => 20,
                            'v2/mix/order/batch-place-order' => 20,
                            'v2/mix/order/modify-order' => 2,
                            'v2/mix/order/cancel-order' => 2,
                            'v2/mix/order/batch-cancel-orders' => 2,
                            'v2/mix/order/close-positions' => 20,
                            'v2/mix/order/place-tpsl-order' => 2,
                            'v2/mix/order/place-plan-order' => 2,
                            'v2/mix/order/modify-tpsl-order' => 2,
                            'v2/mix/order/modify-plan-order' => 2,
                            'v2/mix/order/cancel-plan-order' => 2,
                        ),
                    ),
                    'user' => array(
                        'get' => array(
                            'user/v1/fee/query' => 2,
                            'user/v1/sub/virtual-list' => 2,
                            'user/v1/sub/virtual-api-list' => 2,
                            'user/v1/tax/spot-record' => 1,
                            'user/v1/tax/future-record' => 1,
                            'user/v1/tax/margin-record' => 1,
                            'user/v1/tax/p2p-record' => 1,
                            'v2/user/virtual-subaccount-list' => 2,
                            'v2/user/virtual-subaccount-apikey-list' => 2,
                        ),
                        'post' => array(
                            'user/v1/sub/virtual-create' => 4,
                            'user/v1/sub/virtual-modify' => 4,
                            'user/v1/sub/virtual-api-batch-create' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'user/v1/sub/virtual-api-create' => 4,
                            'user/v1/sub/virtual-api-modify' => 4,
                            'v2/user/create-virtual-subaccount' => 4,
                            'v2/user/modify-virtual-subaccount' => 4,
                            'v2/user/batch-create-subaccount-and-apikey' => 20,
                            'v2/user/create-virtual-subaccount-apikey' => 4,
                            'v2/user/modify-virtual-subaccount-apikey' => 4,
                        ),
                    ),
                    'p2p' => array(
                        'get' => array(
                            'p2p/v1/merchant/merchantList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'p2p/v1/merchant/merchantInfo' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'p2p/v1/merchant/advList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'p2p/v1/merchant/orderList' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/p2p/merchantList' => 2,
                            'v2/p2p/merchantInfo' => 2,
                            'v2/p2p/orderList' => 2,
                            'v2/p2p/advList' => 2,
                        ),
                    ),
                    'broker' => array(
                        'get' => array(
                            'broker/v1/account/info' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/sub-list' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'broker/v1/account/sub-email' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'broker/v1/account/sub-spot-assets' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/sub-future-assets' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/subaccount-transfer' => 1, // unknown
                            'broker/v1/account/subaccount-deposit' => 1, // unknown
                            'broker/v1/account/subaccount-withdrawal' => 1, // unknown
                            'broker/v1/account/sub-api-list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/broker/account/info' => 2,
                            'v2/broker/account/subaccount-list' => 20,
                            'v2/broker/account/subaccount-email' => 2,
                            'v2/broker/account/subaccount-spot-assets' => 2,
                            'v2/broker/account/subaccount-future-assets' => 2,
                            'v2/broker/manage/subaccount-apikey-list' => 2,
                        ),
                        'post' => array(
                            'broker/v1/account/sub-create' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'broker/v1/account/sub-modify' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'broker/v1/account/sub-modify-email' => 20, // 1 times/1s (UID) => 20/1 = 20
                            'broker/v1/account/sub-address' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/sub-withdrawal' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/sub-auto-transfer' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'broker/v1/account/sub-api-create' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'broker/v1/account/sub-api-modify' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/broker/account/modify-subaccount-email' => 2,
                            'v2/broker/account/create-subaccount' => 20,
                            'v2/broker/account/modify-subaccount' => 20,
                            'v2/broker/account/subaccount-address' => 2,
                            'v2/broker/account/subaccount-withdrawal' => 2,
                            'v2/broker/account/set-subaccount-autotransfer' => 2,
                            'v2/broker/manage/create-subaccount-apikey' => 2,
                            'v2/broker/manage/modify-subaccount-apikey' => 2,
                        ),
                    ),
                    'margin' => array(
                        'get' => array(
                            'margin/v1/cross/account/riskRate' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/maxTransferOutAmount' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/maxTransferOutAmount' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/order/openOrders' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/order/history' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/order/fills' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/loan/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/repay/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/interest/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/liquidation/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/fin/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/openOrders' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/history' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/fills' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/loan/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/repay/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/interest/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/liquidation/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/fin/list' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/assets' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'margin/v1/isolated/account/assets' => 2, // 10 times/1s (IP) => 20/10 = 2
                            'v2/margin/crossed/borrow-history' => 2,
                            'v2/margin/crossed/repay-history' => 2,
                            'v2/margin/crossed/interest-history' => 2,
                            'v2/margin/crossed/liquidation-history' => 2,
                            'v2/margin/crossed/financial-records' => 2,
                            'v2/margin/crossed/account/assets' => 2,
                            'v2/margin/crossed/account/risk-rate' => 2,
                            'v2/margin/crossed/account/max-borrowable-amount' => 2,
                            'v2/margin/crossed/account/max-transfer-out-amount' => 2,
                            'v2/margin/crossed/interest-rate-and-limit' => 2,
                            'v2/margin/crossed/tier-data' => 2,
                            'v2/margin/crossed/open-orders' => 2,
                            'v2/margin/crossed/history-orders' => 2,
                            'v2/margin/crossed/fills' => 2,
                            'v2/margin/isolated/borrow-history' => 2,
                            'v2/margin/isolated/repay-history' => 2,
                            'v2/margin/isolated/interest-history' => 2,
                            'v2/margin/isolated/liquidation-history' => 2,
                            'v2/margin/isolated/financial-records' => 2,
                            'v2/margin/isolated/account/assets' => 2,
                            'v2/margin/isolated/account/risk-rate' => 2,
                            'v2/margin/isolated/account/max-borrowable-amount' => 2,
                            'v2/margin/isolated/account/max-transfer-out-amount' => 2,
                            'v2/margin/isolated/interest-rate-and-limit' => 2,
                            'v2/margin/isolated/tier-data' => 2,
                            'v2/margin/isolated/open-orders' => 2,
                            'v2/margin/isolated/history-orders' => 2,
                            'v2/margin/isolated/fills' => 2,
                        ),
                        'post' => array(
                            'margin/v1/cross/account/borrow' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/borrow' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/repay' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/repay' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/riskRate' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/maxBorrowableAmount' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/maxBorrowableAmount' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/flashRepay' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/account/queryFlashRepayStatus' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/flashRepay' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/account/queryFlashRepayStatus' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/order/placeOrder' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'margin/v1/isolated/order/batchPlaceOrder' => 4, // 5 times/1s (UID) => 20/5 = 4
                            'margin/v1/isolated/order/cancelOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/isolated/order/batchCancelOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/placeOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/batchPlaceOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/cancelOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'margin/v1/cross/order/batchCancelOrder' => 2, // 10 times/1s (UID) => 20/10 = 2
                            'v2/margin/crossed/account/borrow' => 2,
                            'v2/margin/crossed/account/repay' => 2,
                            'v2/margin/crossed/account/flash-repay' => 2,
                            'v2/margin/crossed/account/query-flash-repay-status' => 2,
                            'v2/margin/crossed/place-order' => 2,
                            'v2/margin/crossed/batch-place-order' => 2,
                            'v2/margin/crossed/cancel-order' => 2,
                            'v2/margin/crossed/batch-cancel-order' => 2,
                            'v2/margin/isolated/account/borrow' => 2,
                            'v2/margin/isolated/account/repay' => 2,
                            'v2/margin/isolated/account/flash-repay' => 2,
                            'v2/margin/isolated/account/query-flash-repay-status' => 2,
                            'v2/margin/isolated/place-order' => 2,
                            'v2/margin/isolated/batch-place-order' => 2,
                            'v2/margin/isolated/cancel-order' => 2,
                            'v2/margin/isolated/batch-cancel-order' => 2,
                        ),
                    ),
                    'copy' => array(
                        'get' => array(
                            'v2/copy/mix-trader/order-current-track' => 2,
                            'v2/copy/mix-trader/order-history-track' => 2,
                            'v2/copy/mix-trader/order-total-detail' => 2,
                            'v2/copy/mix-trader/profit-history-summarys' => 1,
                            'v2/copy/mix-trader/profit-history-details' => 1,
                            'v2/copy/mix-trader/profit-details' => 1,
                            'v2/copy/mix-trader/profits-group-coin-date' => 1,
                            'v2/copy/mix-trader/config-query-symbols' => 1,
                            'v2/copy/mix-trader/config-query-followers' => 2,
                            'v2/copy/mix-follower/query-current-orders' => 2,
                            'v2/copy/mix-follower/query-history-orders' => 1,
                            'v2/copy/mix-follower/query-settings' => 2,
                            'v2/copy/mix-follower/query-traders' => 2,
                            'v2/copy/mix-follower/query-quantity-limit' => 2,
                            'v2/copy/mix-broker/query-traders' => 2,
                            'v2/copy/mix-broker/query-history-traces' => 2,
                            'v2/copy/mix-broker/query-current-traces' => 2,
                            'v2/copy/spot-trader/profit-summarys' => 2,
                            'v2/copy/spot-trader/profit-history-details' => 2,
                            'v2/copy/spot-trader/profit-details' => 2,
                            'v2/copy/spot-trader/order-total-detail' => 2,
                            'v2/copy/spot-trader/order-history-track' => 2,
                            'v2/copy/spot-trader/order-current-track' => 2,
                            'v2/copy/spot-trader/config-query-settings' => 2,
                            'v2/copy/spot-trader/config-query-followers' => 2,
                            'v2/copy/spot-follower/query-traders' => 2,
                            'v2/copy/spot-follower/query-trader-symbols' => 2,
                            'v2/copy/spot-follower/query-settings' => 2,
                            'v2/copy/spot-follower/query-history-orders' => 2,
                            'v2/copy/spot-follower/query-current-orders' => 2,
                        ),
                        'post' => array(
                            'v2/copy/mix-trader/order-modify-tpsl' => 2,
                            'v2/copy/mix-trader/order-close-positions' => 2,
                            'v2/copy/mix-trader/config-setting-symbols' => 2,
                            'v2/copy/mix-trader/config-setting-base' => 2,
                            'v2/copy/mix-trader/config-remove-follower' => 2,
                            'v2/copy/mix-follower/setting-tpsl' => 1,
                            'v2/copy/mix-follower/settings' => 2,
                            'v2/copy/mix-follower/close-positions' => 2,
                            'v2/copy/mix-follower/cancel-trader' => 4,
                            'v2/copy/spot-trader/order-modify-tpsl' => 2,
                            'v2/copy/spot-trader/order-close-tracking' => 2,
                            'v2/copy/spot-trader/config-setting-symbols' => 2,
                            'v2/copy/spot-trader/config-remove-follower' => 2,
                            'v2/copy/spot-follower/stop-order' => 2,
                            'v2/copy/spot-follower/settings' => 2,
                            'v2/copy/spot-follower/setting-tpsl' => 2,
                            'v2/copy/spot-follower/order-close-tracking' => 2,
                            'v2/copy/spot-follower/cancel-trader' => 2,
                        ),
                    ),
                    'tax' => array(
                        'get' => array(
                            'v2/tax/spot-record' => 20,
                            'v2/tax/future-record' => 20,
                            'v2/tax/margin-record' => 20,
                            'v2/tax/p2p-record' => 20,
                        ),
                    ),
                    'convert' => array(
                        'get' => array(
                            'v2/convert/currencies' => 2,
                            'v2/convert/quoted-price' => 2,
                            'v2/convert/convert-record' => 2,
                            'v2/convert/bgb-convert-coin-list' => 2,
                            'v2/convert/bgb-convert-records' => 2,
                        ),
                        'post' => array(
                            'v2/convert/trade' => 2,
                            'v2/convert/bgb-convert' => 2,
                        ),
                    ),
                    'earn' => array(
                        'get' => array(
                            'v2/earn/savings/product' => 2,
                            'v2/earn/savings/account' => 2,
                            'v2/earn/savings/assets' => 2,
                            'v2/earn/savings/records' => 2,
                            'v2/earn/savings/subscribe-info' => 2,
                            'v2/earn/savings/subscribe-result' => 2,
                            'v2/earn/savings/redeem-result' => 2,
                            'v2/earn/sharkfin/product' => 2,
                            'v2/earn/sharkfin/account' => 2,
                            'v2/earn/sharkfin/assets' => 2,
                            'v2/earn/sharkfin/records' => 2,
                            'v2/earn/sharkfin/subscribe-info' => 2,
                            'v2/earn/sharkfin/subscribe-result' => 4,
                            'v2/earn/loan/ongoing-orders' => 2,
                            'v2/earn/loan/repay-history' => 2,
                            'v2/earn/loan/revise-history' => 2,
                            'v2/earn/loan/borrow-history' => 2,
                            'v2/earn/loan/debts' => 2,
                            'v2/earn/loan/reduces' => 2,
                            'v2/earn/account/assets' => 2,
                        ),
                        'post' => array(
                            'v2/earn/savings/subscribe' => 2,
                            'v2/earn/savings/redeem' => 2,
                            'v2/earn/sharkfin/subscribe' => 2,
                            'v2/earn/loan/borrow' => 2,
                            'v2/earn/loan/repay' => 2,
                            'v2/earn/loan/revise-pledge' => 2,
                        ),
                    ),
                    'common' => array(
                        'get' => array(
                            'v2/common/trade-rate' => 2,
                        ),
                    ),
                    'uta' => array(
                        'get' => array(
                            'v3/account/assets' => 1,
                            'v3/account/settings' => 1,
                            'v3/account/deposit-records' => 2,
                            'v3/account/financial-records' => 1,
                            'v3/account/repayable-coins' => 2,
                            'v3/account/payment-coins' => 2,
                            'v3/account/convert-records' => 1,
                            'v3/account/transferable-coins' => 2,
                            'v3/account/sub-transfer-record' => 4,
                            'v3/ins-loan/transfered' => 6.6667,
                            'v3/ins-loan/symbols' => 6.6667,
                            'v3/ins-loan/risk-unit' => 6.6667,
                            'v3/ins-loan/repaid-history' => 6.6667,
                            'v3/ins-loan/product-infos' => 6.6667,
                            'v3/ins-loan/loan-order' => 6.6667,
                            'v3/ins-loan/ltv-convert' => 6.6667,
                            'v3/ins-loan/ensure-coins-convert' => 6.6667,
                            'v3/position/current-position' => 1,
                            'v3/position/history-position' => 1,
                            'v3/trade/order-info' => 1,
                            'v3/trade/unfilled-orders' => 1,
                            'v3/trade/unfilled-strategy-orders' => 1,
                            'v3/trade/history-orders' => 1,
                            'v3/trade/history-strategy-orders' => 1,
                            'v3/trade/fills' => 1,
                            'v3/user/sub-list' => 2,
                            'v3/user/sub-api-list' => 2,
                        ),
                        'post' => array(
                            'v3/account/set-leverage' => 2,
                            'v3/account/set-hold-mode' => 2,
                            'v3/account/repay' => 4,
                            'v3/account/transfer' => 4,
                            'v3/account/sub-transfer' => 4,
                            'v3/account/max-open-available' => 4,
                            'v3/ins-loan/bind-uid' => 6.6667,
                            'v3/trade/place-order' => 2,
                            'v3/trade/place-strategy-order' => 2,
                            'v3/trade/modify-order' => 2,
                            'v3/trade/modify-strategy-order' => 2,
                            'v3/trade/cancel-order' => 2,
                            'v3/trade/cancel-strategy-order' => 2,
                            'v3/trade/place-batch' => 4,
                            'v3/trade/batch-modify-order' => 2,
                            'v3/trade/cancel-batch' => 4,
                            'v3/trade/cancel-symbol-order' => 4,
                            'v3/trade/close-positions' => 4,
                            'v3/user/create-sub' => 2,
                            'v3/user/freeze-sub' => 2,
                            'v3/user/create-sub-api' => 2,
                            'v3/user/update-sub-api' => 2,
                            'v3/user/delete-sub-api' => 2,
                        ),
                    ),
                ),
            ),
            'fees' => array(
                'spot' => array(
                    'taker' => $this->parse_number('0.002'),
                    'maker' => $this->parse_number('0.002'),
                ),
                'swap' => array(
                    'taker' => $this->parse_number('0.0006'),
                    'maker' => $this->parse_number('0.0004'),
                ),
            ),
            'requiredCredentials' => array(
                'apiKey' => true,
                'secret' => true,
                'password' => true,
            ),
            'exceptions' => array(
                // http error codes
                // 400 Bad Request — Invalid request format
                // 401 Unauthorized — Invalid API Key
                // 403 Forbidden — You do not have access to the requested resource
                // 404 Not Found
                // 500 Internal Server Error — We had a problem with our server
                'exact' => array(
                    '1' => '\\ccxt\\ExchangeError', // array( "code" => 1, "message" => "System error" )
                    // undocumented
                    'failure to get a peer from the ring-balancer' => '\\ccxt\\ExchangeNotAvailable', // array( "message" => "failure to get a peer from the ring-balancer" )
                    '4010' => '\\ccxt\\PermissionDenied', // array( "code" => 4010, "message" => "For the security of your funds, withdrawals are not permitted within 24 hours after changing fund password  / mobile number / Google Authenticator settings " )
                    // common
                    // '0' => '\\ccxt\\ExchangeError', // 200 successful,when the order placement / cancellation / operation is successful
                    '4001' => '\\ccxt\\ExchangeError', // no data received in 30s
                    '4002' => '\\ccxt\\ExchangeError', // Buffer full. cannot write data
                    '40020' => '\\ccxt\\BadRequest', // array("code":"40020","msg":"Parameter orderId error","requestTime":1754305078588,"data":null)
                    // --------------------------------------------------------
                    '30001' => '\\ccxt\\AuthenticationError', // array( "code" => 30001, "message" => 'request header "OK_ACCESS_KEY" cannot be blank')
                    '30002' => '\\ccxt\\AuthenticationError', // array( "code" => 30002, "message" => 'request header "OK_ACCESS_SIGN" cannot be blank')
                    '30003' => '\\ccxt\\AuthenticationError', // array( "code" => 30003, "message" => 'request header "OK_ACCESS_TIMESTAMP" cannot be blank')
                    '30004' => '\\ccxt\\AuthenticationError', // array( "code" => 30004, "message" => 'request header "OK_ACCESS_PASSPHRASE" cannot be blank')
                    '30005' => '\\ccxt\\InvalidNonce', // array( "code" => 30005, "message" => "invalid OK_ACCESS_TIMESTAMP" )
                    '30006' => '\\ccxt\\AuthenticationError', // array( "code" => 30006, "message" => "invalid OK_ACCESS_KEY" )
                    '30007' => '\\ccxt\\BadRequest', // array( "code" => 30007, "message" => 'invalid Content_Type, please use "application/json" format')
                    '30008' => '\\ccxt\\RequestTimeout', // array( "code" => 30008, "message" => "timestamp request expired" )
                    '30009' => '\\ccxt\\ExchangeError', // array( "code" => 30009, "message" => "system error" )
                    '30010' => '\\ccxt\\AuthenticationError', // array( "code" => 30010, "message" => "API validation failed" )
                    '30011' => '\\ccxt\\PermissionDenied', // array( "code" => 30011, "message" => "invalid IP" )
                    '30012' => '\\ccxt\\AuthenticationError', // array( "code" => 30012, "message" => "invalid authorization" )
                    '30013' => '\\ccxt\\AuthenticationError', // array( "code" => 30013, "message" => "invalid sign" )
                    '30014' => '\\ccxt\\DDoSProtection', // array( "code" => 30014, "message" => "request too frequent" )
                    '30015' => '\\ccxt\\AuthenticationError', // array( "code" => 30015, "message" => 'request header "OK_ACCESS_PASSPHRASE" incorrect')
                    '30016' => '\\ccxt\\ExchangeError', // array( "code" => 30015, "message" => "you are using v1 apiKey, please use v1 endpoint. If you would like to use v3 endpoint, please subscribe to v3 apiKey" )
                    '30017' => '\\ccxt\\ExchangeError', // array( "code" => 30017, "message" => "apikey's broker id does not match" )
                    '30018' => '\\ccxt\\ExchangeError', // array( "code" => 30018, "message" => "apikey's domain does not match" )
                    '30019' => '\\ccxt\\ExchangeNotAvailable', // array( "code" => 30019, "message" => "Api is offline or unavailable" )
                    '30020' => '\\ccxt\\BadRequest', // array( "code" => 30020, "message" => "body cannot be blank" )
                    '30021' => '\\ccxt\\BadRequest', // array( "code" => 30021, "message" => "Json data format error" ), array( "code" => 30021, "message" => "json data format error" )
                    '30022' => '\\ccxt\\PermissionDenied', // array( "code" => 30022, "message" => "Api has been frozen" )
                    '30023' => '\\ccxt\\BadRequest', // array( "code" => 30023, "message" => "{0} parameter cannot be blank" )
                    '30024' => '\\ccxt\\BadSymbol', // array("code":30024,"message":"\"instrument_id\" is an invalid parameter")
                    '30025' => '\\ccxt\\BadRequest', // array( "code" => 30025, "message" => "{0} parameter category error" )
                    '30026' => '\\ccxt\\DDoSProtection', // array( "code" => 30026, "message" => "requested too frequent" )
                    '30027' => '\\ccxt\\AuthenticationError', // array( "code" => 30027, "message" => "login failure" )
                    '30028' => '\\ccxt\\PermissionDenied', // array( "code" => 30028, "message" => "unauthorized execution" )
                    '30029' => '\\ccxt\\AccountSuspended', // array( "code" => 30029, "message" => "account suspended" )
                    '30030' => '\\ccxt\\ExchangeError', // array( "code" => 30030, "message" => "endpoint request failed. Please try again" )
                    '30031' => '\\ccxt\\BadRequest', // array( "code" => 30031, "message" => "token does not exist" )
                    '30032' => '\\ccxt\\BadSymbol', // array( "code" => 30032, "message" => "pair does not exist" )
                    '30033' => '\\ccxt\\BadRequest', // array( "code" => 30033, "message" => "exchange domain does not exist" )
                    '30034' => '\\ccxt\\ExchangeError', // array( "code" => 30034, "message" => "exchange ID does not exist" )
                    '30035' => '\\ccxt\\ExchangeError', // array( "code" => 30035, "message" => "trading is not property_exists($this, supported) website" )
                    '30036' => '\\ccxt\\ExchangeError', // array( "code" => 30036, "message" => "no relevant data" )
                    '30037' => '\\ccxt\\ExchangeNotAvailable', // array( "code" => 30037, "message" => "endpoint is offline or unavailable" )
                    // '30038' => '\\ccxt\\AuthenticationError', // array( "code" => 30038, "message" => "user does not exist" )
                    '30038' => '\\ccxt\\OnMaintenance', // array("client_oid":"","code":"30038","error_code":"30038","error_message":"Matching engine is being upgraded. Please try in about 1 minute.","message":"Matching engine is being upgraded. Please try in about 1 minute.","order_id":"-1","result":false)
                    // futures
                    '32001' => '\\ccxt\\AccountSuspended', // array( "code" => 32001, "message" => "futures account suspended" )
                    '32002' => '\\ccxt\\PermissionDenied', // array( "code" => 32002, "message" => "futures account does not exist" )
                    '32003' => '\\ccxt\\CancelPending', // array( "code" => 32003, "message" => "canceling, please wait" )
                    '32004' => '\\ccxt\\ExchangeError', // array( "code" => 32004, "message" => "you have no unfilled orders" )
                    '32005' => '\\ccxt\\InvalidOrder', // array( "code" => 32005, "message" => "max order quantity" )
                    '32006' => '\\ccxt\\InvalidOrder', // array( "code" => 32006, "message" => "the order price or trigger price exceeds USD 1 million" )
                    '32007' => '\\ccxt\\InvalidOrder', // array( "code" => 32007, "message" => "leverage level must be the same for orders on the same side of the contract" )
                    '32008' => '\\ccxt\\InvalidOrder', // array( "code" => 32008, "message" => "Max. positions to open (cross margin)" )
                    '32009' => '\\ccxt\\InvalidOrder', // array( "code" => 32009, "message" => "Max. positions to open (fixed margin)" )
                    '32010' => '\\ccxt\\ExchangeError', // array( "code" => 32010, "message" => "leverage cannot be changed with open positions" )
                    '32011' => '\\ccxt\\ExchangeError', // array( "code" => 32011, "message" => "futures status error" )
                    '32012' => '\\ccxt\\ExchangeError', // array( "code" => 32012, "message" => "futures order update error" )
                    '32013' => '\\ccxt\\ExchangeError', // array( "code" => 32013, "message" => "token type is blank" )
                    '32014' => '\\ccxt\\ExchangeError', // array( "code" => 32014, "message" => "your number of contracts closing is larger than the number of contracts available" )
                    '32015' => '\\ccxt\\ExchangeError', // array( "code" => 32015, "message" => "margin ratio is lower than 100% before opening positions" )
                    '32016' => '\\ccxt\\ExchangeError', // array( "code" => 32016, "message" => "margin ratio is lower than 100% after opening position" )
                    '32017' => '\\ccxt\\ExchangeError', // array( "code" => 32017, "message" => "no BBO" )
                    '32018' => '\\ccxt\\ExchangeError', // array( "code" => 32018, "message" => "the order quantity is less than 1, please try again" )
                    '32019' => '\\ccxt\\ExchangeError', // array( "code" => 32019, "message" => "the order price deviates from the price of the previous minute by more than 3%" )
                    '32020' => '\\ccxt\\ExchangeError', // array( "code" => 32020, "message" => "the price is not in the range of the price limit" )
                    '32021' => '\\ccxt\\ExchangeError', // array( "code" => 32021, "message" => "leverage error" )
                    '32022' => '\\ccxt\\ExchangeError', // array( "code" => 32022, "message" => "this function is not supported in your country or region according to the regulations" )
                    '32023' => '\\ccxt\\ExchangeError', // array( "code" => 32023, "message" => "this account has outstanding loan" )
                    '32024' => '\\ccxt\\ExchangeError', // array( "code" => 32024, "message" => "order cannot be placed during delivery" )
                    '32025' => '\\ccxt\\ExchangeError', // array( "code" => 32025, "message" => "order cannot be placed during settlement" )
                    '32026' => '\\ccxt\\ExchangeError', // array( "code" => 32026, "message" => "your account is restricted from opening positions" )
                    '32027' => '\\ccxt\\ExchangeError', // array( "code" => 32027, "message" => "cancelled over 20 orders" )
                    '32028' => '\\ccxt\\AccountSuspended', // array( "code" => 32028, "message" => "account is suspended and liquidated" )
                    '32029' => '\\ccxt\\ExchangeError', // array( "code" => 32029, "message" => "order info does not exist" )
                    '32030' => '\\ccxt\\InvalidOrder', // The order cannot be cancelled
                    '32031' => '\\ccxt\\ArgumentsRequired', // client_oid or order_id is required.
                    '32038' => '\\ccxt\\AuthenticationError', // User does not exist
                    '32040' => '\\ccxt\\ExchangeError', // User have open contract orders or position
                    '32044' => '\\ccxt\\ExchangeError', // array( "code" => 32044, "message" => "The margin ratio after submitting this order is lower than the minimum requirement ({0}) for your tier." )
                    '32045' => '\\ccxt\\ExchangeError', // 'strval' of commission over 1 million
                    '32046' => '\\ccxt\\ExchangeError', // Each user can hold up to 10 trade plans at the same time
                    '32047' => '\\ccxt\\ExchangeError', // system error
                    '32048' => '\\ccxt\\InvalidOrder', // Order strategy track range error
                    '32049' => '\\ccxt\\ExchangeError', // Each user can hold up to 10 track plans at the same time
                    '32050' => '\\ccxt\\InvalidOrder', // Order strategy rang error
                    '32051' => '\\ccxt\\InvalidOrder', // Order strategy ice depth error
                    '32052' => '\\ccxt\\ExchangeError', // 'strval' of commission over 100 thousand
                    '32053' => '\\ccxt\\ExchangeError', // Each user can hold up to 6 ice plans at the same time
                    '32057' => '\\ccxt\\ExchangeError', // The order price is zero. Market-close-all function cannot be executed
                    '32054' => '\\ccxt\\ExchangeError', // Trade not allow
                    '32055' => '\\ccxt\\InvalidOrder', // cancel order error
                    '32056' => '\\ccxt\\ExchangeError', // iceberg per order average should between {0}-{1} contracts
                    '32058' => '\\ccxt\\ExchangeError', // Each user can hold up to 6 initiative plans at the same time
                    '32059' => '\\ccxt\\InvalidOrder', // Total amount should exceed per order amount
                    '32060' => '\\ccxt\\InvalidOrder', // Order strategy type error
                    '32061' => '\\ccxt\\InvalidOrder', // Order strategy initiative limit error
                    '32062' => '\\ccxt\\InvalidOrder', // Order strategy initiative range error
                    '32063' => '\\ccxt\\InvalidOrder', // Order strategy initiative rate error
                    '32064' => '\\ccxt\\ExchangeError', // Time Stringerval of orders should set between 5-120s
                    '32065' => '\\ccxt\\ExchangeError', // Close amount exceeds the limit of Market-close-all (999 for BTC, and 9999 for the rest tokens)
                    '32066' => '\\ccxt\\ExchangeError', // You have open orders. Please cancel all open orders before changing your leverage level.
                    '32067' => '\\ccxt\\ExchangeError', // Account equity < required property_exists($this, margin) setting. Please adjust your leverage level again.
                    '32068' => '\\ccxt\\ExchangeError', // The margin for this position will fall short of the required property_exists($this, margin) setting. Please adjust your leverage level or increase your margin to proceed.
                    '32069' => '\\ccxt\\ExchangeError', // Target leverage level too low. Your account balance is insufficient to cover the margin required. Please adjust the leverage level again.
                    '32070' => '\\ccxt\\ExchangeError', // Please check open position or unfilled order
                    '32071' => '\\ccxt\\ExchangeError', // Your current liquidation mode does not support this action.
                    '32072' => '\\ccxt\\ExchangeError', // The highest available margin for your order’s tier is {0}. Please edit your margin and place a new order.
                    '32073' => '\\ccxt\\ExchangeError', // The action does not apply to the token
                    '32074' => '\\ccxt\\ExchangeError', // The number of contracts of your position, open orders, and the current order has exceeded the maximum order limit of this asset.
                    '32075' => '\\ccxt\\ExchangeError', // Account risk rate breach
                    '32076' => '\\ccxt\\ExchangeError', // Liquidation of the holding position(s) at market price will require cancellation of all pending close orders of the contracts.
                    '32077' => '\\ccxt\\ExchangeError', // Your margin for this asset in futures account is insufficient and the position has been taken over for liquidation. (You will not be able to place orders, close positions, transfer funds, or add margin during this period of time. Your account will be restored after the liquidation is complete.)
                    '32078' => '\\ccxt\\ExchangeError', // Please cancel all open orders before switching the liquidation mode(Please cancel all open orders before switching the liquidation mode)
                    '32079' => '\\ccxt\\ExchangeError', // Your open positions are at high risk.(Please add margin or reduce positions before switching the mode)
                    '32080' => '\\ccxt\\ExchangeError', // Funds cannot be transferred out within 30 minutes after futures settlement
                    '32083' => '\\ccxt\\ExchangeError', // The number of contracts should be a positive multiple of %%. Please place your order again
                    // token and margin trading
                    '33001' => '\\ccxt\\PermissionDenied', // array( "code" => 33001, "message" => "margin account for this pair is not enabled yet" )
                    '33002' => '\\ccxt\\AccountSuspended', // array( "code" => 33002, "message" => "margin account for this pair is suspended" )
                    '33003' => '\\ccxt\\InsufficientFunds', // array( "code" => 33003, "message" => "no loan balance" )
                    '33004' => '\\ccxt\\ExchangeError', // array( "code" => 33004, "message" => "loan amount cannot be smaller than the minimum limit" )
                    '33005' => '\\ccxt\\ExchangeError', // array( "code" => 33005, "message" => "repayment amount must exceed 0" )
                    '33006' => '\\ccxt\\ExchangeError', // array( "code" => 33006, "message" => "loan order not found" )
                    '33007' => '\\ccxt\\ExchangeError', // array( "code" => 33007, "message" => "status not found" )
                    '33008' => '\\ccxt\\InsufficientFunds', // array( "code" => 33008, "message" => "loan amount cannot exceed the maximum limit" )
                    '33009' => '\\ccxt\\ExchangeError', // array( "code" => 33009, "message" => "user ID is blank" )
                    '33010' => '\\ccxt\\ExchangeError', // array( "code" => 33010, "message" => "you cannot cancel an order during session 2 of call auction" )
                    '33011' => '\\ccxt\\ExchangeError', // array( "code" => 33011, "message" => "no new market data" )
                    '33012' => '\\ccxt\\ExchangeError', // array( "code" => 33012, "message" => "order cancellation failed" )
                    '33013' => '\\ccxt\\InvalidOrder', // array( "code" => 33013, "message" => "order placement failed" )
                    '33014' => '\\ccxt\\OrderNotFound', // array( "code" => 33014, "message" => "order does not exist" )
                    '33015' => '\\ccxt\\InvalidOrder', // array( "code" => 33015, "message" => "exceeded maximum limit" )
                    '33016' => '\\ccxt\\ExchangeError', // array( "code" => 33016, "message" => "margin trading is not open for this token" )
                    '33017' => '\\ccxt\\InsufficientFunds', // array( "code" => 33017, "message" => "insufficient balance" )
                    '33018' => '\\ccxt\\ExchangeError', // array( "code" => 33018, "message" => "this parameter must be smaller than 1" )
                    '33020' => '\\ccxt\\ExchangeError', // array( "code" => 33020, "message" => "request not supported" )
                    '33021' => '\\ccxt\\BadRequest', // array( "code" => 33021, "message" => "token and the pair do not match" )
                    '33022' => '\\ccxt\\InvalidOrder', // array( "code" => 33022, "message" => "pair and the order do not match" )
                    '33023' => '\\ccxt\\ExchangeError', // array( "code" => 33023, "message" => "you can only place market orders during call auction" )
                    '33024' => '\\ccxt\\InvalidOrder', // array( "code" => 33024, "message" => "trading amount too small" )
                    '33025' => '\\ccxt\\InvalidOrder', // array( "code" => 33025, "message" => "base token amount is blank" )
                    '33026' => '\\ccxt\\ExchangeError', // array( "code" => 33026, "message" => "transaction completed" )
                    '33027' => '\\ccxt\\InvalidOrder', // array( "code" => 33027, "message" => "cancelled order or order cancelling" )
                    '33028' => '\\ccxt\\InvalidOrder', // array( "code" => 33028, "message" => "the decimal places of the trading price exceeded the limit" )
                    '33029' => '\\ccxt\\InvalidOrder', // array( "code" => 33029, "message" => "the decimal places of the trading size exceeded the limit" )
                    '33034' => '\\ccxt\\ExchangeError', // array( "code" => 33034, "message" => "You can only place limit order after Call Auction has started" )
                    '33035' => '\\ccxt\\ExchangeError', // This type of order cannot be canceled(This type of order cannot be canceled)
                    '33036' => '\\ccxt\\ExchangeError', // Exceeding the limit of entrust order
                    '33037' => '\\ccxt\\ExchangeError', // The buy order price should be lower than 130% of the trigger price
                    '33038' => '\\ccxt\\ExchangeError', // The sell order price should be higher than 70% of the trigger price
                    '33039' => '\\ccxt\\ExchangeError', // The limit of callback rate is 0 < x <= 5%
                    '33040' => '\\ccxt\\ExchangeError', // The trigger price of a buy order should be lower than the latest transaction price
                    '33041' => '\\ccxt\\ExchangeError', // The trigger price of a sell order should be higher than the latest transaction price
                    '33042' => '\\ccxt\\ExchangeError', // The limit of price variance is 0 < x <= 1%
                    '33043' => '\\ccxt\\ExchangeError', // The total amount must be larger than 0
                    '33044' => '\\ccxt\\ExchangeError', // The average amount should be 1/1000 * total amount <= x <= total amount
                    '33045' => '\\ccxt\\ExchangeError', // The price should not be 0, including trigger price, order price, and price limit
                    '33046' => '\\ccxt\\ExchangeError', // Price variance should be 0 < x <= 1%
                    '33047' => '\\ccxt\\ExchangeError', // Sweep ratio should be 0 < x <= 100%
                    '33048' => '\\ccxt\\ExchangeError', // Per order limit => Total amount/1000 < x <= Total amount
                    '33049' => '\\ccxt\\ExchangeError', // Total amount should be X > 0
                    '33050' => '\\ccxt\\ExchangeError', // Time interval should be 5 <= x <= 120s
                    '33051' => '\\ccxt\\ExchangeError', // cancel order number not higher limit => plan and track entrust no more than 10, ice and time entrust no more than 6
                    '33059' => '\\ccxt\\BadRequest', // array( "code" => 33059, "message" => "client_oid or order_id is required" )
                    '33060' => '\\ccxt\\BadRequest', // array( "code" => 33060, "message" => "Only fill in either parameter client_oid or order_id" )
                    '33061' => '\\ccxt\\ExchangeError', // Value of a single market price order cannot exceed 100,000 USD
                    '33062' => '\\ccxt\\ExchangeError', // The leverage ratio is too high. The borrowed position has exceeded the maximum position of this leverage ratio. Please readjust the leverage ratio
                    '33063' => '\\ccxt\\ExchangeError', // Leverage multiple is too low, there is insufficient margin in the account, please readjust the leverage ratio
                    '33064' => '\\ccxt\\ExchangeError', // The setting of the leverage ratio cannot be less than 2, please readjust the leverage ratio
                    '33065' => '\\ccxt\\ExchangeError', // Leverage ratio exceeds maximum leverage ratio, please readjust leverage ratio
                    // account
                    '21009' => '\\ccxt\\ExchangeError', // Funds cannot be transferred out within 30 minutes after swap settlement(Funds cannot be transferred out within 30 minutes after swap settlement)
                    '34001' => '\\ccxt\\PermissionDenied', // array( "code" => 34001, "message" => "withdrawal suspended" )
                    '34002' => '\\ccxt\\InvalidAddress', // array( "code" => 34002, "message" => "please add a withdrawal address" )
                    '34003' => '\\ccxt\\ExchangeError', // array( "code" => 34003, "message" => "sorry, this token cannot be withdrawn to xx at the moment" )
                    '34004' => '\\ccxt\\ExchangeError', // array( "code" => 34004, "message" => "withdrawal fee is smaller than minimum limit" )
                    '34005' => '\\ccxt\\ExchangeError', // array( "code" => 34005, "message" => "withdrawal fee exceeds the maximum limit" )
                    '34006' => '\\ccxt\\ExchangeError', // array( "code" => 34006, "message" => "withdrawal amount is lower than the minimum limit" )
                    '34007' => '\\ccxt\\ExchangeError', // array( "code" => 34007, "message" => "withdrawal amount exceeds the maximum limit" )
                    '34008' => '\\ccxt\\InsufficientFunds', // array( "code" => 34008, "message" => "insufficient balance" )
                    '34009' => '\\ccxt\\ExchangeError', // array( "code" => 34009, "message" => "your withdrawal amount exceeds the daily limit" )
                    '34010' => '\\ccxt\\ExchangeError', // array( "code" => 34010, "message" => "transfer amount must be larger than 0" )
                    '34011' => '\\ccxt\\ExchangeError', // array( "code" => 34011, "message" => "conditions not met" )
                    '34012' => '\\ccxt\\ExchangeError', // array( "code" => 34012, "message" => "the minimum withdrawal amount for NEO is 1, and the amount must be an integer" )
                    '34013' => '\\ccxt\\ExchangeError', // array( "code" => 34013, "message" => "please transfer" )
                    '34014' => '\\ccxt\\ExchangeError', // array( "code" => 34014, "message" => "transfer limited" )
                    '34015' => '\\ccxt\\ExchangeError', // array( "code" => 34015, "message" => "subaccount does not exist" )
                    '34016' => '\\ccxt\\PermissionDenied', // array( "code" => 34016, "message" => "transfer suspended" )
                    '34017' => '\\ccxt\\AccountSuspended', // array( "code" => 34017, "message" => "account suspended" )
                    '34018' => '\\ccxt\\AuthenticationError', // array( "code" => 34018, "message" => "incorrect trades password" )
                    '34019' => '\\ccxt\\PermissionDenied', // array( "code" => 34019, "message" => "please bind your email before withdrawal" )
                    '34020' => '\\ccxt\\PermissionDenied', // array( "code" => 34020, "message" => "please bind your funds password before withdrawal" )
                    '34021' => '\\ccxt\\InvalidAddress', // array( "code" => 34021, "message" => "Not verified address" )
                    '34022' => '\\ccxt\\ExchangeError', // array( "code" => 34022, "message" => "Withdrawals are not available for sub accounts" )
                    '34023' => '\\ccxt\\PermissionDenied', // array( "code" => 34023, "message" => "Please enable futures trading before transferring your funds" )
                    '34026' => '\\ccxt\\ExchangeError', // transfer too frequently(transfer too frequently)
                    '34036' => '\\ccxt\\ExchangeError', // Parameter is incorrect, please refer to API documentation
                    '34037' => '\\ccxt\\ExchangeError', // Get the sub-account balance interface, account type is not supported
                    '34038' => '\\ccxt\\ExchangeError', // Since your C2C transaction is unusual, you are restricted from fund transfer. Please contact our customer support to cancel the restriction
                    '34039' => '\\ccxt\\ExchangeError', // You are now restricted from transferring out your funds due to abnormal trades on C2C Market. Please transfer your fund on our website or app instead to verify your identity
                    // swap
                    '35001' => '\\ccxt\\ExchangeError', // array( "code" => 35001, "message" => "Contract does not exist" )
                    '35002' => '\\ccxt\\ExchangeError', // array( "code" => 35002, "message" => "Contract settling" )
                    '35003' => '\\ccxt\\ExchangeError', // array( "code" => 35003, "message" => "Contract paused" )
                    '35004' => '\\ccxt\\ExchangeError', // array( "code" => 35004, "message" => "Contract pending settlement" )
                    '35005' => '\\ccxt\\AuthenticationError', // array( "code" => 35005, "message" => "User does not exist" )
                    '35008' => '\\ccxt\\InvalidOrder', // array( "code" => 35008, "message" => "Risk ratio too high" )
                    '35010' => '\\ccxt\\InvalidOrder', // array( "code" => 35010, "message" => "Position closing too large" )
                    '35012' => '\\ccxt\\InvalidOrder', // array( "code" => 35012, "message" => "Incorrect order size" )
                    '35014' => '\\ccxt\\InvalidOrder', // array( "code" => 35014, "message" => "Order price is not within limit" )
                    '35015' => '\\ccxt\\InvalidOrder', // array( "code" => 35015, "message" => "Invalid leverage level" )
                    '35017' => '\\ccxt\\ExchangeError', // array( "code" => 35017, "message" => "Open orders exist" )
                    '35019' => '\\ccxt\\InvalidOrder', // array( "code" => 35019, "message" => "Order size too large" )
                    '35020' => '\\ccxt\\InvalidOrder', // array( "code" => 35020, "message" => "Order price too high" )
                    '35021' => '\\ccxt\\InvalidOrder', // array( "code" => 35021, "message" => "Order size exceeded current tier limit" )
                    '35022' => '\\ccxt\\ExchangeError', // array( "code" => 35022, "message" => "Contract status error" )
                    '35024' => '\\ccxt\\ExchangeError', // array( "code" => 35024, "message" => "Contract not initialized" )
                    '35025' => '\\ccxt\\InsufficientFunds', // array( "code" => 35025, "message" => "No account balance" )
                    '35026' => '\\ccxt\\ExchangeError', // array( "code" => 35026, "message" => "Contract settings not initialized" )
                    '35029' => '\\ccxt\\OrderNotFound', // array( "code" => 35029, "message" => "Order does not exist" )
                    '35030' => '\\ccxt\\InvalidOrder', // array( "code" => 35030, "message" => "Order size too large" )
                    '35031' => '\\ccxt\\InvalidOrder', // array( "code" => 35031, "message" => "Cancel order size too large" )
                    '35032' => '\\ccxt\\ExchangeError', // array( "code" => 35032, "message" => "Invalid user status" )
                    '35037' => '\\ccxt\\ExchangeError', // No last traded price in cache
                    '35039' => '\\ccxt\\ExchangeError', // array( "code" => 35039, "message" => "Open order quantity exceeds limit" )
                    '35040' => '\\ccxt\\InvalidOrder', // array("error_message":"Invalid order type","result":"true","error_code":"35040","order_id":"-1")
                    '35044' => '\\ccxt\\ExchangeError', // array( "code" => 35044, "message" => "Invalid order status" )
                    '35046' => '\\ccxt\\InsufficientFunds', // array( "code" => 35046, "message" => "Negative account balance" )
                    '35047' => '\\ccxt\\InsufficientFunds', // array( "code" => 35047, "message" => "Insufficient account balance" )
                    '35048' => '\\ccxt\\ExchangeError', // array( "code" => 35048, "message" => "User contract is frozen and liquidating" )
                    '35049' => '\\ccxt\\InvalidOrder', // array( "code" => 35049, "message" => "Invalid order type" )
                    '35050' => '\\ccxt\\InvalidOrder', // array( "code" => 35050, "message" => "Position settings are blank" )
                    '35052' => '\\ccxt\\InsufficientFunds', // array( "code" => 35052, "message" => "Insufficient cross margin" )
                    '35053' => '\\ccxt\\ExchangeError', // array( "code" => 35053, "message" => "Account risk too high" )
                    '35055' => '\\ccxt\\InsufficientFunds', // array( "code" => 35055, "message" => "Insufficient account balance" )
                    '35057' => '\\ccxt\\ExchangeError', // array( "code" => 35057, "message" => "No last traded price" )
                    '35058' => '\\ccxt\\ExchangeError', // array( "code" => 35058, "message" => "No limit" )
                    '35059' => '\\ccxt\\BadRequest', // array( "code" => 35059, "message" => "client_oid or order_id is required" )
                    '35060' => '\\ccxt\\BadRequest', // array( "code" => 35060, "message" => "Only fill in either parameter client_oid or order_id" )
                    '35061' => '\\ccxt\\BadRequest', // array( "code" => 35061, "message" => "Invalid instrument_id" )
                    '35062' => '\\ccxt\\InvalidOrder', // array( "code" => 35062, "message" => "Invalid match_price" )
                    '35063' => '\\ccxt\\InvalidOrder', // array( "code" => 35063, "message" => "Invalid order_size" )
                    '35064' => '\\ccxt\\InvalidOrder', // array( "code" => 35064, "message" => "Invalid client_oid" )
                    '35066' => '\\ccxt\\InvalidOrder', // Order interval error
                    '35067' => '\\ccxt\\InvalidOrder', // Time-weighted order ratio error
                    '35068' => '\\ccxt\\InvalidOrder', // Time-weighted order range error
                    '35069' => '\\ccxt\\InvalidOrder', // Time-weighted single transaction limit error
                    '35070' => '\\ccxt\\InvalidOrder', // Algo order type error
                    '35071' => '\\ccxt\\InvalidOrder', // Order total must be larger than single order limit
                    '35072' => '\\ccxt\\InvalidOrder', // Maximum 6 unfulfilled time-weighted orders can be held at the same time
                    '35073' => '\\ccxt\\InvalidOrder', // Order price is 0. Market-close-all not available
                    '35074' => '\\ccxt\\InvalidOrder', // Iceberg order single transaction average error
                    '35075' => '\\ccxt\\InvalidOrder', // Failed to cancel order
                    '35076' => '\\ccxt\\InvalidOrder', // LTC 20x leverage. Not allowed to open position
                    '35077' => '\\ccxt\\InvalidOrder', // Maximum 6 unfulfilled iceberg orders can be held at the same time
                    '35078' => '\\ccxt\\InvalidOrder', // Order amount exceeded 100,000
                    '35079' => '\\ccxt\\InvalidOrder', // Iceberg order price variance error
                    '35080' => '\\ccxt\\InvalidOrder', // Callback rate error
                    '35081' => '\\ccxt\\InvalidOrder', // Maximum 10 unfulfilled trail orders can be held at the same time
                    '35082' => '\\ccxt\\InvalidOrder', // Trail order callback rate error
                    '35083' => '\\ccxt\\InvalidOrder', // Each user can only hold a maximum of 10 unfulfilled stop-limit orders at the same time
                    '35084' => '\\ccxt\\InvalidOrder', // Order amount exceeded 1 million
                    '35085' => '\\ccxt\\InvalidOrder', // Order amount is not in the correct range
                    '35086' => '\\ccxt\\InvalidOrder', // Price exceeds 100 thousand
                    '35087' => '\\ccxt\\InvalidOrder', // Price exceeds 100 thousand
                    '35088' => '\\ccxt\\InvalidOrder', // Average amount error
                    '35089' => '\\ccxt\\InvalidOrder', // Price exceeds 100 thousand
                    '35090' => '\\ccxt\\ExchangeError', // No stop-limit orders available for cancelation
                    '35091' => '\\ccxt\\ExchangeError', // No trail orders available for cancellation
                    '35092' => '\\ccxt\\ExchangeError', // No iceberg orders available for cancellation
                    '35093' => '\\ccxt\\ExchangeError', // No trail orders available for cancellation
                    '35094' => '\\ccxt\\ExchangeError', // Stop-limit order last traded price error
                    '35095' => '\\ccxt\\BadRequest', // Instrument_id error
                    '35096' => '\\ccxt\\ExchangeError', // Algo order status error
                    '35097' => '\\ccxt\\ExchangeError', // Order status and order ID cannot exist at the same time
                    '35098' => '\\ccxt\\ExchangeError', // An order status or order ID must exist
                    '35099' => '\\ccxt\\ExchangeError', // Algo order ID error
                    // option
                    '36001' => '\\ccxt\\BadRequest', // Invalid underlying index.
                    '36002' => '\\ccxt\\BadRequest', // Instrument does not exist.
                    '36005' => '\\ccxt\\ExchangeError', // Instrument status is invalid.
                    '36101' => '\\ccxt\\AuthenticationError', // Account does not exist.
                    '36102' => '\\ccxt\\PermissionDenied', // Account status is invalid.
                    '36103' => '\\ccxt\\AccountSuspended', // Account is suspended due to ongoing liquidation.
                    '36104' => '\\ccxt\\PermissionDenied', // Account is not enabled for options trading.
                    '36105' => '\\ccxt\\PermissionDenied', // Please enable the account for option contract.
                    '36106' => '\\ccxt\\AccountSuspended', // Funds cannot be transferred in or out, is suspended.
                    '36107' => '\\ccxt\\PermissionDenied', // Funds cannot be transferred out within 30 minutes after option exercising or settlement.
                    '36108' => '\\ccxt\\InsufficientFunds', // Funds cannot be transferred in or out, of the account is less than zero.
                    '36109' => '\\ccxt\\PermissionDenied', // Funds cannot be transferred in or out during option exercising or settlement.
                    '36201' => '\\ccxt\\PermissionDenied', // New order function is blocked.
                    '36202' => '\\ccxt\\PermissionDenied', // Account does not have permission to short option.
                    '36203' => '\\ccxt\\InvalidOrder', // Invalid format for client_oid.
                    '36204' => '\\ccxt\\ExchangeError', // Invalid format for request_id.
                    '36205' => '\\ccxt\\BadRequest', // Instrument id does not match underlying index.
                    '36206' => '\\ccxt\\BadRequest', // Order_id and client_oid can not be used at the same time.
                    '36207' => '\\ccxt\\InvalidOrder', // Either order price or fartouch price must be present.
                    '36208' => '\\ccxt\\InvalidOrder', // Either order price or size must be present.
                    '36209' => '\\ccxt\\InvalidOrder', // Either order_id or client_oid must be present.
                    '36210' => '\\ccxt\\InvalidOrder', // Either order_ids or client_oids must be present.
                    '36211' => '\\ccxt\\InvalidOrder', // Exceeding max batch size for order submission.
                    '36212' => '\\ccxt\\InvalidOrder', // Exceeding max batch size for oder cancellation.
                    '36213' => '\\ccxt\\InvalidOrder', // Exceeding max batch size for order amendment.
                    '36214' => '\\ccxt\\ExchangeError', // Instrument does not have valid bid/ask quote.
                    '36216' => '\\ccxt\\OrderNotFound', // Order does not exist.
                    '36217' => '\\ccxt\\InvalidOrder', // Order submission failed.
                    '36218' => '\\ccxt\\InvalidOrder', // Order cancellation failed.
                    '36219' => '\\ccxt\\InvalidOrder', // Order amendment failed.
                    '36220' => '\\ccxt\\InvalidOrder', // Order is pending cancel.
                    '36221' => '\\ccxt\\InvalidOrder', // Order qty is not valid multiple of lot size.
                    '36222' => '\\ccxt\\InvalidOrder', // Order price is breaching highest buy limit.
                    '36223' => '\\ccxt\\InvalidOrder', // Order price is breaching lowest sell limit.
                    '36224' => '\\ccxt\\InvalidOrder', // Exceeding max order size.
                    '36225' => '\\ccxt\\InvalidOrder', // Exceeding max open order count for instrument.
                    '36226' => '\\ccxt\\InvalidOrder', // Exceeding max open order count for underlying.
                    '36227' => '\\ccxt\\InvalidOrder', // Exceeding max open size across all orders for underlying
                    '36228' => '\\ccxt\\InvalidOrder', // Exceeding max available qty for instrument.
                    '36229' => '\\ccxt\\InvalidOrder', // Exceeding max available qty for underlying.
                    '36230' => '\\ccxt\\InvalidOrder', // Exceeding max position limit for underlying.
                    // --------------------------------------------------------
                    // swap
                    '400' => '\\ccxt\\BadRequest', // Bad Request
                    '401' => '\\ccxt\\AuthenticationError', // Unauthorized access
                    '403' => '\\ccxt\\PermissionDenied', // Access prohibited
                    '404' => '\\ccxt\\BadRequest', // Request address does not exist
                    '405' => '\\ccxt\\BadRequest', // The HTTP Method is not supported
                    '415' => '\\ccxt\\BadRequest', // The current media type is not supported
                    '429' => '\\ccxt\\DDoSProtection', // Too many requests
                    '500' => '\\ccxt\\ExchangeNotAvailable', // System busy
                    '1001' => '\\ccxt\\RateLimitExceeded', // The request is too frequent and has been throttled
                    '1002' => '\\ccxt\\ExchangeError', // {0} verifications within 24 hours
                    '1003' => '\\ccxt\\ExchangeError', // You failed more than {0} times today, the current operation is locked, please try again in 24 hours
                    // '00000' => '\\ccxt\\ExchangeError', // success
                    '40001' => '\\ccxt\\AuthenticationError', // ACCESS_KEY cannot be empty
                    '40002' => '\\ccxt\\AuthenticationError', // SECRET_KEY cannot be empty
                    '40003' => '\\ccxt\\AuthenticationError', // Signature cannot be empty
                    '40004' => '\\ccxt\\InvalidNonce', // Request timestamp expired
                    '40005' => '\\ccxt\\InvalidNonce', // Invalid ACCESS_TIMESTAMP
                    '40006' => '\\ccxt\\AuthenticationError', // Invalid ACCESS_KEY
                    '40007' => '\\ccxt\\BadRequest', // Invalid Content_Type
                    '40008' => '\\ccxt\\InvalidNonce', // Request timestamp expired
                    '40009' => '\\ccxt\\AuthenticationError', // sign signature error
                    '40010' => '\\ccxt\\AuthenticationError', // sign signature error
                    '40011' => '\\ccxt\\AuthenticationError', // ACCESS_PASSPHRASE cannot be empty
                    '40012' => '\\ccxt\\AuthenticationError', // apikey/password is incorrect
                    '40013' => '\\ccxt\\ExchangeError', // User status is abnormal
                    '40014' => '\\ccxt\\PermissionDenied', // Incorrect permissions
                    '40015' => '\\ccxt\\ExchangeError', // System is abnormal, please try again later
                    '40016' => '\\ccxt\\PermissionDenied', // The user must bind the phone or Google
                    '40017' => '\\ccxt\\ExchangeError', // Parameter verification failed
                    '40018' => '\\ccxt\\PermissionDenied', // Invalid IP
                    '40019' => '\\ccxt\\BadRequest', // array("code":"40019","msg":"Parameter QLCUSDT_SPBL cannot be empty","requestTime":1679196063659,"data":null)
                    '40031' => '\\ccxt\\AccountSuspended', // The account has been cancelled and cannot be used again
                    '40037' => '\\ccxt\\AuthenticationError', // Apikey does not exist
                    '40102' => '\\ccxt\\BadRequest', // Contract configuration does not exist, please check the parameters
                    '40103' => '\\ccxt\\BadRequest', // Request method cannot be empty
                    '40104' => '\\ccxt\\ExchangeError', // Lever adjustment failure
                    '40105' => '\\ccxt\\ExchangeError', // Abnormal access to current price limit data
                    '40106' => '\\ccxt\\ExchangeError', // Abnormal get next settlement time
                    '40107' => '\\ccxt\\ExchangeError', // Abnormal access to index price data
                    '40108' => '\\ccxt\\InvalidOrder', // Wrong order quantity
                    '40109' => '\\ccxt\\OrderNotFound', // The data of the order cannot be found, please confirm the order number
                    '40200' => '\\ccxt\\OnMaintenance', // Server upgrade, please try again later
                    '40201' => '\\ccxt\\InvalidOrder', // Order number cannot be empty
                    '40202' => '\\ccxt\\ExchangeError', // User information cannot be empty
                    '40203' => '\\ccxt\\BadRequest', // The amount of adjustment margin cannot be empty or negative
                    '40204' => '\\ccxt\\BadRequest', // Adjustment margin type cannot be empty
                    '40205' => '\\ccxt\\BadRequest', // Adjusted margin type data is wrong
                    '40206' => '\\ccxt\\BadRequest', // The direction of the adjustment margin cannot be empty
                    '40207' => '\\ccxt\\BadRequest', // The adjustment margin data is wrong
                    '40208' => '\\ccxt\\BadRequest', // The accuracy of the adjustment margin amount is incorrect
                    '40209' => '\\ccxt\\BadRequest', // The current page number is wrong, please confirm
                    '40300' => '\\ccxt\\ExchangeError', // User does not exist
                    '40301' => '\\ccxt\\PermissionDenied', // Permission has not been obtained yet. If you need to use it, please contact customer service
                    '40302' => '\\ccxt\\BadRequest', // Parameter abnormality
                    '40303' => '\\ccxt\\BadRequest', // Can only query up to 20,000 data
                    '40304' => '\\ccxt\\BadRequest', // Parameter type is abnormal
                    '40305' => '\\ccxt\\BadRequest', // Client_oid length is not greater than 50, and cannot be Martian characters
                    '40306' => '\\ccxt\\ExchangeError', // Batch processing orders can only process up to 20
                    '40308' => '\\ccxt\\OnMaintenance', // The contract is being temporarily maintained
                    '40309' => '\\ccxt\\BadSymbol', // The contract has been removed
                    '40400' => '\\ccxt\\ExchangeError', // Status check abnormal
                    '40401' => '\\ccxt\\ExchangeError', // The operation cannot be performed
                    '40402' => '\\ccxt\\BadRequest', // The opening direction cannot be empty
                    '40403' => '\\ccxt\\BadRequest', // Wrong opening direction format
                    '40404' => '\\ccxt\\BadRequest', // Whether to enable automatic margin call parameters cannot be empty
                    '40405' => '\\ccxt\\BadRequest', // Whether to enable the automatic margin call parameter type is wrong
                    '40406' => '\\ccxt\\BadRequest', // Whether to enable automatic margin call parameters is of unknown type
                    '40407' => '\\ccxt\\ExchangeError', // The query direction is not the direction entrusted by the plan
                    '40408' => '\\ccxt\\ExchangeError', // Wrong time range
                    '40409' => '\\ccxt\\ExchangeError', // Time format error
                    '40500' => '\\ccxt\\InvalidOrder', // Client_oid check error
                    '40501' => '\\ccxt\\ExchangeError', // Channel name error
                    '40502' => '\\ccxt\\ExchangeError', // If it is a copy user, you must pass the copy to whom
                    '40503' => '\\ccxt\\ExchangeError', // With the single type
                    '40504' => '\\ccxt\\ExchangeError', // Platform code must pass
                    '40505' => '\\ccxt\\ExchangeError', // Not the same type
                    '40506' => '\\ccxt\\AuthenticationError', // Platform signature error
                    '40507' => '\\ccxt\\AuthenticationError', // Api signature error
                    '40508' => '\\ccxt\\ExchangeError', // KOL is not authorized
                    '40509' => '\\ccxt\\ExchangeError', // Abnormal copy end
                    '40600' => '\\ccxt\\ExchangeError', // Copy function suspended
                    '40601' => '\\ccxt\\ExchangeError', // Followers cannot be KOL
                    '40602' => '\\ccxt\\ExchangeError', // The number of copies has reached the limit and cannot process the request
                    '40603' => '\\ccxt\\ExchangeError', // Abnormal copy end
                    '40604' => '\\ccxt\\ExchangeNotAvailable', // Server is busy, please try again later
                    '40605' => '\\ccxt\\ExchangeError', // Copy type, the copy number must be passed
                    '40606' => '\\ccxt\\ExchangeError', // The type of document number is wrong
                    '40607' => '\\ccxt\\ExchangeError', // Document number must be passed
                    '40608' => '\\ccxt\\ExchangeError', // No documented products currently supported
                    '40609' => '\\ccxt\\ExchangeError', // The contract product does not support copying
                    '40700' => '\\ccxt\\BadRequest', // Cursor parameters are incorrect
                    '40701' => '\\ccxt\\ExchangeError', // KOL is not authorized
                    '40702' => '\\ccxt\\ExchangeError', // Unauthorized copying user
                    '40703' => '\\ccxt\\ExchangeError', // Bill inquiry start and end time cannot be empty
                    '40704' => '\\ccxt\\ExchangeError', // Can only check the data of the last three months
                    '40705' => '\\ccxt\\BadRequest', // The start and end time cannot exceed 90 days
                    '40706' => '\\ccxt\\InvalidOrder', // Wrong order price
                    '40707' => '\\ccxt\\BadRequest', // Start time is greater than end time
                    '40708' => '\\ccxt\\BadRequest', // Parameter verification is abnormal
                    '40709' => '\\ccxt\\ExchangeError', // There is no property_exists($this, position) position, and no automatic margin call can be set
                    '40710' => '\\ccxt\\ExchangeError', // Abnormal account status
                    '40711' => '\\ccxt\\InsufficientFunds', // Insufficient contract account balance
                    '40712' => '\\ccxt\\InsufficientFunds', // Insufficient margin
                    '40713' => '\\ccxt\\ExchangeError', // Cannot exceed the maximum transferable margin amount
                    '40714' => '\\ccxt\\ExchangeError', // No direct margin call is allowed
                    '40762' => '\\ccxt\\InsufficientFunds', // array("code":"40762","msg":"The order amount exceeds the balance","requestTime":1716572156622,"data":null)
                    '40768' => '\\ccxt\\OrderNotFound', // Order does not exist
                    '40808' => '\\ccxt\\InvalidOrder', // array("code":"40808","msg":"Parameter verification exception size checkBDScale error value=2293.577 checkScale=2","requestTime":1725638500052,"data":null)
                    '41103' => '\\ccxt\\InvalidOrder', // array("code":"41103","msg":"param price scale error error","requestTime":1725635883561,"data":null)
                    '41114' => '\\ccxt\\OnMaintenance', // array("code":"41114","msg":"The current trading pair is under maintenance, please refer to the official announcement for the opening time","requestTime":1679196062544,"data":null)
                    '43011' => '\\ccxt\\InvalidOrder', // The parameter does not meet the specification executePrice <= 0
                    '43001' => '\\ccxt\\OrderNotFound',
                    '43012' => '\\ccxt\\InsufficientFunds', // array("code":"43012","msg":"Insufficient balance","requestTime":1711648951774,"data":null)
                    '43025' => '\\ccxt\\InvalidOrder', // Plan order does not exist
                    '43115' => '\\ccxt\\OnMaintenance', // array("code":"43115","msg":"The current trading pair is opening soon, please refer to the official announcement for the opening time","requestTime":1688907202434,"data":null)
                    '45110' => '\\ccxt\\InvalidOrder', // array("code":"45110","msg":"less than the minimum amount 5 USDT","requestTime":1669911118932,"data":null)
                    '40774' => '\\ccxt\\InvalidOrder', // array("code":"40774","msg":"The order type for unilateral position must also be the unilateral position type.","requestTime":1758709764409,"data":null)
                    '45122' => '\\ccxt\\InvalidOrder', // array("code":"45122","msg":"Short position stop loss price please > mark price 106.86","requestTime":1758709970499,"data":null)
                    // spot
                    'invalid sign' => '\\ccxt\\AuthenticationError',
                    'invalid currency' => '\\ccxt\\BadSymbol', // invalid trading pair
                    'invalid symbol' => '\\ccxt\\BadSymbol',
                    'invalid period' => '\\ccxt\\BadRequest', // invalid Kline type
                    'invalid user' => '\\ccxt\\ExchangeError',
                    'invalid amount' => '\\ccxt\\InvalidOrder',
                    'invalid type' => '\\ccxt\\InvalidOrder', // array("status":"error","ts":1595700344504,"err_code":"invalid-parameter","err_msg":"invalid type")
                    'invalid orderId' => '\\ccxt\\InvalidOrder',
                    'invalid record' => '\\ccxt\\ExchangeError',
                    'invalid accountId' => '\\ccxt\\BadRequest',
                    'invalid address' => '\\ccxt\\BadRequest',
                    'accesskey not null' => '\\ccxt\\AuthenticationError', // array("status":"error","ts":1595704360508,"err_code":"invalid-parameter","err_msg":"accesskey not null")
                    'illegal accesskey' => '\\ccxt\\AuthenticationError',
                    'sign not null' => '\\ccxt\\AuthenticationError',
                    'req_time is too much difference from server time' => '\\ccxt\\InvalidNonce',
                    'permissions not right' => '\\ccxt\\PermissionDenied', // array("status":"error","ts":1595704490084,"err_code":"invalid-parameter","err_msg":"permissions not right")
                    'illegal sign invalid' => '\\ccxt\\AuthenticationError', // array("status":"error","ts":1595684716042,"err_code":"invalid-parameter","err_msg":"illegal sign invalid")
                    'user locked' => '\\ccxt\\AccountSuspended',
                    'Request Frequency Is Too High' => '\\ccxt\\RateLimitExceeded',
                    'more than a daily rate of cash' => '\\ccxt\\BadRequest',
                    'more than the maximum daily withdrawal amount' => '\\ccxt\\BadRequest',
                    'need to bind email or mobile' => '\\ccxt\\ExchangeError',
                    'user forbid' => '\\ccxt\\PermissionDenied',
                    'User Prohibited Cash Withdrawal' => '\\ccxt\\PermissionDenied',
                    'Cash Withdrawal Is Less Than The Minimum Value' => '\\ccxt\\BadRequest',
                    'Cash Withdrawal Is More Than The Maximum Value' => '\\ccxt\\BadRequest',
                    'the account with in 24 hours ban coin' => '\\ccxt\\PermissionDenied',
                    'order cancel fail' => '\\ccxt\\BadRequest', // array("status":"error","ts":1595703343035,"err_code":"bad-request","err_msg":"order cancel fail")
                    'base symbol error' => '\\ccxt\\BadSymbol',
                    'base date error' => '\\ccxt\\ExchangeError',
                    'api signature not valid' => '\\ccxt\\AuthenticationError',
                    'gateway internal error' => '\\ccxt\\ExchangeError',
                    'audit failed' => '\\ccxt\\ExchangeError',
                    'order queryorder invalid' => '\\ccxt\\BadRequest',
                    'market no need price' => '\\ccxt\\InvalidOrder',
                    'limit need price' => '\\ccxt\\InvalidOrder',
                    'userid not equal to account_id' => '\\ccxt\\ExchangeError',
                    'your balance is low' => '\\ccxt\\InsufficientFunds', // array("status":"error","ts":1595594160149,"err_code":"invalid-parameter","err_msg":"invalid size, valid range => [1,2000]")
                    'address invalid cointype' => '\\ccxt\\ExchangeError',
                    'system exception' => '\\ccxt\\ExchangeError', // array("status":"error","ts":1595711862763,"err_code":"system exception","err_msg":"system exception")
                    '50003' => '\\ccxt\\ExchangeError', // No record
                    '50004' => '\\ccxt\\BadSymbol', // The transaction pair is currently not supported or has been suspended
                    '50006' => '\\ccxt\\PermissionDenied', // The account is forbidden to withdraw. If you have any questions, please contact customer service.
                    '50007' => '\\ccxt\\PermissionDenied', // The account is forbidden to withdraw within 24 hours. If you have any questions, please contact customer service.
                    '50008' => '\\ccxt\\RequestTimeout', // network timeout
                    '50009' => '\\ccxt\\RateLimitExceeded', // The operation is too frequent, please try again later
                    '50010' => '\\ccxt\\ExchangeError', // The account is abnormally frozen. If you have any questions, please contact customer service.
                    '50014' => '\\ccxt\\InvalidOrder', // The transaction amount under minimum limits
                    '50015' => '\\ccxt\\InvalidOrder', // The transaction amount exceed maximum limits
                    '50016' => '\\ccxt\\InvalidOrder', // The price can't be higher than the current price
                    '50017' => '\\ccxt\\InvalidOrder', // Price under minimum limits
                    '50018' => '\\ccxt\\InvalidOrder', // The price exceed maximum limits
                    '50019' => '\\ccxt\\InvalidOrder', // The amount under minimum limits
                    '50020' => '\\ccxt\\InsufficientFunds', // Insufficient balance
                    '50021' => '\\ccxt\\InvalidOrder', // Price is under minimum limits
                    '50026' => '\\ccxt\\InvalidOrder', // Market price parameter error
                    'invalid order query time' => '\\ccxt\\ExchangeError', // start time is greater than end time; or the time interval between start time and end time is greater than 48 hours
                    'invalid start time' => '\\ccxt\\BadRequest', // start time is a date 30 days ago; or start time is a date in the future
                    'invalid end time' => '\\ccxt\\BadRequest', // end time is a date 30 days ago; or end time is a date in the future
                    '20003' => '\\ccxt\\ExchangeError', // operation failed, array("status":"error","ts":1595730308979,"err_code":"bad-request","err_msg":"20003")
                    '01001' => '\\ccxt\\ExchangeError', // order failed, array("status":"fail","err_code":"01001","err_msg":"系统异常，请稍后重试")
                    '43111' => '\\ccxt\\PermissionDenied', // array("code":"43111","msg":"参数错误 address not in address book","requestTime":1665394201164,"data":null)
                ),
                'broad' => array(
                    'invalid size, valid range' => '\\ccxt\\ExchangeError',
                ),
            ),
            'precisionMode' => TICK_SIZE,
            'commonCurrencies' => array(
                'APX' => 'AstroPepeX',
                'DEGEN' => 'DegenReborn',
                'JADE' => 'Jade Protocol',
                'OMNI' => 'omni', // conflict with Omni Network
                'TONCOIN' => 'TON',
            ),
            'options' => array(
                'uta' => false,
                'timeDifference' => 0, // the difference between system clock and Binance clock
                'adjustForTimeDifference' => false, // controls the adjustment logic upon instantiation
                'timeframes' => array(
                    'spot' => array(
                        '1m' => '1min',
                        '5m' => '5min',
                        '15m' => '15min',
                        '30m' => '30min',
                        '1h' => '1h',
                        '4h' => '4h',
                        '6h' => '6Hutc',
                        '12h' => '12Hutc',
                        '1d' => '1Dutc',
                        '3d' => '3Dutc',
                        '1w' => '1Wutc',
                        '1M' => '1Mutc',
                    ),
                    'swap' => array(
                        '1m' => '1m',
                        '3m' => '3m',
                        '5m' => '5m',
                        '15m' => '15m',
                        '30m' => '30m',
                        '1h' => '1H',
                        '2h' => '2H',
                        '4h' => '4H',
                        '6h' => '6Hutc',
                        '12h' => '12Hutc',
                        '1d' => '1Dutc',
                        '3d' => '3Dutc',
                        '1w' => '1Wutc',
                        '1M' => '1Mutc',
                    ),
                    'uta' => array(
                        '1m' => '1m',
                        '3m' => '3m',
                        '5m' => '5m',
                        '15m' => '15m',
                        '30m' => '30m',
                        '1h' => '1H',
                        '2h' => '2H',
                        '4h' => '4H',
                        '6h' => '6H',
                        '12h' => '12H',
                        '1d' => '1D',
                    ),
                ),
                'fetchMarkets' => array(
                    'types' => array( 'spot', 'swap' ), // there is future markets but they use the same endpoints
                ),
                'defaultType' => 'spot', // 'spot', 'swap', 'future'
                'defaultSubType' => 'linear', // 'linear', 'inverse'
                'createMarketBuyOrderRequiresPrice' => true,
                'broker' => 'p4sve',
                'withdraw' => array(
                    'fillResponseFromRequest' => true,
                ),
                'fetchOHLCV' => array(
                    // ### Timeframe settings ###
                    // after testing, the below values are real ones, because the values provided by API DOCS are wrong
                    // so, start timestamp should be within these thresholds to be able to call "recent" candles endpoint
                    'maxRecentDaysPerTimeframe' => array(
                        '1m' => 30,
                        '3m' => 30,
                        '5m' => 30,
                        '15m' => 30,
                        '30m' => 30,
                        '1h' => 60,
                        '4h' => 240,
                        '6h' => 360,
                        '12h' => 720,
                        '1d' => 1440,
                        '3d' => 1440 * 3,
                        '1w' => 1440 * 7,
                        '1M' => 1440 * 30,
                    ),
                    'spot' => array(
                        'maxLimitPerTimeframe' => array(
                            '1d' => 300,
                            '3d' => 100,
                            '1w' => 100,
                            '1M' => 100,
                        ),
                        'method' => 'publicSpotGetV2SpotMarketCandles', // publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
                    ),
                    'swap' => array(
                        'maxLimitPerTimeframe' => array(
                            '4h' => 540,
                            '6h' => 360,
                            '12h' => 180,
                            '1d' => 90,
                            '3d' => 30,
                            '1w' => 13,
                            '1M' => 4,
                        ),
                        'method' => 'publicMixGetV2MixMarketCandles', // publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
                    ),
                ),
                'fetchTrades' => array(
                    'spot' => array(
                        'method' => 'publicSpotGetV2SpotMarketFillsHistory', // or publicSpotGetV2SpotMarketFills
                    ),
                    'swap' => array(
                        'method' => 'publicMixGetV2MixMarketFillsHistory', // or publicMixGetV2MixMarketFills
                    ),
                ),
                'fetchFundingRate' => array(
                    'method' => 'publicMixGetV2MixMarketCurrentFundRate', // or publicMixGetV2MixMarketFundingTime
                ),
                'accountsByType' => array(
                    'spot' => 'spot',
                    'cross' => 'crossed_margin',
                    'isolated' => 'isolated_margin',
                    'swap' => 'usdt_futures',
                    'usdc_swap' => 'usdc_futures',
                    'future' => 'coin_futures',
                    'p2p' => 'p2p',
                ),
                'accountsById' => array(
                    'spot' => 'spot',
                    'crossed_margin' => 'cross',
                    'isolated_margin' => 'isolated',
                    'usdt_futures' => 'swap',
                    'usdc_futures' => 'usdc_swap',
                    'coin_futures' => 'future',
                    'p2p' => 'p2p',
                ),
                'sandboxMode' => false,
                'networks' => array(
                    // 'TRX' => 'TRX', // different code for mainnet
                    'TRC20' => 'TRC20',
                    // 'ETH' => 'ETH', // different code for mainnet
                    'ERC20' => 'ERC20',
                    'BEP20' => 'BSC',
                    // 'BEP20' => 'BEP20', // different for BEP20
                    'ATOM' => 'ATOM',
                    'ACA' => 'AcalaToken',
                    'APT' => 'Aptos',
                    'ARBONE' => 'ArbitrumOne',
                    'ARBNOVA' => 'ArbitrumNova',
                    'AVAXC' => 'C-Chain',
                    'AVAXX' => 'X-Chain',
                    'AR' => 'Arweave',
                    'BCH' => 'BCH',
                    'BCHA' => 'BCHA',
                    'BITCI' => 'BITCI',
                    'BTC' => 'BTC',
                    'CELO' => 'CELO',
                    'CSPR' => 'CSPR',
                    'ADA' => 'Cardano',
                    'CHZ' => 'ChilizChain',
                    'CRC20' => 'CronosChain',
                    'DOGE' => 'DOGE',
                    'DOT' => 'DOT',
                    'EOS' => 'EOS',
                    'ETHF' => 'ETHFAIR',
                    'ETHW' => 'ETHW',
                    'ETC' => 'ETC',
                    'EGLD' => 'Elrond',
                    'FIL' => 'FIL',
                    'FIO' => 'FIO',
                    'FTM' => 'Fantom',
                    'HRC20' => 'HECO',
                    'ONE' => 'Harmony',
                    'HNT' => 'Helium',
                    'ICP' => 'ICP',
                    'IOTX' => 'IoTeX',
                    'KARDIA' => 'KAI',
                    'KAVA' => 'KAVA',
                    'KDA' => 'KDA',
                    'KLAY' => 'Klaytn',
                    'KSM' => 'Kusama',
                    'LAT' => 'LAT',
                    'LTC' => 'LTC',
                    'MINA' => 'MINA',
                    'MOVR' => 'MOVR',
                    'METIS' => 'MetisToken',
                    'GLMR' => 'Moonbeam',
                    'NEAR' => 'NEARProtocol',
                    'NULS' => 'NULS',
                    'OASYS' => 'OASYS',
                    'OASIS' => 'ROSE',
                    'OMNI' => 'OMNI',
                    'ONT' => 'Ontology',
                    'OPTIMISM' => 'Optimism',
                    'OSMO' => 'Osmosis',
                    'POKT' => 'PocketNetwork',
                    'MATIC' => 'Polygon',
                    'QTUM' => 'QTUM',
                    'REEF' => 'REEF',
                    'SOL' => 'SOL',
                    'SYS' => 'SYS', // SyscoinNEVM is different
                    'SXP' => 'Solar',
                    'XYM' => 'Symbol',
                    'TON' => 'TON',
                    'TT' => 'TT',
                    'TLOS' => 'Telos',
                    'THETA' => 'ThetaToken',
                    'VITE' => 'VITE',
                    'WAVES' => 'WAVES',
                    'WAX' => 'WAXP',
                    'WEMIX' => 'WEMIXMainnet',
                    'XDC' => 'XDCNetworkXDC',
                    'XRP' => 'XRP',
                    'FET' => 'FETCH',
                    'NEM' => 'NEM',
                    'REI' => 'REINetwork',
                    'ZIL' => 'ZIL',
                    'ABBC' => 'ABBCCoin',
                    'RSK' => 'RSK',
                    'AZERO' => 'AZERO',
                    'TRC10' => 'TRC10',
                    'JUNO' => 'JUNO',
                    // undetected => USDSP, more info at https://www.bitget.com/v1/spot/public/coinChainList
                    // todo => uncomment below after unification
                    // 'TERRACLASSIC' => 'Terra', // tbd, that network id is also assigned to TERRANEW network
                    // 'CUBENETWORK' => 'CUBE',
                    // 'CADUCEUS' => 'CMP',
                    // 'CONFLUX' => 'CFX', // CFXeSpace is different
                    // 'CERE' => 'CERE',
                    // 'CANTO' => 'CANTO',
                    'ZKSYNC' => 'zkSyncEra',
                    'STARKNET' => 'Starknet',
                    'VIC' => 'VICTION',
                ),
                'networksById' => array(
                ),
                'fetchPositions' => array(
                    'method' => 'privateMixGetV2MixPositionAllPosition', // or privateMixGetV2MixPositionHistoryPosition
                ),
                'defaultTimeInForce' => 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
                // fiat currencies on deposit page
                'fiatCurrencies' => array( 'EUR', 'VND', 'PLN', 'CZK', 'HUF', 'DKK', 'AUD', 'CAD', 'NOK', 'SEK', 'CHF', 'MXN', 'COP', 'ARS', 'GBP', 'BRL', 'UAH', 'ZAR' ),
            ),
            'features' => array(
                'spot' => array(
                    'sandbox' => true,
                    'createOrder' => array(
                        'marginMode' => true,
                        'triggerPrice' => true,
                        'triggerPriceType' => array(
                            'last' => true,
                            'mark' => true,
                            'index' => false, // not on spot
                        ),
                        'triggerDirection' => false,
                        'stopLossPrice' => true, // todo =>  not yet implemented in spot
                        'takeProfitPrice' => true, // todo => not yet implemented in spot
                        'attachedStopLossTakeProfit' => array(
                            'triggerPriceType' => array(
                                'last' => false,
                                'mark' => false,
                                'index' => false,
                            ),
                            'price' => true,
                        ),
                        'timeInForce' => array(
                            'IOC' => true,
                            'FOK' => true,
                            'PO' => true,
                            'GTD' => false,
                        ),
                        'hedged' => false,
                        'trailing' => false,
                        'marketBuyRequiresPrice' => true,
                        'marketBuyByCost' => true,
                        // exchange-supported features
                        // 'selfTradePrevention' => true,
                        // 'twap' => false,
                        // 'iceberg' => false,
                        // 'oco' => false,
                    ),
                    'createOrders' => array(
                        'max' => 50,
                    ),
                    'fetchMyTrades' => array(
                        'marginMode' => true,
                        'limit' => 100,
                        'daysBack' => null,
                        'untilDays' => 90,
                        'symbolRequired' => true,
                    ),
                    'fetchOrder' => array(
                        'marginMode' => false,
                        'trigger' => false,
                        'trailing' => false,
                        'symbolRequired' => true,
                    ),
                    'fetchOpenOrders' => array(
                        'marginMode' => true,
                        'limit' => 100,
                        'trigger' => true,
                        'trailing' => false,
                        'symbolRequired' => false,
                    ),
                    'fetchOrders' => null,
                    'fetchClosedOrders' => array(
                        'marginMode' => true,
                        'limit' => 100,
                        'daysBack' => null,
                        'daysBackCanceled' => null,
                        'untilDays' => 90,
                        'trigger' => true,
                        'trailing' => false,
                        'symbolRequired' => false,
                    ),
                    'fetchOHLCV' => array(
                        'limit' => 200, // variable timespans for recent endpoint, 200 for historical
                    ),
                ),
                'forPerps' => array(
                    'extends' => 'spot',
                    'createOrder' => array(
                        'triggerPrice' => true,
                        'triggerPriceType' => array(
                            'last' => true,
                            'mark' => true,
                            'index' => false, // not on spot
                        ),
                        'triggerDirection' => false,
                        'stopLossPrice' => true,
                        'takeProfitPrice' => true,
                        'attachedStopLossTakeProfit' => array(
                            'triggerPriceType' => array(
                                'last' => true,
                                'mark' => true,
                                'index' => true,
                            ),
                            'price' => false,
                        ),
                        'timeInForce' => array(
                            'IOC' => true,
                            'FOK' => true,
                            'PO' => true,
                            'GTD' => false,
                        ),
                        'hedged' => true,
                        'trailing' => true,
                        'marketBuyRequiresPrice' => false,
                        'marketBuyByCost' => false,
                        // exchange-supported features
                        // 'selfTradePrevention' => true,
                        // 'trailing' => true,
                        // 'twap' => false,
                        // 'iceberg' => false,
                        // 'oco' => false,
                    ),
                    'fetchMyTrades' => array(
                        'untilDays' => 7,
                    ),
                    'fetchClosedOrders' => array(
                        'trailing' => true,
                    ),
                ),
                'swap' => array(
                    'linear' => array(
                        'extends' => 'forPerps',
                    ),
                    'inverse' => array(
                        'extends' => 'forPerps',
                    ),
                ),
                'future' => array(
                    'linear' => array(
                        'extends' => 'forPerps',
                    ),
                    'inverse' => array(
                        'extends' => 'forPerps',
                    ),
                ),
            ),
        ));
    }

    public function set_sandbox_mode($enabled) {
        $this->options['sandboxMode'] = $enabled;
    }

    public function handle_product_type_and_params($market = null, $params = array ()) {
        $subType = null;
        list($subType, $params) = $this->handle_sub_type_and_params('handleProductTypeAndParams', null, $params);
        $defaultProductType = null;
        if (($subType !== null) && ($market === null)) {
            // set default only if $subType is defined and $market is not defined, since there is also USDC productTypes which are also linear
            // $sandboxMode = $this->safe_bool($this->options, 'sandboxMode', false);
            // if ($sandboxMode) {
            //     $defaultProductType = ($subType === 'linear') ? 'SUSDT-FUTURES' : 'SCOIN-FUTURES';
            // } else {
            $defaultProductType = ($subType === 'linear') ? 'USDT-FUTURES' : 'COIN-FUTURES';
            // }
        }
        $productType = $this->safe_string_2($params, 'productType', 'category', $defaultProductType);
        if (($productType === null) && ($market !== null)) {
            $settle = $market['settle'];
            if ($market['spot']) {
                $marginMode = null;
                list($marginMode, $params) = $this->handle_margin_mode_and_params('handleProductTypeAndParams', $params);
                if ($marginMode !== null) {
                    $productType = 'MARGIN';
                } else {
                    $productType = 'SPOT';
                }
            } elseif ($settle === 'USDT') {
                $productType = 'USDT-FUTURES';
            } elseif ($settle === 'USDC') {
                $productType = 'USDC-FUTURES';
            } elseif ($settle === 'SUSDT') {
                $productType = 'SUSDT-FUTURES';
            } elseif ($settle === 'SUSDC') {
                $productType = 'SUSDC-FUTURES';
            } elseif (($settle === 'SBTC') || ($settle === 'SETH') || ($settle === 'SEOS')) {
                $productType = 'SCOIN-FUTURES';
            } else {
                $productType = 'COIN-FUTURES';
            }
        }
        if ($productType === null) {
            throw new ArgumentsRequired($this->id . ' requires a $productType param, one of "USDT-FUTURES", "USDC-FUTURES", "COIN-FUTURES", "SUSDT-FUTURES", "SUSDC-FUTURES", "SCOIN-FUTURES" or for uta only "SPOT"');
        }
        $params = $this->omit($params, array( 'productType', 'category' ));
        return array( $productType, $params );
    }

    public function fetch_time($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetches the current integer timestamp in milliseconds from the exchange server
             *
             * @see https://www.bitget.com/api-doc/common/public/Get-Server-Time
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {int} the current integer timestamp in milliseconds from the exchange server
             */
            $response = Async\await($this->publicCommonGetV2PublicTime ($params));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700111073740,
            //         "data" => {
            //             "serverTime" => "1700111073740"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->safe_integer($data, 'serverTime');
        }) ();
    }

    public function fetch_markets($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * retrieves data on all markets for bitget
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Symbols
             * @see https://www.bitget.com/api-doc/contract/market/Get-All-Symbols-Contracts
             * @see https://www.bitget.com/api-doc/margin/common/support-currencies
             * @see https://www.bitget.com/api-doc/uta/public/Instruments
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array[]} an array of objects representing market data
             */
            if ($this->options['adjustForTimeDifference']) {
                Async\await($this->load_time_difference());
            }
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchMarkets', 'uta', false);
            if ($uta) {
                return Async\await($this->fetch_uta_markets($params));
            } else {
                return Async\await($this->fetch_default_markets($params));
            }
        }) ();
    }

    public function fetch_default_markets($params): PromiseInterface {
        return Async\async(function () use ($params) {
            $types = null;
            $fetchMarketsOptions = $this->safe_dict($this->options, 'fetchMarkets');
            $defaultMarkets = array( 'spot', 'swap' );
            if ($fetchMarketsOptions !== null) {
                $types = $this->safe_list($fetchMarketsOptions, 'types', $defaultMarkets);
            } else {
                // for backward-compatibility
                $types = $this->safe_list($this->options, 'fetchMarkets', $defaultMarkets);
            }
            $promises = array();
            $fetchMargins = false;
            for ($i = 0; $i < count($types); $i++) {
                $type = $types[$i];
                if (($type === 'swap') || ($type === 'future')) {
                    $subTypes = array( 'USDT-FUTURES', 'COIN-FUTURES', 'USDC-FUTURES', 'SUSDT-FUTURES', 'SCOIN-FUTURES', 'SUSDC-FUTURES' );
                    for ($j = 0; $j < count($subTypes); $j++) {
                        $promises[] = $this->publicMixGetV2MixMarketContracts ($this->extend($params, array(
                            'productType' => $subTypes[$j],
                        )));
                    }
                } elseif ($type === 'spot') {
                    $promises[] = $this->publicSpotGetV2SpotPublicSymbols ($params);
                    $fetchMargins = true;
                    $promises[] = $this->publicMarginGetV2MarginCurrencies ($params);
                } else {
                    throw new NotSupported($this->id . ' does not support ' . $type . ' market');
                }
            }
            $results = Async\await(Promise\all($promises));
            $markets = array();
            $this->options['crossMarginPairsData'] = array();
            $this->options['isolatedMarginPairsData'] = array();
            for ($i = 0; $i < count($results); $i++) {
                $res = $this->safe_dict($results, $i);
                $data = $this->safe_list($res, 'data', array());
                $firstData = $this->safe_dict($data, 0, array());
                $isBorrowable = $this->safe_bool($firstData, 'isBorrowable');
                if ($fetchMargins && $isBorrowable !== null) {
                    $keysList = is_array($this->index_by($data, 'symbol')) ? array_keys($this->index_by($data, 'symbol')) : array();
                    $this->options['crossMarginPairsData'] = $keysList;
                    $this->options['isolatedMarginPairsData'] = $keysList;
                } else {
                    $markets = $this->array_concat($markets, $data);
                }
            }
            //
            // $spot
            //
            //     {
            //         "symbol" => "TRXUSDT",
            //         "baseCoin" => "TRX",
            //         "quoteCoin" => "USDT",
            //         "minTradeAmount" => "0",
            //         "maxTradeAmount" => "10000000000",
            //         "takerFeeRate" => "0.002",
            //         "makerFeeRate" => "0.002",
            //         "pricePrecision" => "6",
            //         "quantityPrecision" => "4",
            //         "quotePrecision" => "6",
            //         "status" => "online",
            //         "minTradeUSDT" => "5",
            //         "buyLimitPriceRatio" => "0.05",
            //         "sellLimitPriceRatio" => "0.05"
            //     }
            //
            // $swap and $future
            //
            //     {
            //         "symbol" => "BTCUSDT",
            //         "baseCoin" => "BTC",
            //         "quoteCoin" => "USDT",
            //         "buyLimitPriceRatio" => "0.01",
            //         "sellLimitPriceRatio" => "0.01",
            //         "feeRateUpRatio" => "0.005",
            //         "makerFeeRate" => "0.0002",
            //         "takerFeeRate" => "0.0006",
            //         "openCostUpRatio" => "0.01",
            //         "supportMarginCoins" => ["USDT"],
            //         "minTradeNum" => "0.001",
            //         "priceEndStep" => "1",
            //         "volumePlace" => "3",
            //         "pricePlace" => "1",
            //         "sizeMultiplier" => "0.001",
            //         "symbolType" => "perpetual",
            //         "minTradeUSDT" => "5",
            //         "maxSymbolOrderNum" => "200",
            //         "maxProductOrderNum" => "400",
            //         "maxPositionNum" => "150",
            //         "symbolStatus" => "normal",
            //         "offTime" => "-1",
            //         "limitOpenTime" => "-1",
            //         "deliveryTime" => "",
            //         "deliveryStartTime" => "",
            //         "deliveryPeriod" => "",
            //         "launchTime" => "",
            //         "fundInterval" => "8",
            //         "minLever" => "1",
            //         "maxLever" => "125",
            //         "posLimit" => "0.05",
            //         "maintainTime" => ""
            //     }
            //
            $result = array();
            for ($i = 0; $i < count($markets); $i++) {
                $market = $markets[$i];
                $marketId = $this->safe_string($market, 'symbol');
                $quoteId = $this->safe_string($market, 'quoteCoin');
                $baseId = $this->safe_string($market, 'baseCoin');
                $quote = $this->safe_currency_code($quoteId);
                $base = $this->safe_currency_code($baseId);
                $supportMarginCoins = $this->safe_value($market, 'supportMarginCoins', array());
                $settleId = null;
                if ($this->in_array($baseId, $supportMarginCoins)) {
                    $settleId = $baseId;
                } elseif ($this->in_array($quoteId, $supportMarginCoins)) {
                    $settleId = $quoteId;
                } else {
                    $settleId = $this->safe_string($supportMarginCoins, 0);
                }
                $settle = $this->safe_currency_code($settleId);
                $symbol = $base . '/' . $quote;
                $type = null;
                $swap = false;
                $spot = false;
                $future = false;
                $contract = false;
                $pricePrecision = null;
                $amountPrecision = null;
                $linear = null;
                $inverse = null;
                $expiry = null;
                $expiryDatetime = null;
                $symbolType = $this->safe_string($market, 'symbolType');
                $marginModes = null;
                $isMarginTradingAllowed = false;
                if ($symbolType === null) {
                    $type = 'spot';
                    $spot = true;
                    $pricePrecision = $this->parse_number($this->parse_precision($this->safe_string($market, 'pricePrecision')));
                    $amountPrecision = $this->parse_number($this->parse_precision($this->safe_string($market, 'quantityPrecision')));
                    $hasCrossMargin = $this->in_array($marketId, $this->options['crossMarginPairsData']);
                    $hasIsolatedMargin = $this->in_array($marketId, $this->options['isolatedMarginPairsData']);
                    $marginModes = array(
                        'cross' => $hasCrossMargin,
                        'isolated' => $hasIsolatedMargin,
                    );
                    $isMarginTradingAllowed = $hasCrossMargin || $hasIsolatedMargin;
                } else {
                    if ($symbolType === 'perpetual') {
                        $type = 'swap';
                        $swap = true;
                        $symbol = $symbol . ':' . $settle;
                    } elseif ($symbolType === 'delivery') {
                        $expiry = $this->safe_integer($market, 'deliveryTime');
                        $expiryDatetime = $this->iso8601($expiry);
                        $expiryParts = explode('-', $expiryDatetime);
                        $yearPart = $this->safe_string($expiryParts, 0);
                        $dayPart = $this->safe_string($expiryParts, 2);
                        $year = mb_substr($yearPart, 2, 4 - 2);
                        $month = $this->safe_string($expiryParts, 1);
                        $day = mb_substr($dayPart, 0, 2 - 0);
                        $expiryString = $year . $month . $day;
                        $type = 'future';
                        $future = true;
                        $symbol = $symbol . ':' . $settle . '-' . $expiryString;
                    }
                    $contract = true;
                    $inverse = ($base === $settle);
                    $linear = !$inverse;
                    $priceDecimals = $this->safe_integer($market, 'pricePlace');
                    $amountDecimals = $this->safe_integer($market, 'volumePlace');
                    $priceStep = $this->safe_string($market, 'priceEndStep');
                    $amountStep = $this->safe_string($market, 'sizeMultiplier');
                    $precise = new Precise ($priceStep);
                    $precise->decimals = max ($precise->decimals, $priceDecimals);
                    $precise->reduce ();
                    $priceString = (string) $precise;
                    $pricePrecision = $this->parse_number($priceString);
                    $preciseAmount = new Precise ($amountStep);
                    $preciseAmount->decimals = max ($preciseAmount->decimals, $amountDecimals);
                    $preciseAmount->reduce ();
                    $amountString = (string) $preciseAmount;
                    $amountPrecision = $this->parse_number($amountString);
                    $marginModes = array(
                        'cross' => true,
                        'isolated' => true,
                    );
                }
                $status = $this->safe_string_2($market, 'status', 'symbolStatus');
                $active = null;
                if ($status !== null) {
                    $active = (($status === 'online') || ($status === 'normal'));
                }
                $minCost = null;
                if ($quote === 'USDT') {
                    $minCost = $this->safe_number($market, 'minTradeUSDT');
                }
                $contractSize = $contract ? 1 : null;
                $result[] = $this->safe_market_structure(array(
                    'id' => $marketId,
                    'symbol' => $symbol,
                    'base' => $base,
                    'quote' => $quote,
                    'settle' => $settle,
                    'baseId' => $baseId,
                    'quoteId' => $quoteId,
                    'settleId' => $settleId,
                    'type' => $type,
                    'spot' => $spot,
                    'margin' => $spot && $isMarginTradingAllowed,
                    'marginModes' => $marginModes,
                    'swap' => $swap,
                    'future' => $future,
                    'option' => false,
                    'active' => $active,
                    'contract' => $contract,
                    'linear' => $linear,
                    'inverse' => $inverse,
                    'taker' => $this->safe_number($market, 'takerFeeRate'),
                    'maker' => $this->safe_number($market, 'makerFeeRate'),
                    'contractSize' => $contractSize,
                    'expiry' => $expiry,
                    'expiryDatetime' => $expiryDatetime,
                    'strike' => null,
                    'optionType' => null,
                    'precision' => array(
                        'amount' => $amountPrecision,
                        'price' => $pricePrecision,
                    ),
                    'limits' => array(
                        'leverage' => array(
                            'min' => $this->safe_number($market, 'minLever'),
                            'max' => $this->safe_number($market, 'maxLever'),
                        ),
                        'amount' => array(
                            'min' => $this->safe_number_2($market, 'minTradeNum', 'minTradeAmount'),
                            'max' => $this->safe_number($market, 'maxTradeAmount'),
                        ),
                        'price' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'cost' => array(
                            'min' => $minCost,
                            'max' => null,
                        ),
                    ),
                    'created' => $this->safe_integer($market, 'launchTime'),
                    'info' => $market,
                ));
            }
            return $result;
        }) ();
    }

    public function fetch_uta_markets($params): PromiseInterface {
        return Async\async(function () use ($params) {
            $subTypes = array( 'SPOT', 'USDT-FUTURES', 'COIN-FUTURES', 'USDC-FUTURES' );
            $promises = array();
            for ($i = 0; $i < count($subTypes); $i++) {
                $req = $this->extend($params, array(
                    'category' => $subTypes[$i],
                ));
                $promises[] = $this->publicUtaGetV3MarketInstruments ($req);
            }
            $results = Async\await(Promise\all($promises));
            $markets = array();
            for ($i = 0; $i < count($results); $i++) {
                $res = $this->safe_dict($results, $i);
                $data = $this->safe_list($res, 'data', array());
                $markets = $this->array_concat($markets, $data);
            }
            //
            // $spot uta
            //
            //     {
            //         "symbol" => "BTCUSDT",
            //         "category" => "SPOT",
            //         "baseCoin" => "BTC",
            //         "quoteCoin" => "USDT",
            //         "buyLimitPriceRatio" => "0.05",
            //         "sellLimitPriceRatio" => "0.05",
            //         "minOrderQty" => "0.000001",
            //         "maxOrderQty" => "0",
            //         "pricePrecision" => "2",
            //         "quantityPrecision" => "6",
            //         "quotePrecision" => "8",
            //         "minOrderAmount" => "1",
            //         "maxSymbolOrderNum" => "400",
            //         "maxProductOrderNum" => "400",
            //         "status" => "online",
            //         "maintainTime" => ""
            //     }
            //
            // margin uta
            //
            //     {
            //         "symbol" => "BTCUSDC",
            //         "category" => "MARGIN",
            //         "baseCoin" => "BTC",
            //         "quoteCoin" => "USDC",
            //         "buyLimitPriceRatio" => "0.05",
            //         "sellLimitPriceRatio" => "0.05",
            //         "minOrderQty" => "0.00001",
            //         "maxOrderQty" => "0",
            //         "pricePrecision" => "2",
            //         "quantityPrecision" => "5",
            //         "quotePrecision" => "7",
            //         "minOrderAmount" => "1",
            //         "maxSymbolOrderNum" => "400",
            //         "maxProductOrderNum" => "400",
            //         "status" => "online",
            //         "maintainTime" => "",
            //         "isIsolatedBaseBorrowable" => "NO",
            //         "isIsolatedQuotedBorrowable" => "NO",
            //         "warningRiskRatio" => "0.8",
            //         "liquidationRiskRatio" => "1",
            //         "maxCrossedLeverage" => "3",
            //         "maxIsolatedLeverage" => "0",
            //         "userMinBorrow" => "0.00000001",
            //         "areaSymbol" => "no"
            //     }
            //
            // $swap and $future uta
            //
            //     {
            //         "symbol" => "BTCPERP",
            //         "category" => "USDC-FUTURES",
            //         "baseCoin" => "BTC",
            //         "quoteCoin" => "USDC",
            //         "buyLimitPriceRatio" => "0.02",
            //         "sellLimitPriceRatio" => "0.02",
            //         "feeRateUpRatio" => "0.005",
            //         "makerFeeRate" => "0.0002",
            //         "takerFeeRate" => "0.0006",
            //         "openCostUpRatio" => "0.01",
            //         "minOrderQty" => "0.0001",
            //         "maxOrderQty" => "",
            //         "pricePrecision" => "1",
            //         "quantityPrecision" => "4",
            //         "quotePrecision" => null,
            //         "priceMultiplier" => "0.5",
            //         "quantityMultiplier" => "0.0001",
            //         "type" => "perpetual",
            //         "minOrderAmount" => "5",
            //         "maxSymbolOrderNum" => "200",
            //         "maxProductOrderNum" => "1000",
            //         "maxPositionNum" => "150",
            //         "status" => "online",
            //         "offTime" => "-1",
            //         "limitOpenTime" => "-1",
            //         "deliveryTime" => "",
            //         "deliveryStartTime" => "",
            //         "deliveryPeriod" => "",
            //         "launchTime" => "",
            //         "fundInterval" => "8",
            //         "minLeverage" => "1",
            //         "maxLeverage" => "125",
            //         "maintainTime" => ""
            //     }
            //
            $result = array();
            for ($i = 0; $i < count($markets); $i++) {
                $market = $markets[$i];
                $category = $this->safe_string($market, 'category');
                $marketId = $this->safe_string($market, 'symbol');
                $quoteId = $this->safe_string($market, 'quoteCoin');
                $baseId = $this->safe_string($market, 'baseCoin');
                $quote = $this->safe_currency_code($quoteId);
                $base = $this->safe_currency_code($baseId);
                $settleId = null;
                $settle = null;
                if ($category === 'USDT-FUTURES') {
                    $settleId = 'USDT';
                } elseif ($category === 'USDC-FUTURES') {
                    $settleId = 'USDC';
                } elseif ($category === 'COIN-FUTURES') {
                    $settleId = $base;
                }
                if ($settleId !== null) {
                    $settle = $this->safe_currency_code($settleId);
                }
                $symbol = $base . '/' . $quote;
                $type = null;
                $swap = false;
                $spot = false;
                $future = false;
                $contract = false;
                $pricePrecision = null;
                $amountPrecision = null;
                $linear = null;
                $inverse = null;
                $expiry = null;
                $expiryDatetime = null;
                $symbolType = $this->safe_string($market, 'type');
                $marginModes = null;
                $isMarginTradingAllowed = false;
                $isUtaMargin = ($category === 'MARGIN');
                if ($isUtaMargin || ($category === 'SPOT')) {
                    $type = 'spot';
                    $spot = true;
                    if ($isUtaMargin) {
                        $isolatedBase = $this->safe_string($market, 'isIsolatedBaseBorrowable');
                        $isolatedQuote = $this->safe_string($market, 'isIsolatedQuotedBorrowable');
                        $isolated = ($isolatedBase === 'YES') || ($isolatedQuote === 'YES');
                        $maxCrossLeverage = $this->safe_string($market, 'maxCrossedLeverage');
                        $cross = ($maxCrossLeverage !== '0');
                        $marginModes = array(
                            'cross' => $cross,
                            'isolated' => $isolated,
                        );
                        $isMarginTradingAllowed = true;
                    }
                } else {
                    if ($symbolType === 'perpetual') {
                        $type = 'swap';
                        $swap = true;
                        $symbol = $symbol . ':' . $settle;
                    } elseif ($symbolType === 'delivery') {
                        $expiry = $this->safe_integer($market, 'deliveryTime');
                        $expiryDatetime = $this->iso8601($expiry);
                        $expiryParts = explode('-', $expiryDatetime);
                        $yearPart = $this->safe_string($expiryParts, 0);
                        $dayPart = $this->safe_string($expiryParts, 2);
                        $year = mb_substr($yearPart, 2, 4 - 2);
                        $month = $this->safe_string($expiryParts, 1);
                        $day = mb_substr($dayPart, 0, 2 - 0);
                        $expiryString = $year . $month . $day;
                        $type = 'future';
                        $future = true;
                        $symbol = $symbol . ':' . $settle . '-' . $expiryString;
                    }
                    $contract = true;
                    $inverse = ($base === $settle);
                    $linear = !$inverse;
                    $marginModes = array(
                        'cross' => true,
                        'isolated' => true,
                    );
                }
                $pricePrecision = $this->parse_number($this->parse_precision($this->safe_string($market, 'pricePrecision')));
                $amountPrecision = $this->parse_number($this->parse_precision($this->safe_string($market, 'quantityPrecision')));
                $status = $this->safe_string($market, 'status');
                $active = null;
                if ($status !== null) {
                    $active = (($status === 'online') || ($status === 'normal'));
                }
                $contractSize = $contract ? 1 : null;
                $result[] = $this->safe_market_structure(array(
                    'id' => $marketId,
                    'symbol' => $symbol,
                    'base' => $base,
                    'quote' => $quote,
                    'settle' => $settle,
                    'baseId' => $baseId,
                    'quoteId' => $quoteId,
                    'settleId' => $settleId,
                    'type' => $type,
                    'spot' => $spot,
                    'margin' => $spot && $isMarginTradingAllowed,
                    'marginModes' => $marginModes,
                    'swap' => $swap,
                    'future' => $future,
                    'option' => false,
                    'active' => $active,
                    'contract' => $contract,
                    'linear' => $linear,
                    'inverse' => $inverse,
                    'taker' => $this->safe_number($market, 'takerFeeRate'),
                    'maker' => $this->safe_number($market, 'makerFeeRate'),
                    'contractSize' => $contractSize,
                    'expiry' => $expiry,
                    'expiryDatetime' => $expiryDatetime,
                    'strike' => null,
                    'optionType' => null,
                    'precision' => array(
                        'amount' => $amountPrecision,
                        'price' => $pricePrecision,
                    ),
                    'limits' => array(
                        'leverage' => array(
                            'min' => $this->safe_number($market, 'minLeverage'),
                            'max' => $this->safe_number($market, 'maxLeverage'),
                        ),
                        'amount' => array(
                            'min' => $this->safe_number($market, 'minOrderQty'),
                            'max' => $this->safe_number($market, 'maxOrderQty'),
                        ),
                        'price' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'cost' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'created' => $this->safe_integer($market, 'launchTime'),
                    'info' => $market,
                ));
            }
            return $result;
        }) ();
    }

    public function fetch_currencies($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetches all available currencies on an exchange
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Coin-List
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an associative dictionary of currencies
             */
            $response = Async\await($this->publicSpotGetV2SpotPublicCoins ($params));
            //
            //    {
            //        "code" => "00000",
            //        "msg" => "success",
            //        "requestTime" => "1746195617812",
            //        "data" => array(
            //            {
            //                "coinId" => "1456",
            //                "coin" => "NEIROETH",
            //                "transfer" => "false",
            //                "chains" => [
            //                    array(
            //                        "chain" => "ERC20",
            //                        "needTag" => "false",
            //                        "withdrawable" => "true",
            //                        "rechargeable" => "true",
            //                        "withdrawFee" => "44.91017965",
            //                        "extraWithdrawFee" => "0",
            //                        "depositConfirm" => "12",
            //                        "withdrawConfirm" => "64",
            //                        "minDepositAmount" => "0.06",
            //                        "minWithdrawAmount" => "60",
            //                        "browserUrl" => "https://etherscan.io/tx/",
            //                        "contractAddress" => "0xee2a03aa6dacf51c18679c516ad5283d8e7c2637",
            //                        "withdrawStep" => "0",
            //                        "withdrawMinScale" => "8",
            //                        "congestion" => "normal"
            //                    }
            //                ),
            //                "areaCoin" => "no"
            //            ),
            //            ...
            //
            $result = array();
            $data = $this->safe_value($response, 'data', array());
            $fiatCurrencies = $this->safe_list($this->options, 'fiatCurrencies', array());
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $id = $this->safe_string($entry, 'coin'); // we don't use 'coinId' has no use. it is 'coin' field that needs to be used in currency related endpoints (deposit, withdraw, etc..)
                $code = $this->safe_currency_code($id);
                $chains = $this->safe_value($entry, 'chains', array());
                $networks = array();
                for ($j = 0; $j < count($chains); $j++) {
                    $chain = $chains[$j];
                    $networkId = $this->safe_string($chain, 'chain');
                    $network = $this->network_id_to_code($networkId, $code);
                    $network = strtoupper($network);
                    $networks[$network] = array(
                        'info' => $chain,
                        'id' => $networkId,
                        'network' => $network,
                        'limits' => array(
                            'withdraw' => array(
                                'min' => $this->safe_number($chain, 'minWithdrawAmount'),
                                'max' => null,
                            ),
                            'deposit' => array(
                                'min' => $this->safe_number($chain, 'minDepositAmount'),
                                'max' => null,
                            ),
                        ),
                        'active' => null,
                        'withdraw' => $this->safe_string($chain, 'withdrawable') === 'true',
                        'deposit' => $this->safe_string($chain, 'rechargeable') === 'true',
                        'fee' => $this->safe_number($chain, 'withdrawFee'),
                        'precision' => $this->parse_number($this->parse_precision($this->safe_string($chain, 'withdrawMinScale'))),
                    );
                }
                $isFiat = $this->in_array($code, $fiatCurrencies);
                $result[$code] = $this->safe_currency_structure(array(
                    'info' => $entry,
                    'id' => $id,
                    'code' => $code,
                    'networks' => $networks,
                    'type' => $isFiat ? 'fiat' : 'crypto',
                    'name' => null,
                    'active' => null,
                    'deposit' => null,
                    'withdraw' => null,
                    'fee' => null,
                    'precision' => null,
                    'limits' => array(
                        'amount' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'withdraw' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'deposit' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'created' => null,
                ));
            }
            return $result;
        }) ();
    }

    public function fetch_market_leverage_tiers(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes for a single $market
             *
             * @see https://www.bitget.com/api-doc/contract/position/Get-Query-Position-Lever
             * @see https://www.bitget.com/api-doc/margin/cross/account/Cross-Tier-Data
             * @see https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Tier-Data
             * @see https://www.bitget.com/api-doc/uta/public/Get-Position-Tier-Data
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] for spot margin 'cross' or 'isolated', default is 'isolated'
             * @param {string} [$params->code] required for cross spot margin
             * @param {string} [$params->productType] *contract and $uta only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=leverage-tiers-structure leverage tiers structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array();
            $response = null;
            $marginMode = null;
            $productType = null;
            $uta = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchMarketLeverageTiers', $params, 'isolated');
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchMarketLeverageTiers', 'uta', false);
            if ($uta) {
                if ($productType === 'SPOT') {
                    if ($marginMode !== null) {
                        $productType = 'MARGIN';
                    }
                }
                $request['symbol'] = $market['id'];
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketPositionTier ($this->extend($request, $params)));
            } elseif (($market['swap']) || ($market['future'])) {
                $request['productType'] = $productType;
                $request['symbol'] = $market['id'];
                $response = Async\await($this->publicMixGetV2MixMarketQueryPositionLever ($this->extend($request, $params)));
            } elseif ($marginMode === 'isolated') {
                $request['symbol'] = $market['id'];
                $response = Async\await($this->privateMarginGetV2MarginIsolatedTierData ($this->extend($request, $params)));
            } elseif ($marginMode === 'cross') {
                $code = $this->safe_string($params, 'code');
                if ($code === null) {
                    throw new ArgumentsRequired($this->id . ' fetchMarketLeverageTiers() requires a $code argument');
                }
                $params = $this->omit($params, 'code');
                $currency = $this->currency($code);
                $request['coin'] = $currency['id'];
                $response = Async\await($this->privateMarginGetV2MarginCrossedTierData ($this->extend($request, $params)));
            } else {
                throw new BadRequest($this->id . ' fetchMarketLeverageTiers() $symbol does not support $market ' . $market['symbol']);
            }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700290724614,
            //         "data" => array(
            //             array(
            //                 "symbol" => "BTCUSDT",
            //                 "level" => "1",
            //                 "startUnit" => "0",
            //                 "endUnit" => "150000",
            //                 "leverage" => "125",
            //                 "keepMarginRate" => "0.004"
            //             ),
            //         )
            //     }
            //
            // isolated
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700291531894,
            //         "data" => array(
            //             array(
            //                 "tier" => "1",
            //                 "symbol" => "BTCUSDT",
            //                 "leverage" => "10",
            //                 "baseCoin" => "BTC",
            //                 "quoteCoin" => "USDT",
            //                 "baseMaxBorrowableAmount" => "2",
            //                 "quoteMaxBorrowableAmount" => "24000",
            //                 "maintainMarginRate" => "0.05",
            //                 "initRate" => "0.1111"
            //             ),
            //         )
            //     }
            //
            // cross
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700291818831,
            //         "data" => array(
            //             {
            //                 "tier" => "1",
            //                 "leverage" => "3",
            //                 "coin" => "BTC",
            //                 "maxBorrowableAmount" => "26",
            //                 "maintainMarginRate" => "0.1"
            //             }
            //         )
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1752735673127,
            //         "data" => array(
            //             array(
            //                 "tier" => "1",
            //                 "minTierValue" => "0",
            //                 "maxTierValue" => "150000",
            //                 "leverage" => "125",
            //                 "mmr" => "0.004"
            //             ),
            //         )
            //     }
            //
            $result = $this->safe_value($response, 'data', array());
            return $this->parse_market_leverage_tiers($result, $market);
        }) ();
    }

    public function parse_market_leverage_tiers($info, ?array $market = null): array {
        //
        // swap and future
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "level" => "1",
        //         "startUnit" => "0",
        //         "endUnit" => "150000",
        //         "leverage" => "125",
        //         "keepMarginRate" => "0.004"
        //     }
        //
        // isolated
        //
        //     {
        //         "tier" => "1",
        //         "symbol" => "BTCUSDT",
        //         "leverage" => "10",
        //         "baseCoin" => "BTC",
        //         "quoteCoin" => "USDT",
        //         "baseMaxBorrowableAmount" => "2",
        //         "quoteMaxBorrowableAmount" => "24000",
        //         "maintainMarginRate" => "0.05",
        //         "initRate" => "0.1111"
        //     }
        //
        // cross
        //
        //     {
        //         "tier" => "1",
        //         "leverage" => "3",
        //         "coin" => "BTC",
        //         "maxBorrowableAmount" => "26",
        //         "maintainMarginRate" => "0.1"
        //     }
        //
        // uta
        //
        //     {
        //         "tier" => "1",
        //         "minTierValue" => "0",
        //         "maxTierValue" => "150000",
        //         "leverage" => "125",
        //         "mmr" => "0.004"
        //     }
        //
        $tiers = array();
        $minNotional = 0;
        for ($i = 0; $i < count($info); $i++) {
            $item = $info[$i];
            $minimumNotional = $this->safe_number_2($item, 'startUnit', 'minTierValue');
            if ($minimumNotional !== null) {
                $minNotional = $minimumNotional;
            }
            $maxNotional = $this->safe_number_n($item, array( 'endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount', 'maxTierValue' ));
            $marginCurrency = $this->safe_string_2($item, 'coin', 'baseCoin');
            $currencyId = ($marginCurrency !== null) ? $marginCurrency : $market['base'];
            $marketId = $this->safe_string($item, 'symbol');
            $tiers[] = array(
                'tier' => $this->safe_integer_2($item, 'level', 'tier'),
                'symbol' => $this->safe_symbol($marketId, $market),
                'currency' => $this->safe_currency_code($currencyId),
                'minNotional' => $minNotional,
                'maxNotional' => $maxNotional,
                'maintenanceMarginRate' => $this->safe_number_n($item, array( 'keepMarginRate', 'maintainMarginRate', 'mmr' )),
                'maxLeverage' => $this->safe_number($item, 'leverage'),
                'info' => $item,
            );
            $minNotional = $maxNotional;
        }
        return $tiers;
    }

    public function fetch_deposits(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch all deposits made to an account
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Deposit-Record
             *
             * @param {string} $code unified $currency $code
             * @param {int} [$since] the earliest time in ms to fetch deposits for
             * @param {int} [$limit] the maximum number of deposits structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] end time in milliseconds
             * @param {string} [$params->idLessThan] return records with id less than the provided value
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transaction-structure transaction structures~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchDeposits', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchDeposits', null, $since, $limit, $params, 'idLessThan', 'idLessThan', null, 100));
            }
            if ($since === null) {
                $since = $this->milliseconds() - 7776000000; // 90 days
            }
            $request = array(
                'startTime' => $since,
                'endTime' => $this->milliseconds(),
            );
            $currency = null;
            if ($code !== null) {
                $currency = $this->currency($code);
                $request['coin'] = $currency['id'];
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            $response = Async\await($this->privateSpotGetV2SpotWalletDepositRecords ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700528340608,
            //         "data" => array(
            //             {
            //                 "orderId" => "1083832260799930368",
            //                 "tradeId" => "35bf0e588a42b25c71a9d45abe7308cabdeec6b7b423910b9bd4743d3a9a9efa",
            //                 "coin" => "BTC",
            //                 "type" => "deposit",
            //                 "size" => "0.00030000",
            //                 "status" => "success",
            //                 "toAddress" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
            //                 "dest" => "on_chain",
            //                 "chain" => "BTC",
            //                 "fromAddress" => null,
            //                 "cTime" => "1694131668281",
            //                 "uTime" => "1694131680247"
            //             }
            //         )
            //     }
            //
            $rawTransactions = $this->safe_list($response, 'data', array());
            return $this->parse_transactions($rawTransactions, null, $since, $limit);
        }) ();
    }

    public function withdraw(string $code, float $amount, string $address, ?string $tag = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $amount, $address, $tag, $params) {
            /**
             * make a withdrawal
             *
             * @see https://www.bitget.com/api-doc/spot/account/Wallet-Withdrawal
             *
             * @param {string} $code unified $currency $code
             * @param {float} $amount the $amount to withdraw
             * @param {string} $address the $address to withdraw to
             * @param {string} $tag
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->chain] the blockchain network the withdrawal is taking place on
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=transaction-structure transaction structure~
             */
            $this->check_address($address);
            $networkCode = null;
            list($networkCode, $params) = $this->handle_network_code_and_params($params);
            if ($networkCode === null) {
                throw new ArgumentsRequired($this->id . ' withdraw() requires a "network" parameter');
            }
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $networkId = $this->network_code_to_id($networkCode);
            $request = array(
                'coin' => $currency['id'],
                'address' => $address,
                'chain' => $networkId,
                'size' => $this->currency_to_precision($code, $amount, $networkCode),
                'transferType' => 'on_chain',
            );
            if ($tag !== null) {
                $request['tag'] = $tag;
            }
            $response = Async\await($this->privateSpotPostV2SpotWalletWithdrawal ($this->extend($request, $params)));
            //
            //     {
            //          "code":"00000",
            //          "msg":"success",
            //          "requestTime":1696784219602,
            //          "data" => {
            //              "orderId":"1094957867615789056",
            //              "clientOid":"64f1e4ce842041d296b4517df1b5c2d7"
            //          }
            //      }
            //
            $data = $this->safe_value($response, 'data', array());
            $result = $this->parse_transaction($data, $currency);
            $result['type'] = 'withdrawal';
            $withdrawOptions = $this->safe_value($this->options, 'withdraw', array());
            $fillResponseFromRequest = $this->safe_bool($withdrawOptions, 'fillResponseFromRequest', true);
            if ($fillResponseFromRequest) {
                $result['currency'] = $code;
                $result['amount'] = $amount;
                $result['tag'] = $tag;
                $result['address'] = $address;
                $result['addressTo'] = $address;
                $result['network'] = $networkCode;
            }
            return $result;
        }) ();
    }

    public function fetch_withdrawals(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch all withdrawals made from an account
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Withdraw-Record
             *
             * @param {string} $code unified $currency $code
             * @param {int} [$since] the earliest time in ms to fetch withdrawals for
             * @param {int} [$limit] the maximum number of withdrawals structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] end time in milliseconds
             * @param {string} [$params->idLessThan] return records with id less than the provided value
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transaction-structure transaction structures~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchWithdrawals', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchWithdrawals', null, $since, $limit, $params, 'idLessThan', 'idLessThan', null, 100));
            }
            $currency = null;
            if ($code !== null) {
                $currency = $this->currency($code);
            }
            if ($since === null) {
                $since = $this->milliseconds() - 7776000000; // 90 days
            }
            $request = array(
                'startTime' => $since,
                'endTime' => $this->milliseconds(),
            );
            if ($currency !== null) {
                $request['coin'] = $currency['id'];
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->privateSpotGetV2SpotWalletWithdrawalRecords ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700528340608,
            //         "data" => array(
            //             {
            //                 "orderId" => "1083832260799930368",
            //                 "tradeId" => "35bf0e588a42b25c71a9d45abe7308cabdeec6b7b423910b9bd4743d3a9a9efa",
            //                 "clientOid" => "123",
            //                 "coin" => "BTC",
            //                 "type" => "withdraw",
            //                 "size" => "0.00030000",
            //                 "fee" => "-1.0000000",
            //                 "status" => "success",
            //                 "toAddress" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
            //                 "dest" => "on_chain",
            //                 "chain" => "BTC",
            //                 "confirm" => "100",
            //                 "fromAddress" => null,
            //                 "cTime" => "1694131668281",
            //                 "uTime" => "1694131680247"
            //             }
            //         )
            //     }
            //
            $rawTransactions = $this->safe_list($response, 'data', array());
            return $this->parse_transactions($rawTransactions, $currency, $since, $limit);
        }) ();
    }

    public function parse_transaction(array $transaction, ?array $currency = null): array {
        //
        // fetchDeposits
        //
        //     {
        //         "orderId" => "1083832260799930368",
        //         "tradeId" => "35bf0e588a42b25c71a9d45abe7308cabdeec6b7b423910b9bd4743d3a9a9efa",
        //         "coin" => "BTC",
        //         "type" => "deposit",
        //         "size" => "0.00030000",
        //         "status" => "success",
        //         "toAddress" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
        //         "dest" => "on_chain",
        //         "chain" => "BTC",
        //         "fromAddress" => null,
        //         "cTime" => "1694131668281",
        //         "uTime" => "1694131680247"
        //     }
        //
        // fetchWithdrawals
        //
        //     {
        //         "orderId" => "1083832260799930368",
        //         "tradeId" => "35bf0e588a42b25c71a9d45abe7308cabdeec6b7b423910b9bd4743d3a9a9efa",
        //         "clientOid" => "123",
        //         "coin" => "BTC",
        //         "type" => "withdraw",
        //         "size" => "0.00030000",
        //         "fee" => "-1.0000000",
        //         "status" => "success",
        //         "toAddress" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
        //         "dest" => "on_chain",
        //         "chain" => "BTC",
        //         "confirm" => "100",
        //         "fromAddress" => null,
        //         "cTime" => "1694131668281",
        //         "uTime" => "1694131680247"
        //     }
        //
        $currencyId = $this->safe_string($transaction, 'coin');
        $code = $this->safe_currency_code($currencyId, $currency);
        $timestamp = $this->safe_integer($transaction, 'cTime');
        $networkId = $this->safe_string($transaction, 'chain');
        $status = $this->safe_string($transaction, 'status');
        $tag = $this->safe_string($transaction, 'tag');
        $feeCostString = $this->safe_string($transaction, 'fee');
        $feeCostAbsString = null;
        if ($feeCostString !== null) {
            $feeCostAbsString = Precise::string_abs($feeCostString);
        }
        $fee = null;
        $amountString = $this->safe_string($transaction, 'size');
        if ($feeCostAbsString !== null) {
            $fee = array( 'currency' => $code, 'cost' => $this->parse_number($feeCostAbsString) );
            $amountString = Precise::string_sub($amountString, $feeCostAbsString);
        }
        return array(
            'id' => $this->safe_string($transaction, 'orderId'),
            'info' => $transaction,
            'txid' => $this->safe_string($transaction, 'tradeId'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'network' => $this->network_id_to_code($networkId),
            'addressFrom' => $this->safe_string($transaction, 'fromAddress'),
            'address' => $this->safe_string($transaction, 'toAddress'),
            'addressTo' => $this->safe_string($transaction, 'toAddress'),
            'amount' => $this->parse_number($amountString),
            'type' => $this->safe_string($transaction, 'type'),
            'currency' => $code,
            'status' => $this->parse_transaction_status($status),
            'updated' => $this->safe_integer($transaction, 'uTime'),
            'tagFrom' => null,
            'tag' => $tag,
            'tagTo' => $tag,
            'comment' => null,
            'internal' => null,
            'fee' => $fee,
        );
    }

    public function parse_transaction_status(?string $status) {
        $statuses = array(
            'success' => 'ok',
            'Pending' => 'pending',
            'pending_review' => 'pending',
            'pending_review_fail' => 'failed',
            'reject' => 'failed',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function fetch_deposit_address(string $code, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $params) {
            /**
             * fetch the deposit address for a $currency associated with this account
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Deposit-Address
             *
             * @param {string} $code unified $currency $code
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=address-structure address structure~
             */
            Async\await($this->load_markets());
            $networkCode = null;
            list($networkCode, $params) = $this->handle_network_code_and_params($params);
            $currency = $this->currency($code);
            $request = array(
                'coin' => $currency['id'],
            );
            if ($networkCode !== null) {
                $request['chain'] = $this->network_code_to_id($networkCode, $code);
            }
            $response = Async\await($this->privateSpotGetV2SpotWalletDepositAddress ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700532244807,
            //         "data" => {
            //             "coin" => "BTC",
            //             "address" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
            //             "chain" => "",
            //             "tag" => null,
            //             "url" => "https://blockchair.com/bitcoin/transaction/"
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_deposit_address($data, $currency);
        }) ();
    }

    public function parse_deposit_address($depositAddress, ?array $currency = null): array {
        //
        //     {
        //         "coin" => "BTC",
        //         "address" => "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
        //         "chain" => "",
        //         "tag" => null,
        //         "url" => "https://blockchair.com/bitcoin/transaction/"
        //     }
        //
        $currencyId = $this->safe_string($depositAddress, 'coin');
        $networkId = $this->safe_string($depositAddress, 'chain');
        $parsedCurrency = $this->safe_currency_code($currencyId, $currency);
        $network = null;
        if ($networkId !== null) {
            $network = $this->network_id_to_code($networkId, $parsedCurrency);
        }
        return array(
            'info' => $depositAddress,
            'currency' => $parsedCurrency,
            'network' => $network,
            'address' => $this->safe_string($depositAddress, 'address'),
            'tag' => $this->safe_string($depositAddress, 'tag'),
        );
    }

    public function fetch_order_book(string $symbol, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $limit, $params) {
            /**
             * fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other $data
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Orderbook
             * @see https://www.bitget.com/api-doc/contract/market/Get-Merge-Depth
             * @see https://www.bitget.com/api-doc/uta/public/OrderBook
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the order book for
             * @param {int} [$limit] the maximum amount of order book entries to return
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} A dictionary of ~@link https://docs.ccxt.com/#/?id=order-book-structure order book structures~ indexed by $market symbols
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchOrderBook', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketOrderbook ($this->extend($request, $params)));
            } elseif ($market['spot']) {
                $response = Async\await($this->publicSpotGetV2SpotMarketOrderbook ($this->extend($request, $params)));
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketMergeDepth ($this->extend($request, $params)));
            }
            //
            //     {
            //       "code" => "00000",
            //       "msg" => "success",
            //       "requestTime" => 1645854610294,
            //       "data" => {
            //         "asks" => array( array( "39102", "11.026" ) ),
            //         "bids" => array( array( '39100.5', "1.773" ) ),
            //         "ts" => "1645854610294"
            //       }
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750329437753,
            //         "data" => {
            //             "a" => array( array( 104992.60, 0.018411 ) ),
            //             "b":array( [104927.40, 0.229914 ) ],
            //             "ts" => "1750329437763"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $bidsKey = $uta ? 'b' : 'bids';
            $asksKey = $uta ? 'a' : 'asks';
            $timestamp = $this->safe_integer($data, 'ts');
            return $this->parse_order_book($data, $market['symbol'], $timestamp, $bidsKey, $asksKey);
        }) ();
    }

    public function parse_ticker(array $ticker, ?array $market = null): array {
        //
        //   {
        //       "symbol" => "BTCUSDT",
        //       "price" => "26242",
        //       "indexPrice" => "34867",
        //       "markPrice" => "25555",
        //       "ts" => "1695793390482"
        //   }
        //
        // spot
        //
        //     {
        //         "open" => "37202.46",
        //         "symbol" => "BTCUSDT",
        //         "high24h" => "37744.75",
        //         "low24h" => "36666",
        //         "lastPr" => "37583.69",
        //         "quoteVolume" => "519127705.303",
        //         "baseVolume" => "13907.0386",
        //         "usdtVolume" => "519127705.302908",
        //         "ts" => "1700532903261",
        //         "bidPr" => "37583.68",
        //         "askPr" => "37583.69",
        //         "bidSz" => "0.0007",
        //         "askSz" => "0.0829",
        //         "openUtc" => "37449.4",
        //         "changeUtc24h" => "0.00359",
        //         "change24h" => "0.00321"
        //     }
        //
        // swap and future
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "lastPr" => "104823.8",
        //         "askPr" => "104823.8",
        //         "bidPr" => "104823.5",
        //         "bidSz" => "0.703",
        //         "askSz" => "13.894",
        //         "high24h" => "105289.3",
        //         "low24h" => "103447.9",
        //         "ts" => "1750332210370",
        //         "change24h" => "0.00471",
        //         "baseVolume" => "79089.5675",
        //         "quoteVolume" => "8274870921.80485",
        //         "usdtVolume" => "8274870921.80485",
        //         "openUtc" => "104833",
        //         "changeUtc24h" => "-0.00009",
        //         "indexPrice" => "104881.953125",
        //         "fundingRate" => "-0.000014",
        //         "holdingAmount" => "7452.6421",
        //         "deliveryStartTime" => null,
        //         "deliveryTime" => null,
        //         "deliveryStatus" => "",
        //         "open24h" => "104332.3",
        //         "markPrice" => "104824.2"
        //     }
        //
        // spot uta
        //
        //     {
        //         "category" => "SPOT",
        //         "symbol" => "BTCUSDT",
        //         "ts" => "1750330651972",
        //         "lastPrice" => "104900.2",
        //         "openPrice24h" => "104321.2",
        //         "highPrice24h" => "107956.8",
        //         "lowPrice24h" => "103600.1",
        //         "ask1Price" => "104945.8",
        //         "bid1Price" => "104880.6",
        //         "bid1Size" => "0.266534",
        //         "ask1Size" => "0.014001",
        //         "price24hPcnt" => "0.00555",
        //         "volume24h" => "355.941109",
        //         "turnover24h" => "37302936.008134"
        //     }
        //
        // swap and future uta
        //
        //     {
        //         "category" => "USDT-FUTURES",
        //         "symbol" => "BTCUSDT",
        //         "ts" => "1750332730472",
        //         "lastPrice" => "104738",
        //         "openPrice24h" => "104374",
        //         "highPrice24h" => "105289.3",
        //         "lowPrice24h" => "103447.9",
        //         "ask1Price" => "104738",
        //         "bid1Price" => "104737.7",
        //         "bid1Size" => "2.036",
        //         "ask1Size" => "8.094",
        //         "price24hPcnt" => "0.00349",
        //         "volume24h" => "79101.6477",
        //         "turnover24h" => "8276293391.45973",
        //         "indexPrice" => "104785.956168",
        //         "markPrice" => "104738",
        //         "fundingRate" => "-0.000007",
        //         "openInterest" => "7465.5938",
        //         "deliveryStartTime" => "",
        //         "deliveryTime" => "",
        //         "deliveryStatus" => ""
        //     }
        //
        $marketId = $this->safe_string($ticker, 'symbol');
        $close = $this->safe_string_2($ticker, 'lastPr', 'lastPrice');
        $timestamp = $this->safe_integer_omit_zero($ticker, 'ts'); // exchange bitget provided 0
        $change = $this->safe_string($ticker, 'change24h');
        $category = $this->safe_string($ticker, 'category');
        $markPrice = $this->safe_string($ticker, 'markPrice');
        if (($markPrice !== null) && ($category !== 'SPOT')) {
            $marketType = 'contract';
        } else {
            $marketType = 'spot';
        }
        $percentage = $this->safe_string($ticker, 'price24hPcnt');
        if ($percentage === null) {
            $percentage = Precise::string_mul($change, '100');
        }
        return $this->safe_ticker(array(
            'symbol' => $this->safe_symbol($marketId, $market, null, $marketType),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'high' => $this->safe_string_2($ticker, 'high24h', 'highPrice24h'),
            'low' => $this->safe_string_2($ticker, 'low24h', 'lowPrice24h'),
            'bid' => $this->safe_string_2($ticker, 'bidPr', 'bid1Price'),
            'bidVolume' => $this->safe_string_2($ticker, 'bidSz', 'bid1Size'),
            'ask' => $this->safe_string_2($ticker, 'askPr', 'ask1Price'),
            'askVolume' => $this->safe_string_2($ticker, 'askSz', 'ask1Size'),
            'vwap' => null,
            'open' => $this->safe_string_n($ticker, array( 'open', 'open24h', 'openPrice24h' )),
            'close' => $close,
            'last' => $close,
            'previousClose' => null,
            'change' => $change,
            'percentage' => $percentage,
            'average' => null,
            'baseVolume' => $this->safe_string_2($ticker, 'baseVolume', 'volume24h'),
            'quoteVolume' => $this->safe_string_2($ticker, 'quoteVolume', 'turnover24h'),
            'indexPrice' => $this->safe_string($ticker, 'indexPrice'),
            'markPrice' => $markPrice,
            'info' => $ticker,
        ), $market);
    }

    public function fetch_ticker(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific $market
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Tickers
             * @see https://www.bitget.com/api-doc/contract/market/Get-Ticker
             * @see https://www.bitget.com/api-doc/uta/public/Tickers
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the ticker for
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchTicker', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketTickers ($this->extend($request, $params)));
            } elseif ($market['spot']) {
                $response = Async\await($this->publicSpotGetV2SpotMarketTickers ($this->extend($request, $params)));
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketTicker ($this->extend($request, $params)));
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700532903782,
            //         "data" => array(
            //             {
            //                 "open" => "37202.46",
            //                 "symbol" => "BTCUSDT",
            //                 "high24h" => "37744.75",
            //                 "low24h" => "36666",
            //                 "lastPr" => "37583.69",
            //                 "quoteVolume" => "519127705.303",
            //                 "baseVolume" => "13907.0386",
            //                 "usdtVolume" => "519127705.302908",
            //                 "ts" => "1700532903261",
            //                 "bidPr" => "37583.68",
            //                 "askPr" => "37583.69",
            //                 "bidSz" => "0.0007",
            //                 "askSz" => "0.0829",
            //                 "openUtc" => "37449.4",
            //                 "changeUtc24h" => "0.00359",
            //                 "change24h" => "0.00321"
            //             }
            //         )
            //     }
            //
            // swap and future
            //
            //      {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750332210369,
            //         "data" => array(
            //             {
            //                 "symbol" => "BTCUSDT",
            //                 "lastPr" => "104823.8",
            //                 "askPr" => "104823.8",
            //                 "bidPr" => "104823.5",
            //                 "bidSz" => "0.703",
            //                 "askSz" => "13.894",
            //                 "high24h" => "105289.3",
            //                 "low24h" => "103447.9",
            //                 "ts" => "1750332210370",
            //                 "change24h" => "0.00471",
            //                 "baseVolume" => "79089.5675",
            //                 "quoteVolume" => "8274870921.80485",
            //                 "usdtVolume" => "8274870921.80485",
            //                 "openUtc" => "104833",
            //                 "changeUtc24h" => "-0.00009",
            //                 "indexPrice" => "104881.953125",
            //                 "fundingRate" => "-0.000014",
            //                 "holdingAmount" => "7452.6421",
            //                 "deliveryStartTime" => null,
            //                 "deliveryTime" => null,
            //                 "deliveryStatus" => "",
            //                 "open24h" => "104332.3",
            //                 "markPrice" => "104824.2"
            //             }
            //         )
            //     }
            //
            // spot $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750330653575,
            //         "data" => array(
            //             {
            //                 "category" => "SPOT",
            //                 "symbol" => "BTCUSDT",
            //                 "ts" => "1750330651972",
            //                 "lastPrice" => "104900.2",
            //                 "openPrice24h" => "104321.2",
            //                 "highPrice24h" => "107956.8",
            //                 "lowPrice24h" => "103600.1",
            //                 "ask1Price" => "104945.8",
            //                 "bid1Price" => "104880.6",
            //                 "bid1Size" => "0.266534",
            //                 "ask1Size" => "0.014001",
            //                 "price24hPcnt" => "0.00555",
            //                 "volume24h" => "355.941109",
            //                 "turnover24h" => "37302936.008134"
            //             }
            //         )
            //     }
            //
            // swap and future $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750332731203,
            //         "data" => array(
            //             {
            //                 "category" => "USDT-FUTURES",
            //                 "symbol" => "BTCUSDT",
            //                 "ts" => "1750332730472",
            //                 "lastPrice" => "104738",
            //                 "openPrice24h" => "104374",
            //                 "highPrice24h" => "105289.3",
            //                 "lowPrice24h" => "103447.9",
            //                 "ask1Price" => "104738",
            //                 "bid1Price" => "104737.7",
            //                 "bid1Size" => "2.036",
            //                 "ask1Size" => "8.094",
            //                 "price24hPcnt" => "0.00349",
            //                 "volume24h" => "79101.6477",
            //                 "turnover24h" => "8276293391.45973",
            //                 "indexPrice" => "104785.956168",
            //                 "markPrice" => "104738",
            //                 "fundingRate" => "-0.000007",
            //                 "openInterest" => "7465.5938",
            //                 "deliveryStartTime" => "",
            //                 "deliveryTime" => "",
            //                 "deliveryStatus" => ""
            //             }
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_ticker($data[0], $market);
        }) ();
    }

    public function fetch_mark_price(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetches the mark price for a specific $market
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-Symbol-Price
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the ticker for
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $response = null;
            if ($market['spot']) {
                throw new NotSupported($this->id . ' fetchMarkPrice() is not supported for spot markets');
            } else {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketSymbolPrice ($this->extend($request, $params)));
            }
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_ticker($data[0], $market);
        }) ();
    }

    public function fetch_tickers(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each $market
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Tickers
             * @see https://www.bitget.com/api-doc/contract/market/Get-All-Symbol-Ticker
             * @see https://www.bitget.com/api-doc/uta/public/Tickers
             *
             * @param {string[]|null} $symbols unified $symbols of the markets to fetch the ticker for, all $market tickers are returned if not assigned
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {string} [$params->subType] *contract only* 'linear', 'inverse'
             * @param {string} [$params->productType] *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structures~
             */
            Async\await($this->load_markets());
            $market = null;
            if ($symbols !== null) {
                $symbol = $this->safe_value($symbols, 0);
                $market = $this->market($symbol);
            }
            $response = null;
            $request = array();
            $type = null;
            list($type, $params) = $this->handle_market_type_and_params('fetchTickers', $market, $params);
            // Calls like `.fetchTickers (null, array(subType:'inverse'))` should be supported for this exchange, so
            // as "options.defaultSubType" is also set in exchange options, we should consider `$params->subType`
            // with higher priority and only default to spot, if `subType` is not set in $params
            $passedSubType = $this->safe_string($params, 'subType');
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            // only if $passedSubType && $productType is null, then use spot
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchTickers', 'uta', false);
            if ($uta) {
                $symbolsLength = count($symbols);
                if (($symbols !== null) && ($symbolsLength === 1)) {
                    $request['symbol'] = $market['id'];
                }
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketTickers ($this->extend($request, $params)));
            } elseif ($type === 'spot' && $passedSubType === null) {
                $response = Async\await($this->publicSpotGetV2SpotMarketTickers ($this->extend($request, $params)));
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketTickers ($this->extend($request, $params)));
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700532903782,
            //         "data" => array(
            //             {
            //                 "open" => "37202.46",
            //                 "symbol" => "BTCUSDT",
            //                 "high24h" => "37744.75",
            //                 "low24h" => "36666",
            //                 "lastPr" => "37583.69",
            //                 "quoteVolume" => "519127705.303",
            //                 "baseVolume" => "13907.0386",
            //                 "usdtVolume" => "519127705.302908",
            //                 "ts" => "1700532903261",
            //                 "bidPr" => "37583.68",
            //                 "askPr" => "37583.69",
            //                 "bidSz" => "0.0007",
            //                 "askSz" => "0.0829",
            //                 "openUtc" => "37449.4",
            //                 "changeUtc24h" => "0.00359",
            //                 "change24h" => "0.00321"
            //             }
            //         )
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700533773477,
            //         "data" => array(
            //             array(
            //                 "open" => "14.9776",
            //                 "symbol" => "LINKUSDT",
            //                 "high24h" => "15.3942",
            //                 "low24h" => "14.3457",
            //                 "lastPr" => "14.3748",
            //                 "quoteVolume" => "7008612.4299",
            //                 "baseVolume" => "469908.8523",
            //                 "usdtVolume" => "7008612.42986561",
            //                 "ts" => "1700533772309",
            //                 "bidPr" => "14.375",
            //                 "askPr" => "14.3769",
            //                 "bidSz" => "50.004",
            //                 "askSz" => "0.7647",
            //                 "openUtc" => "14.478",
            //                 "changeUtc24h" => "-0.00713",
            //                 "change24h" => "-0.04978"
            //             ),
            //         )
            //     }
            //
            // spot $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750330653575,
            //         "data" => array(
            //             {
            //                 "category" => "SPOT",
            //                 "symbol" => "BTCUSDT",
            //                 "ts" => "1750330651972",
            //                 "lastPrice" => "104900.2",
            //                 "openPrice24h" => "104321.2",
            //                 "highPrice24h" => "107956.8",
            //                 "lowPrice24h" => "103600.1",
            //                 "ask1Price" => "104945.8",
            //                 "bid1Price" => "104880.6",
            //                 "bid1Size" => "0.266534",
            //                 "ask1Size" => "0.014001",
            //                 "price24hPcnt" => "0.00555",
            //                 "volume24h" => "355.941109",
            //                 "turnover24h" => "37302936.008134"
            //             }
            //         )
            //     }
            //
            // swap and future $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750332731203,
            //         "data" => array(
            //             {
            //                 "category" => "USDT-FUTURES",
            //                 "symbol" => "BTCUSDT",
            //                 "ts" => "1750332730472",
            //                 "lastPrice" => "104738",
            //                 "openPrice24h" => "104374",
            //                 "highPrice24h" => "105289.3",
            //                 "lowPrice24h" => "103447.9",
            //                 "ask1Price" => "104738",
            //                 "bid1Price" => "104737.7",
            //                 "bid1Size" => "2.036",
            //                 "ask1Size" => "8.094",
            //                 "price24hPcnt" => "0.00349",
            //                 "volume24h" => "79101.6477",
            //                 "turnover24h" => "8276293391.45973",
            //                 "indexPrice" => "104785.956168",
            //                 "markPrice" => "104738",
            //                 "fundingRate" => "-0.000007",
            //                 "openInterest" => "7465.5938",
            //                 "deliveryStartTime" => "",
            //                 "deliveryTime" => "",
            //                 "deliveryStatus" => ""
            //             }
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_tickers($data, $symbols);
        }) ();
    }

    public function parse_trade(array $trade, ?array $market = null): array {
        //
        // spot, swap and future => fetchTrades
        //
        //     {
        //         "tradeId" => "1075199767891652609",
        //         "price" => "29376.5",
        //         "size" => "6.035",
        //         "side" => "Buy",
        //         "ts" => "1692073521000",
        //         "symbol" => "BTCUSDT"
        //     }
        //
        // spot => fetchMyTrades
        //
        //     {
        //         "userId" => "7264631750",
        //         "symbol" => "BTCUSDT",
        //         "orderId" => "1098394344925597696",
        //         "tradeId" => "1098394344974925824",
        //         "orderType" => "market",
        //         "side" => "sell",
        //         "priceAvg" => "28467.68",
        //         "size" => "0.0002",
        //         "amount" => "5.693536",
        //         "feeDetail" => array(
        //             "deduction" => "no",
        //             "feeCoin" => "USDT",
        //             "totalDeductionFee" => "",
        //             "totalFee" => "-0.005693536"
        //         ),
        //         "tradeScope" => "taker",
        //         "cTime" => "1697603539699",
        //         "uTime" => "1697603539754"
        //     }
        //
        // spot margin => fetchMyTrades
        //
        //     {
        //         "orderId" => "1099353730455318528",
        //         "tradeId" => "1099353730627092481",
        //         "orderType" => "market",
        //         "side" => "sell",
        //         "priceAvg" => "29543.7",
        //         "size" => "0.0001",
        //         "amount" => "2.95437",
        //         "tradeScope" => "taker",
        //         "feeDetail" => array(
        //             "deduction" => "no",
        //             "feeCoin" => "USDT",
        //             "totalDeductionFee" => "0",
        //             "totalFee" => "-0.00295437"
        //         ),
        //         "cTime" => "1697832275063",
        //         "uTime" => "1697832275150"
        //     }
        //
        // swap and future => fetchMyTrades
        //
        //     {
        //         "tradeId" => "1111468664328269825",
        //         "symbol" => "BTCUSDT",
        //         "orderId" => "1111468664264753162",
        //         "price" => "37271.4",
        //         "baseVolume" => "0.001",
        //         "feeDetail" => array(
        //             {
        //                 "deduction" => "no",
        //                 "feeCoin" => "USDT",
        //                 "totalDeductionFee" => null,
        //                 "totalFee" => "-0.02236284"
        //             }
        //         ),
        //         "side" => "buy",
        //         "quoteVolume" => "37.2714",
        //         "profit" => "-0.0007",
        //         "enterPointSource" => "web",
        //         "tradeSide" => "close",
        //         "posMode" => "hedge_mode",
        //         "tradeScope" => "taker",
        //         "cTime" => "1700720700342"
        //     }
        //
        // uta fetchTrades
        //
        //     {
        //         "execId" => "1319896716324937729",
        //         "price" => "105909.1",
        //         "size" => "6.3090",
        //         "side" => "sell",
        //         "ts" => "1750413820344"
        //     }
        //
        // uta fetchMyTrades
        //
        //     {
        //         "execId" => "1322441401010528257",
        //         "orderId" => "1322441400976261120",
        //         "category" => "USDT-FUTURES",
        //         "symbol" => "BTCUSDT",
        //         "orderType" => "market",
        //         "side" => "sell",
        //         "execPrice" => "107005.4",
        //         "execQty" => "0.0001",
        //         "execValue" => "10.7005",
        //         "tradeScope" => "taker",
        //         "feeDetail" => [array(
        //             "feeCoin" => "USDT",
        //             "fee":"0.00642032"
        //         )],
        //         "createdTime" => "1751020520451",
        //         "updatedTime" => "1751020520458",
        //         "execPnl" => "0.00017"
        //     }
        //
        $marketId = $this->safe_string($trade, 'symbol');
        $symbol = $this->safe_symbol($marketId, $market);
        $timestamp = $this->safe_integer_n($trade, array( 'cTime', 'ts', 'createdTime' ));
        $fee = null;
        $feeDetail = $this->safe_value($trade, 'feeDetail');
        $posMode = $this->safe_string($trade, 'posMode');
        $category = $this->safe_string($trade, 'category');
        $isFeeStructure = ($posMode !== null) || ($category !== null);
        $feeStructure = $isFeeStructure ? $feeDetail[0] : $feeDetail;
        if ($feeStructure !== null) {
            $currencyCode = $this->safe_currency_code($this->safe_string($feeStructure, 'feeCoin'));
            $fee = array(
                'currency' => $currencyCode,
            );
            $feeCostString = $this->safe_string_2($feeStructure, 'totalFee', 'fee');
            $deduction = $this->safe_string($feeStructure, 'deduction') === 'yes' ? true : false;
            if ($deduction) {
                $fee['cost'] = $feeCostString;
            } else {
                $fee['cost'] = Precise::string_neg($feeCostString);
            }
        }
        return $this->safe_trade(array(
            'info' => $trade,
            'id' => $this->safe_string_2($trade, 'tradeId', 'execId'),
            'order' => $this->safe_string($trade, 'orderId'),
            'symbol' => $symbol,
            'side' => $this->safe_string_lower($trade, 'side'),
            'type' => $this->safe_string($trade, 'orderType'),
            'takerOrMaker' => $this->safe_string($trade, 'tradeScope'),
            'price' => $this->safe_string_n($trade, array( 'priceAvg', 'price', 'execPrice' )),
            'amount' => $this->safe_string_n($trade, array( 'baseVolume', 'size', 'execQty' )),
            'cost' => $this->safe_string_n($trade, array( 'quoteVolume', 'amount', 'execValue' )),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'fee' => $fee,
        ), $market);
    }

    public function fetch_trades(string $symbol, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * get the list of most recent trades for a particular $symbol
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Recent-Trades
             * @see https://www.bitget.com/api-doc/spot/market/Get-Market-Trades
             * @see https://www.bitget.com/api-doc/contract/market/Get-Recent-Fills
             * @see https://www.bitget.com/api-doc/contract/market/Get-Fills-History
             * @see https://www.bitget.com/api-doc/uta/public/Fills
             *
             * @param {string} $symbol unified $symbol of the $market to fetch trades for
             * @param {int} [$since] timestamp in ms of the earliest trade to fetch
             * @param {int} [$limit] the maximum amount of trades to fetch
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {int} [$params->until] *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* the latest time in ms to fetch trades for
             * @param {boolean} [$params->paginate] *only applies to publicSpotGetV2SpotMarketFillsHistory and publicMixGetV2MixMarketFillsHistory* default false, when true will automatically $paginate by calling this endpoint multiple times
             * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=public-trades trade structures~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchTrades', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchTrades', $symbol, $since, $limit, $params, 'idLessThan', 'idLessThan'));
            }
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchTrades', 'uta', false);
            if ($limit !== null) {
                if ($uta) {
                    $request['limit'] = min ($limit, 100);
                } elseif ($market['contract']) {
                    $request['limit'] = min ($limit, 1000);
                } else {
                    $request['limit'] = $limit;
                }
            }
            $options = $this->safe_value($this->options, 'fetchTrades', array());
            $response = null;
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            if ($uta) {
                if ($productType === 'SPOT') {
                    $marginMode = null;
                    list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchTrades', $params);
                    if ($marginMode !== null) {
                        $productType = 'MARGIN';
                    }
                }
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketFills ($this->extend($request, $params)));
            } elseif ($market['spot']) {
                $spotOptions = $this->safe_value($options, 'spot', array());
                $defaultSpotMethod = $this->safe_string($spotOptions, 'method', 'publicSpotGetV2SpotMarketFillsHistory');
                $spotMethod = $this->safe_string($params, 'method', $defaultSpotMethod);
                $params = $this->omit($params, 'method');
                if ($spotMethod === 'publicSpotGetV2SpotMarketFillsHistory') {
                    list($request, $params) = $this->handle_until_option('endTime', $request, $params);
                    if ($since !== null) {
                        $request['startTime'] = $since;
                    }
                    $response = Async\await($this->publicSpotGetV2SpotMarketFillsHistory ($this->extend($request, $params)));
                } elseif ($spotMethod === 'publicSpotGetV2SpotMarketFills') {
                    $response = Async\await($this->publicSpotGetV2SpotMarketFills ($this->extend($request, $params)));
                }
            } else {
                $swapOptions = $this->safe_value($options, 'swap', array());
                $defaultSwapMethod = $this->safe_string($swapOptions, 'method', 'publicMixGetV2MixMarketFillsHistory');
                $swapMethod = $this->safe_string($params, 'method', $defaultSwapMethod);
                $params = $this->omit($params, 'method');
                $request['productType'] = $productType;
                if ($swapMethod === 'publicMixGetV2MixMarketFillsHistory') {
                    list($request, $params) = $this->handle_until_option('endTime', $request, $params);
                    if ($since !== null) {
                        $request['startTime'] = $since;
                    }
                    $response = Async\await($this->publicMixGetV2MixMarketFillsHistory ($this->extend($request, $params)));
                } elseif ($swapMethod === 'publicMixGetV2MixMarketFills') {
                    $response = Async\await($this->publicMixGetV2MixMarketFills ($this->extend($request, $params)));
                }
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1692073693562,
            //         "data" => array(
            //             array(
            //                 "symbol" => "BTCUSDT_SPBL",
            //                 "tradeId" => "1075200479040323585",
            //                 "side" => "Sell",
            //                 "price" => "29381.54",
            //                 "size" => "0.0056",
            //                 "ts" => "1692073691000"
            //             ),
            //         )
            //     }
            //
            // swap
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1692073522689,
            //         "data" => array(
            //             array(
            //                 "tradeId" => "1075199767891652609",
            //                 "price" => "29376.5",
            //                 "size" => "6.035",
            //                 "side" => "Buy",
            //                 "ts" => "1692073521000",
            //                 "symbol" => "BTCUSDT_UMCBL"
            //             ),
            //         )
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750413823980,
            //         "data" => array(
            //             {
            //                 "execId" => "1319896716324937729",
            //                 "price" => "105909.1",
            //                 "size" => "6.3090",
            //                 "side" => "sell",
            //                 "ts" => "1750413820344"
            //             }
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_trades($data, $market, $since, $limit);
        }) ();
    }

    public function fetch_trading_fee(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the trading fees for a $market
             *
             * @see https://www.bitget.com/api-doc/common/public/Get-Trade-Rate
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'isolated' or 'cross', for finding the fee rate of spot margin trading pairs
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=fee-structure fee structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchTradingFee', $params);
            if ($market['spot']) {
                if ($marginMode !== null) {
                    $request['businessType'] = 'margin';
                } else {
                    $request['businessType'] = 'spot';
                }
            } else {
                $request['businessType'] = 'mix';
            }
            $response = Async\await($this->privateCommonGetV2CommonTradeRate ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700549524887,
            //         "data" => {
            //             "makerFeeRate" => "0.001",
            //             "takerFeeRate" => "0.001"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_trading_fee($data, $market);
        }) ();
    }

    public function fetch_trading_fees($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetch the trading fees for multiple markets
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Symbols
             * @see https://www.bitget.com/api-doc/contract/market/Get-All-Symbols-Contracts
             * @see https://www.bitget.com/api-doc/margin/common/support-currencies
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->productType] *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->margin] set to true for spot $margin
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=$fee-structure $fee structures~ indexed by $market symbols
             */
            Async\await($this->load_markets());
            $response = null;
            $marginMode = null;
            $marketType = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchTradingFees', $params);
            list($marketType, $params) = $this->handle_market_type_and_params('fetchTradingFees', null, $params);
            if ($marketType === 'spot') {
                $margin = $this->safe_bool($params, 'margin', false);
                $params = $this->omit($params, 'margin');
                if (($marginMode !== null) || $margin) {
                    $response = Async\await($this->publicMarginGetV2MarginCurrencies ($params));
                } else {
                    $response = Async\await($this->publicSpotGetV2SpotPublicSymbols ($params));
                }
            } elseif (($marketType === 'swap') || ($marketType === 'future')) {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params(null, $params);
                $params['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketContracts ($params));
            } else {
                throw new NotSupported($this->id . ' does not support ' . $marketType . ' market');
            }
            //
            // spot and $margin
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700102364653,
            //         "data" => array(
            //             array(
            //                 "symbol" => "TRXUSDT",
            //                 "baseCoin" => "TRX",
            //                 "quoteCoin" => "USDT",
            //                 "minTradeAmount" => "0",
            //                 "maxTradeAmount" => "10000000000",
            //                 "takerFeeRate" => "0.002",
            //                 "makerFeeRate" => "0.002",
            //                 "pricePrecision" => "6",
            //                 "quantityPrecision" => "4",
            //                 "quotePrecision" => "6",
            //                 "status" => "online",
            //                 "minTradeUSDT" => "5",
            //                 "buyLimitPriceRatio" => "0.05",
            //                 "sellLimitPriceRatio" => "0.05"
            //             ),
            //         )
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700102364709,
            //         "data" => [
            //             array(
            //                 "symbol" => "BTCUSDT",
            //                 "baseCoin" => "BTC",
            //                 "quoteCoin" => "USDT",
            //                 "buyLimitPriceRatio" => "0.01",
            //                 "sellLimitPriceRatio" => "0.01",
            //                 "feeRateUpRatio" => "0.005",
            //                 "makerFeeRate" => "0.0002",
            //                 "takerFeeRate" => "0.0006",
            //                 "openCostUpRatio" => "0.01",
            //                 "supportMarginCoins" => ["USDT"],
            //                 "minTradeNum" => "0.001",
            //                 "priceEndStep" => "1",
            //                 "volumePlace" => "3",
            //                 "pricePlace" => "1",
            //                 "sizeMultiplier" => "0.001",
            //                 "symbolType" => "perpetual",
            //                 "minTradeUSDT" => "5",
            //                 "maxSymbolOrderNum" => "200",
            //                 "maxProductOrderNum" => "400",
            //                 "maxPositionNum" => "150",
            //                 "symbolStatus" => "normal",
            //                 "offTime" => "-1",
            //                 "limitOpenTime" => "-1",
            //                 "deliveryTime" => "",
            //                 "deliveryStartTime" => "",
            //                 "deliveryPeriod" => "",
            //                 "launchTime" => "",
            //                 "fundInterval" => "8",
            //                 "minLever" => "1",
            //                 "maxLever" => "125",
            //                 "posLimit" => "0.05",
            //                 "maintainTime" => ""
            //             ),
            //         ]
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $marketId = $this->safe_string($entry, 'symbol');
                $symbol = $this->safe_symbol($marketId, null, null, $marketType);
                $market = $this->market($symbol);
                $fee = $this->parse_trading_fee($entry, $market);
                $result[$symbol] = $fee;
            }
            return $result;
        }) ();
    }

    public function parse_trading_fee($data, ?array $market = null) {
        $marketId = $this->safe_string($data, 'symbol');
        return array(
            'info' => $data,
            'symbol' => $this->safe_symbol($marketId, $market),
            'maker' => $this->safe_number($data, 'makerFeeRate'),
            'taker' => $this->safe_number($data, 'takerFeeRate'),
            'percentage' => null,
            'tierBased' => null,
        );
    }

    public function parse_ohlcv($ohlcv, ?array $market = null): array {
        //
        //     array(
        //         "1645911960000",
        //         "39406",
        //         "39407",
        //         "39374.5",
        //         "39379",
        //         "35.526",
        //         "1399132.341"
        //     )
        //
        $inverse = $this->safe_bool($market, 'inverse');
        $volumeIndex = $inverse ? 6 : 5;
        return array(
            $this->safe_integer($ohlcv, 0),
            $this->safe_number($ohlcv, 1),
            $this->safe_number($ohlcv, 2),
            $this->safe_number($ohlcv, 3),
            $this->safe_number($ohlcv, 4),
            $this->safe_number($ohlcv, $volumeIndex),
        );
    }

    public function fetch_ohlcv(string $symbol, $timeframe = '1m', ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $timeframe, $since, $limit, $params) {
            /**
             * fetches historical candlestick $data containing the open, high, low, and close price, and the volume of a $market
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Candle-Data
             * @see https://www.bitget.com/api-doc/spot/market/Get-History-Candle-Data
             * @see https://www.bitget.com/api-doc/contract/market/Get-Candle-Data
             * @see https://www.bitget.com/api-doc/contract/market/Get-History-Candle-Data
             * @see https://www.bitget.com/api-doc/contract/market/Get-History-Index-Candle-Data
             * @see https://www.bitget.com/api-doc/contract/market/Get-History-Mark-Candle-Data
             * @see https://www.bitget.com/api-doc/uta/public/Get-Candle-Data
             *
             * @param {string} $symbol unified $symbol of the $market to fetch OHLCV $data for
             * @param {string} $timeframe the length of time each candle represents
             * @param {int} [$since] timestamp in ms of the earliest candle to fetch
             * @param {int} [$limit] the maximum amount of candles to fetch
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {int} [$params->until] timestamp in ms of the latest candle to fetch
             * @param {boolean} [$params->useHistoryEndpoint] whether to force to use historical endpoint (it has max $limit of 200)
             * @param {boolean} [$params->useHistoryEndpointForPagination] whether to force to use historical endpoint for pagination (default true)
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {string} [$params->price] *swap only* "mark" (to fetch mark price candles) or "index" (to fetch index price candles)
             * @return {int[][]} A list of candles ordered, open, high, low, close, volume
             */
            Async\await($this->load_markets());
            $defaultLimit = 100; // default 100, max 1000
            $maxLimitForRecentEndpoint = 1000;
            $maxLimitForHistoryEndpoint = 200; // note, max 1000 bars are supported for "recent-candles" endpoint, but "historical-candles" support only max 200
            $useHistoryEndpoint = $this->safe_bool($params, 'useHistoryEndpoint', false);
            $useHistoryEndpointForPagination = $this->safe_bool($params, 'useHistoryEndpointForPagination', true);
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchOHLCV', 'paginate');
            if ($paginate) {
                $limitForPagination = $useHistoryEndpointForPagination ? $maxLimitForHistoryEndpoint : $maxLimitForRecentEndpoint;
                return Async\await($this->fetch_paginated_call_deterministic('fetchOHLCV', $symbol, $since, $limit, $timeframe, $params, $limitForPagination));
            }
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $marketType = null;
            $timeframes = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchOHLCV', 'uta', false);
            if ($uta) {
                $timeframes = $this->options['timeframes']['uta'];
                $request['interval'] = $this->safe_string($timeframes, $timeframe, $timeframe);
            } else {
                $marketType = $market['spot'] ? 'spot' : 'swap';
                $timeframes = $this->options['timeframes'][$marketType];
                $request['granularity'] = $this->safe_string($timeframes, $timeframe, $timeframe);
            }
            $msInDay = 86400000;
            $now = $this->milliseconds();
            $duration = $this->parse_timeframe($timeframe) * 1000;
            $until = $this->safe_integer($params, 'until');
            $limitDefined = $limit !== null;
            $sinceDefined = $since !== null;
            $untilDefined = $until !== null;
            $params = $this->omit($params, array( 'until' ));
            // retrievable periods listed here:
            // - https://www.bitget.com/api-doc/spot/market/Get-Candle-Data#$request-parameters
            // - https://www.bitget.com/api-doc/contract/market/Get-Candle-Data#description
            $key = $market['spot'] ? 'spot' : 'swap';
            $ohlcOptions = $this->safe_dict($this->options['fetchOHLCV'], $key, array());
            $maxLimitPerTimeframe = $this->safe_dict($ohlcOptions, 'maxLimitPerTimeframe', array());
            $maxLimitForThisTimeframe = $this->safe_integer($maxLimitPerTimeframe, $timeframe, $limit);
            $recentEndpointDaysMap = $this->safe_dict($this->options['fetchOHLCV'], 'maxRecentDaysPerTimeframe', array());
            $recentEndpointAvailableDays = $this->safe_integer($recentEndpointDaysMap, $timeframe);
            $recentEndpointBoundaryTs = $now - ($recentEndpointAvailableDays - 1) * $msInDay;
            if ($limitDefined) {
                $limit = min ($limit, $maxLimitForRecentEndpoint);
                $limit = min ($limit, $maxLimitForThisTimeframe);
            } else {
                $limit = $defaultLimit;
            }
            $limitMultipliedDuration = $limit * $duration;
            // exchange aligns from endTime, so it's important, not startTime
            // startTime is supported only on "recent" endpoint, not on "historical" endpoint
            $calculatedStartTime = null;
            $calculatedEndTime = null;
            if ($sinceDefined) {
                $calculatedStartTime = $since;
                $request['startTime'] = $since;
                if (!$untilDefined) {
                    $calculatedEndTime = $this->sum($calculatedStartTime, $limitMultipliedDuration);
                    $request['endTime'] = $calculatedEndTime;
                }
            }
            if ($untilDefined) {
                $calculatedEndTime = $until;
                $request['endTime'] = $calculatedEndTime;
                if (!$sinceDefined) {
                    $calculatedStartTime = $calculatedEndTime - $limitMultipliedDuration;
                    // we do not need to set "startTime" here
                }
            }
            // if historical endpoint is needed, we should re-set the variables
            $historicalEndpointNeeded = false;
            if (($calculatedStartTime !== null && $calculatedStartTime <= $recentEndpointBoundaryTs) || $useHistoryEndpoint) {
                $historicalEndpointNeeded = true;
                // only for "historical-candles" - ensure we use correct max $limit
                $limit = min ($limit, $maxLimitForHistoryEndpoint);
                $limitMultipliedDuration = $limit * $duration;
                $calculatedStartTime = $calculatedEndTime - $limitMultipliedDuration;
                $request['startTime'] = $calculatedStartTime;
                // for contract, maximum 90 days allowed between start-end times
                if (!$market['spot']) {
                    $maxDistanceDaysForContracts = 90;
                    // only correct if $request is larger
                    if ($calculatedEndTime - $calculatedStartTime > $maxDistanceDaysForContracts * $msInDay) {
                        $calculatedEndTime = $this->sum($calculatedStartTime, $maxDistanceDaysForContracts * $msInDay);
                        $request['endTime'] = $calculatedEndTime;
                    }
                }
            }
            // we need to set $limit to safely cover the period
            $request['limit'] = $limit;
            // make $request
            $response = null;
            $productType = null;
            $priceType = null;
            list($priceType, $params) = $this->handle_param_string($params, 'price');
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            if ($uta) {
                if ($priceType !== null) {
                    if ($priceType === 'mark') {
                        $request['type'] = 'MARK';
                    } elseif ($priceType === 'index') {
                        $request['type'] = 'INDEX';
                    }
                }
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketCandles ($this->extend($request, $params)));
            } elseif ($market['spot']) {
                // checks if we need history endpoint
                if ($historicalEndpointNeeded) {
                    $response = Async\await($this->publicSpotGetV2SpotMarketHistoryCandles ($this->extend($request, $params)));
                } else {
                    if (!$limitDefined) {
                        $request['limit'] = 1000;
                        $limit = 1000;
                    }
                    $response = Async\await($this->publicSpotGetV2SpotMarketCandles ($this->extend($request, $params)));
                }
            } else {
                $request['productType'] = $productType;
                $extended = $this->extend($request, $params);
                if (!$historicalEndpointNeeded && ($priceType === 'mark' || $priceType === 'index')) {
                    if (!$limitDefined) {
                        $extended['limit'] = 1000;
                        $limit = 1000;
                    }
                    // Recent endpoint for mark/index prices
                    // https://www.bitget.com/api-doc/contract/market/Get-Candle-Data
                    $response = Async\await($this->publicMixGetV2MixMarketCandles ($this->extend(array( 'kLineType' => $priceType ), $extended)));
                } elseif ($priceType === 'mark') {
                    $response = Async\await($this->publicMixGetV2MixMarketHistoryMarkCandles ($extended));
                } elseif ($priceType === 'index') {
                    $response = Async\await($this->publicMixGetV2MixMarketHistoryIndexCandles ($extended));
                } else {
                    if ($historicalEndpointNeeded) {
                        $response = Async\await($this->publicMixGetV2MixMarketHistoryCandles ($extended));
                    } else {
                        if (!$limitDefined) {
                            $extended['limit'] = 1000;
                            $limit = 1000;
                        }
                        $response = Async\await($this->publicMixGetV2MixMarketCandles ($extended));
                    }
                }
            }
            if ($response === '') {
                return array(); // happens when a new token is listed
            }
            //  [ ["1645911960000","39406","39407","39374.5","39379","35.526","1399132.341"] ]
            $data = $this->safe_list($response, 'data', $response);
            return $this->parse_ohlcvs($data, $market, $timeframe, $since, $limit);
        }) ();
    }

    public function fetch_balance($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * query for balance and get the amount of funds available for trading or funds locked in orders
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Account-Assets
             * @see https://www.bitget.com/api-doc/contract/account/Get-Account-List
             * @see https://www.bitget.com/api-doc/margin/cross/account/Get-Cross-Assets
             * @see https://www.bitget.com/api-doc/margin/isolated/account/Get-Isolated-Assets
             * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-cross-$assets
             * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-isolated-$assets
             * @see https://www.bitget.com/api-doc/uta/account/Get-Account
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->productType] *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {string} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=balance-structure balance structure~
             */
            Async\await($this->load_markets());
            $request = array();
            $marketType = null;
            $marginMode = null;
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchBalance', 'uta', false);
            list($marketType, $params) = $this->handle_market_type_and_params('fetchBalance', null, $params);
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchBalance', $params);
            if ($uta) {
                $response = Async\await($this->privateUtaGetV3AccountAssets ($this->extend($request, $params)));
                $results = $this->safe_dict($response, 'data', array());
                $assets = $this->safe_list($results, 'assets', array());
                return $this->parse_uta_balance($assets);
            } elseif (($marketType === 'swap') || ($marketType === 'future')) {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params(null, $params);
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixAccountAccounts ($this->extend($request, $params)));
            } elseif ($marginMode === 'isolated') {
                $response = Async\await($this->privateMarginGetV2MarginIsolatedAccountAssets ($this->extend($request, $params)));
                //
                //    {
                //        "code" => "00000",
                //        "msg" => "success",
                //        "requestTime" => "1759829170717",
                //        "data" => array(
                //            array(
                //                "symbol" => "BTCUSDT",
                //                "coin" => "USDT",
                //                "totalAmount" => "0.000001",
                //                "available" => "0.000001",
                //                "frozen" => "0",
                //                "borrow" => "0",
                //                "interest" => "0",
                //                "net" => "0.000001",
                //                "coupon" => "0",
                //                "cTime" => "1759826434145",
                //                "uTime" => "1759826434146"
                //            ),
                //        )
                //    }
                //
            } elseif ($marginMode === 'cross') {
                $response = Async\await($this->privateMarginGetV2MarginCrossedAccountAssets ($this->extend($request, $params)));
                //
                //    {
                //        "code" => "00000",
                //        "msg" => "success",
                //        "requestTime" => "1759828519501",
                //        "data" => array(
                //            {
                //                "coin" => "USDT",
                //                "totalAmount" => "0.01",
                //                "available" => "0.01",
                //                "frozen" => "0",
                //                "borrow" => "0",
                //                "interest" => "0",
                //                "net" => "0.01",
                //                "coupon" => "0",
                //                "cTime" => "1759828511592",
                //                "uTime" => "1759828511592"
                //            }
                //        )
                //    }
                //
            } elseif ($marketType === 'spot') {
                $response = Async\await($this->privateSpotGetV2SpotAccountAssets ($this->extend($request, $params)));
            } else {
                throw new NotSupported($this->id . ' fetchBalance() does not support ' . $marketType . ' accounts');
            }
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700623852854,
            //         "data" => array(
            //             {
            //                 "coin" => "USDT",
            //                 "available" => "0.00000000",
            //                 "limitAvailable" => "0",
            //                 "frozen" => "0.00000000",
            //                 "locked" => "0.00000000",
            //                 "uTime" => "1699937566000"
            //             }
            //         )
            //     }
            //
            // swap
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700625127294,
            //         "data" => array(
            //             {
            //                 "marginCoin" => "USDT",
            //                 "locked" => "0",
            //                 "available" => "0",
            //                 "crossedMaxAvailable" => "0",
            //                 "isolatedMaxAvailable" => "0",
            //                 "maxTransferOut" => "0",
            //                 "accountEquity" => "0",
            //                 "usdtEquity" => "0.000000005166",
            //                 "btcEquity" => "0",
            //                 "crossedRiskRate" => "0",
            //                 "unrealizedPL" => "0",
            //                 "coupon" => "0",
            //                 "crossedUnrealizedPL" => null,
            //                 "isolatedUnrealizedPL" => null
            //             }
            //         )
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1749980065089,
            //         "data" => {
            //             "accountEquity" => "11.13919278",
            //             "usdtEquity" => "11.13921165",
            //             "btcEquity" => "0.00011256",
            //             "unrealisedPnl" => "0",
            //             "usdtUnrealisedPnl" => "0",
            //             "btcUnrealizedPnl" => "0",
            //             "effEquity" => "6.19299777",
            //             "mmr" => "0",
            //             "imr" => "0",
            //             "mgnRatio" => "0",
            //             "positionMgnRatio" => "0",
            //             "assets" => array(
            //                 {
            //                     "coin" => "USDT",
            //                     "equity" => "6.19300826",
            //                     "usdValue" => "6.19299777",
            //                     "balance" => "6.19300826",
            //                     "available" => "6.19300826",
            //                     "debt" => "0",
            //                     "locked" => "0"
            //                 }
            //             )
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_balance($data);
        }) ();
    }

    public function parse_uta_balance($balance): array {
        $result = array( 'info' => $balance );
        //
        //     {
        //         "coin" => "USDT",
        //         "equity" => "6.19300826",
        //         "usdValue" => "6.19299777",
        //         "balance" => "6.19300826",
        //         "available" => "6.19300826",
        //         "debt" => "0",
        //         "locked" => "0"
        //     }
        //
        for ($i = 0; $i < count($balance); $i++) {
            $entry = $balance[$i];
            $account = $this->account();
            $currencyId = $this->safe_string($entry, 'coin');
            $code = $this->safe_currency_code($currencyId);
            $account['debt'] = $this->safe_string($entry, 'debt');
            $account['used'] = $this->safe_string($entry, 'locked');
            $account['free'] = $this->safe_string($entry, 'available');
            $account['total'] = $this->safe_string($entry, 'balance');
            $result[$code] = $account;
        }
        return $this->safe_balance($result);
    }

    public function parse_balance($balance): array {
        $result = array( 'info' => $balance );
        //
        // spot
        //
        //     {
        //         "coin" => "USDT",
        //         "available" => "0.00000000",
        //         "limitAvailable" => "0",
        //         "frozen" => "0.00000000",
        //         "locked" => "0.00000000",
        //         "uTime" => "1699937566000"
        //     }
        //
        // swap
        //
        //     {
        //         "marginCoin" => "USDT",
        //         "locked" => "0",
        //         "available" => "0",
        //         "crossedMaxAvailable" => "0",
        //         "isolatedMaxAvailable" => "0",
        //         "maxTransferOut" => "0",
        //         "accountEquity" => "0",
        //         "usdtEquity" => "0.000000005166",
        //         "btcEquity" => "0",
        //         "crossedRiskRate" => "0",
        //         "unrealizedPL" => "0",
        //         "coupon" => "0",
        //         "crossedUnrealizedPL" => null,
        //         "isolatedUnrealizedPL" => null
        //     }
        //
        // cross & isolated margin
        //
        //      {
        //           "coin" => "USDT",
        //           "totalAmount" => "0.01",
        //           "available" => "0.01",
        //           "frozen" => "0",
        //           "borrow" => "0",
        //           "interest" => "0",
        //           "net" => "0.01",
        //           "coupon" => "0",
        //           "cTime" => "1759828511592",
        //           "uTime" => "1759828511592"
        //           // "symbol" => "BTCUSDT" // only for isolated margin
        //       }
        //
        for ($i = 0; $i < count($balance); $i++) {
            $entry = $balance[$i];
            $account = $this->account();
            $currencyId = $this->safe_string_2($entry, 'marginCoin', 'coin');
            $code = $this->safe_currency_code($currencyId);
            $borrow = $this->safe_string($entry, 'borrow');
            if ($borrow !== null) {
                $interest = $this->safe_string($entry, 'interest');
                $account['free'] = $this->safe_string($entry, 'transferable');
                $account['total'] = $this->safe_string($entry, 'totalAmount');
                $account['debt'] = Precise::string_add($borrow, $interest);
            } else {
                // Use transferable instead of available for swap and margin https://github.com/ccxt/ccxt/pull/19127
                $spotAccountFree = $this->safe_string($entry, 'available');
                $contractAccountFree = $this->safe_string($entry, 'maxTransferOut');
                if ($contractAccountFree !== null) {
                    $account['free'] = $contractAccountFree;
                    $account['total'] = $this->safe_string($entry, 'accountEquity');
                } else {
                    $account['free'] = $spotAccountFree;
                    $frozen = $this->safe_string($entry, 'frozen');
                    $locked = $this->safe_string($entry, 'locked');
                    $account['used'] = Precise::string_add($frozen, $locked);
                }
            }
            $result[$code] = $account;
        }
        return $this->safe_balance($result);
    }

    public function parse_order_status(?string $status) {
        $statuses = array(
            'new' => 'open',
            'init' => 'open',
            'not_trigger' => 'open',
            'partial_fill' => 'open',
            'partially_fill' => 'open',
            'partially_filled' => 'open',
            'triggered' => 'closed',
            'full_fill' => 'closed',
            'filled' => 'closed',
            'fail_trigger' => 'rejected',
            'cancel' => 'canceled',
            'cancelled' => 'canceled',
            'canceled' => 'canceled',
            'live' => 'open',
            'fail_execute' => 'rejected',
            'executed' => 'closed',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function parse_order(array $order, ?array $market = null): array {
        //
        // createOrder, editOrder, closePosition
        //
        //     {
        //         "clientOid" => "abe95dbe-6081-4a6f-a2d3-ae49601cd479",
        //         "orderId" => null
        //     }
        //
        // createOrders
        //
        //     array(
        //         array(
        //             "orderId" => "1111397214281175046",
        //             "clientOid" => "766d3fc3-7321-4406-a689-15c9987a2e75"
        //         ),
        //         array(
        //             "orderId" => "",
        //             "clientOid" => "d1b75cb3-cc15-4ede-ad4c-3937396f75ab",
        //             "errorMsg" => "less than the minimum amount 5 USDT",
        //             "errorCode" => "45110"
        //         ),
        //     )
        //
        // spot, swap, future, spot margin and $uta => cancelOrder, cancelOrders, cancelAllOrders
        //
        //     {
        //         "orderId" => "1098758604547850241",
        //         "clientOid" => "1098758604585598977"
        //     }
        //
        // spot trigger => cancelOrder
        //
        //     {
        //         "result" => "success"
        //     }
        //
        // spot => fetchOrder, fetchOpenOrders, fetchCanceledAndClosedOrders
        //
        //     {
        //         "userId" => "7264631750",
        //         "symbol" => "BTCUSDT",
        //         "orderId" => "1111499608327360513",
        //         "clientOid" => "d0d4dad5-18d0-4869-a074-ec40bb47cba6",
        //         "size" => "0.0002000000000000", // COST for 'buy market' $order! AMOUNT in all other cases
        //         "price" => "0", // in fetchOrder => 0 for $market $order, otherwise limit $price (field not present in fetchOpenOrders
        //         "orderType" => "limit",
        //         "side" => "buy",
        //         "status" => "live",
        //         "basePrice" => "0",
        //         "priceAvg" => "25000.0000000000000000",   // 0 if nothing $filled
        //         "baseVolume" => "0.0000000000000000",     // 0 if nothing $filled
        //         "quoteVolume" => "0.0000000000000000",    // 0 if nothing $filled
        //         "enterPointSource" => "WEB",
        //         "orderSource" => "normal",
        //         "cTime" => "1700728077966",
        //         "uTime" => "1700728077966"
        //         "feeDetail" => "array(\\"newFees\\":array(\\"c\\":0,\\"d\\":0,\\"deduction\\":false,\\"r\\":-0.0064699886,\\"t\\":-0.0064699886,\\"totalDeductionFee\\":0),\\"USDT\\":array(\\"deduction\\":false,\\"feeCoinCode\\":\\"USDT\\",\\"totalDeductionFee\\":0,\\"totalFee\\":-0.0064699886000000))", // might not be present in fetchOpenOrders
        //         "triggerPrice" => null,
        //         "tpslType" => "normal",
        //         "quoteCoin" => "USDT",  // not present in fetchOpenOrders
        //         "baseCoin" => "DOT",    // not present in fetchOpenOrders
        //         "cancelReason" => "",   // not present in fetchOpenOrders
        //     }
        //
        // spot trigger => fetchOpenOrders, fetchCanceledAndClosedOrders
        //
        //     {
        //         "orderId" => "1111503385931620352",
        //         "clientOid" => "1111503385910648832",
        //         "symbol" => "BTCUSDT",
        //         "size" => "0.0002",
        //         "planType" => "AMOUNT",
        //         "executePrice" => "25000",
        //         "triggerPrice" => "26000",
        //         "status" => "live",
        //         "orderType" => "limit",
        //         "side" => "buy",
        //         "triggerType" => "fill_price",
        //         "enterPointSource" => "API",
        //         "cTime" => "1700728978617",
        //         "uTime" => "1700728978617"
        //     }
        //
        // spot margin => fetchOpenOrders, fetchCanceledAndClosedOrders
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "orderType" => "limit",
        //         "enterPointSource" => "WEB",
        //         "orderId" => "1111506377509580801",
        //         "clientOid" => "2043a3b59a60445f9d9f7365bf3e960c",
        //         "loanType" => "autoLoanAndRepay",
        //         "price" => "25000",
        //         "side" => "buy",
        //         "status" => "live",
        //         "baseSize" => "0.0002",
        //         "quoteSize" => "5",
        //         "priceAvg" => "0",
        //         "size" => "0",
        //         "amount" => "0",
        //         "force" => "gtc",
        //         "cTime" => "1700729691866",
        //         "uTime" => "1700729691866"
        //     }
        //
        // swap and future => fetchOrder, fetchOpenOrders, fetchCanceledAndClosedOrders
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "size" => "0.001",
        //         "orderId" => "1111465253393825792",
        //         "clientOid" => "1111465253431574529",
        //         "baseVolume" => "0",
        //         "fee" => "0",
        //         "price" => "27000",
        //         "priceAvg" => "",
        //         "state" => "live",
        //         // "status" => "live", // key for fetchOpenOrders, fetchClosedOrders
        //         "side" => "buy",
        //         "force" => "gtc",
        //         "totalProfits" => "0",
        //         "posSide" => "long",
        //         "marginCoin" => "USDT",
        //         "quoteVolume" => "0",
        //         "leverage" => "20",
        //         "marginMode" => "crossed",
        //         "enterPointSource" => "API",
        //         "tradeSide" => "open",
        //         "posMode" => "hedge_mode",
        //         "orderType" => "limit",
        //         "orderSource" => "normal",
        //         "presetStopSurplusPrice" => "",
        //         "presetStopLossPrice" => "",
        //         "reduceOnly" => "NO",
        //         "cTime" => "1700719887120",
        //         "uTime" => "1700719887120"
        //
        //     for swap trigger $order, the additional below fields are present:
        //
        //         "planType" => "normal_plan",
        //         "callbackRatio" => "",
        //         "triggerPrice" => "24000",
        //         "triggerType" => "mark_price",
        //         "planStatus" => "live",
        //         "stopSurplusTriggerPrice" => "",
        //         "stopSurplusExecutePrice" => "",
        //         "stopSurplusTriggerType" => "fill_price",
        //         "stopLossTriggerPrice" => "",
        //         "stopLossExecutePrice" => "",
        //         "stopLossTriggerType" => "fill_price",
        //     }
        //
        // $uta => fetchOrder, fetchOpenOrders, fetchCanceledAndClosedOrders
        //
        //     {
        //         "orderId" => "1320244799629316096",
        //         "clientOid" => "1320244799633510400",
        //         "category" => "USDT-FUTURES",
        //         "symbol" => "BTCUSDT",
        //         "orderType" => "limit",
        //         "side" => "buy",
        //         "price" => "50000",
        //         "qty" => "0.001",
        //         "amount" => "0",
        //         "cumExecQty" => "0",
        //         "cumExecValue" => "0",
        //         "avgPrice" => "0",
        //         "timeInForce" => "gtc",
        //         "orderStatus" => "live",
        //         "posSide" => "long",
        //         "holdMode" => "hedge_mode",
        //         "reduceOnly" => "NO",
        //         "feeDetail" => [array(
        //             "feeCoin" => "",
        //             "fee" => ""
        //         )],
        //         "createdTime" => "1750496809871",
        //         "updatedTime" => "1750496809886",
        //         "cancelReason" => "",
        //         "execType" => "normal",
        //         "stpMode" => "none",
        //         "tpTriggerBy" => null,
        //         "slTriggerBy" => null,
        //         "takeProfit" => null,
        //         "stopLoss" => null,
        //         "tpOrderType" => null,
        //         "slOrderType" => null,
        //         "tpLimitPrice" => null,
        //         "slLimitPrice" => null
        //     }
        //
        // $uta trigger => fetchClosedOrders, fetchCanceledOrders
        //
        //     {
        //         "orderId" => "1330984742276198400",
        //         "clientOid" => "1330984742276198400",
        //         "symbol" => "BTCUSDT",
        //         "category" => "USDT-FUTURES",
        //         "qty" => "0.001",
        //         "posSide" => "long",
        //         "tpTriggerBy" => "market",
        //         "slTriggerBy" => "mark",
        //         "takeProfit" => "",
        //         "stopLoss" => "112000",
        //         "tpOrderType" => "market",
        //         "slOrderType" => "limit",
        //         "tpLimitPrice" => "",
        //         "slLimitPrice" => "111000",
        //         "createdTime" => "1753057411736",
        //         "updatedTime" => "1753058267412"
        //     }
        //
        $errorMessage = $this->safe_string($order, 'errorMsg');
        if ($errorMessage !== null) {
            return $this->safe_order(array(
                'info' => $order,
                'id' => $this->safe_string($order, 'orderId'),
                'clientOrderId' => $this->safe_string_2($order, 'clientOrderId', 'clientOid'),
                'status' => 'rejected',
            ), $market);
        }
        $posSide = $this->safe_string($order, 'posSide');
        $isContractOrder = ($posSide !== null);
        $marketType = $isContractOrder ? 'contract' : 'spot';
        if ($market !== null) {
            $marketType = $market['type'];
        }
        $marketId = $this->safe_string($order, 'symbol');
        $market = $this->safe_market($marketId, $market, null, $marketType);
        $timestamp = $this->safe_integer_n($order, array( 'cTime', 'ctime', 'createdTime' ));
        $updateTimestamp = $this->safe_integer_2($order, 'uTime', 'updatedTime');
        $rawStatus = $this->safe_string_n($order, array( 'status', 'state', 'orderStatus', 'planStatus' ));
        $fee = null;
        $feeCostString = $this->safe_string($order, 'fee');
        if ($feeCostString !== null) {
            // swap
            $fee = array(
                'cost' => $this->parse_number(Precise::string_neg($feeCostString)),
                'currency' => $market['settle'],
            );
        }
        $feeDetail = $this->safe_value($order, 'feeDetail');
        $uta = $this->safe_string($order, 'category') !== null;
        if ($uta) {
            $feeResult = $this->safe_dict($feeDetail, 0, array());
            $utaFee = $this->safe_string($feeResult, 'fee');
            $fee = array(
                'cost' => $this->parse_number(Precise::string_neg($utaFee)),
                'currency' => $market['settle'],
            );
        } else {
            if ($feeDetail !== null) {
                $parsedFeeDetail = json_decode($feeDetail, $as_associative_array = true);
                $feeValues = is_array($parsedFeeDetail) ? array_values($parsedFeeDetail) : array();
                $feeObject = null;
                for ($i = 0; $i < count($feeValues); $i++) {
                    $feeValue = $feeValues[$i];
                    if ($this->safe_value($feeValue, 'feeCoinCode') !== null) {
                        $feeObject = $feeValue;
                        break;
                    }
                }
                $fee = array(
                    'cost' => $this->parse_number(Precise::string_neg($this->safe_string($feeObject, 'totalFee'))),
                    'currency' => $this->safe_currency_code($this->safe_string($feeObject, 'feeCoinCode')),
                );
            }
        }
        $postOnly = null;
        $timeInForce = $this->safe_string_upper_2($order, 'force', 'timeInForce');
        if ($timeInForce === 'POST_ONLY') {
            $postOnly = true;
            $timeInForce = 'PO';
        }
        $reduceOnly = null;
        $reduceOnlyRaw = $this->safe_string($order, 'reduceOnly');
        if ($reduceOnlyRaw !== null) {
            $reduceOnly = ($reduceOnlyRaw === 'NO') ? false : true;
        }
        $price = null;
        $average = null;
        $basePrice = $this->safe_string($order, 'basePrice');
        if ($basePrice !== null) {
            // for spot fetchOpenOrders, the $price is priceAvg and the $filled $price is $basePrice
            $price = $this->safe_string($order, 'priceAvg');
            $average = $this->safe_string($order, 'basePrice');
        } else {
            $price = $this->safe_string_n($order, array( 'price', 'executePrice', 'slLimitPrice', 'tpLimitPrice' ));
            $average = $this->safe_string($order, 'priceAvg');
        }
        $size = null;
        $filled = null;
        $baseSize = $this->safe_string($order, 'baseSize');
        if ($baseSize !== null) {
            // for spot margin fetchOpenOrders, the $order $size is $baseSize and the $filled amount is $size
            $size = $baseSize;
            $filled = $this->safe_string($order, 'size');
        } else {
            $size = $this->safe_string_2($order, 'size', 'qty');
            $filled = $this->safe_string_2($order, 'baseVolume', 'cumExecQty');
        }
        $side = $this->safe_string($order, 'side');
        $posMode = $this->safe_string($order, 'posMode');
        if ($posMode === 'hedge_mode' && $reduceOnly) {
            $side = ($side === 'buy') ? 'sell' : 'buy';
            // on bitget hedge mode if the position is long the $side is always buy, and if the position is short the $side is always sell
            // so the $side of the $reduceOnly $order is inversed
        }
        $orderType = $this->safe_string($order, 'orderType');
        $isBuyMarket = ($side === 'buy') && ($orderType === 'market');
        if ($market['spot'] && $isBuyMarket) {
            // in top comment, for 'buy market' the 'size' field is COST, not AMOUNT
            $size = $this->safe_string($order, 'baseVolume');
        }
        return $this->safe_order(array(
            'info' => $order,
            'id' => $this->safe_string_2($order, 'orderId', 'data'),
            'clientOrderId' => $this->safe_string_2($order, 'clientOrderId', 'clientOid'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'lastTradeTimestamp' => $updateTimestamp,
            'lastUpdateTimestamp' => $updateTimestamp,
            'symbol' => $market['symbol'],
            'type' => $orderType,
            'side' => $side,
            'price' => $price,
            'amount' => $size,
            'cost' => $this->safe_string_2($order, 'quoteVolume', 'quoteSize'),
            'average' => $average,
            'filled' => $filled,
            'remaining' => null,
            'timeInForce' => $timeInForce,
            'postOnly' => $postOnly,
            'reduceOnly' => $reduceOnly,
            'triggerPrice' => $this->safe_number($order, 'triggerPrice'),
            'takeProfitPrice' => $this->safe_number_n($order, array( 'presetStopSurplusPrice', 'stopSurplusTriggerPrice', 'takeProfit' )),
            'stopLossPrice' => $this->safe_number_n($order, array( 'presetStopLossPrice', 'stopLossTriggerPrice', 'stopLoss' )),
            'status' => $this->parse_order_status($rawStatus),
            'fee' => $fee,
            'trades' => null,
        ), $market);
    }

    public function create_market_buy_order_with_cost(string $symbol, float $cost, $params = array ()) {
        return Async\async(function () use ($symbol, $cost, $params) {
            /**
             * create a $market buy order by providing the $symbol and $cost
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Place-Order
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Cross-Place-Order
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
             *
             * @param {string} $symbol unified $symbol of the $market to create an order in
             * @param {float} $cost how much you want to trade in units of the quote currency
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['spot']) {
                throw new NotSupported($this->id . ' createMarketBuyOrderWithCost() supports spot orders only');
            }
            $req = array(
                'createMarketBuyOrderRequiresPrice' => false,
            );
            return Async\await($this->create_order($symbol, 'market', 'buy', $cost, null, $this->extend($req, $params)));
        }) ();
    }

    public function create_order(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        return Async\async(function () use ($symbol, $type, $side, $amount, $price, $params) {
            /**
             * create a trade order
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Place-Order
             * @see https://www.bitget.com/api-doc/spot/plan/Place-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Place-Order
             * @see https://www.bitget.com/api-doc/contract/plan/Place-Tpsl-Order
             * @see https://www.bitget.com/api-doc/contract/plan/Place-Plan-Order
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Cross-Place-Order
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
             * @see https://www.bitget.com/api-doc/uta/trade/Place-Order
             * @see https://www.bitget.com/api-doc/uta/strategy/Place-Strategy-Order
             *
             * @param {string} $symbol unified $symbol of the $market to create an order in
             * @param {string} $type 'market' or 'limit'
             * @param {string} $side 'buy' or 'sell'
             * @param {float} $amount how much you want to trade in units of the base currency
             * @param {float} [$price] the $price at which the order is to be fulfilled, in units of the quote currency, ignored in $market orders
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {float} [$params->cost] *spot only* how much you want to trade in units of the quote currency, for $market buy orders only
             * @param {float} [$params->triggerPrice] *swap only* The $price at which a trigger order is triggered at
             * @param {float} [$params->stopLossPrice] *swap only* The $price at which a stop loss order is triggered at
             * @param {float} [$params->takeProfitPrice] *swap only* The $price at which a take profit order is triggered at
             * @param {array} [$params->takeProfit] *takeProfit object in $params* containing the $triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
             * @param {float} [$params->takeProfit.triggerPrice] *swap only* take profit trigger $price
             * @param {array} [$params->stopLoss] *stopLoss object in $params* containing the $triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
             * @param {float} [$params->stopLoss.triggerPrice] *swap only* stop loss trigger $price
             * @param {string} [$params->timeInForce] "GTC", "IOC", "FOK", or "PO"
             * @param {string} [$params->marginMode] 'isolated' or 'cross' for spot margin trading
             * @param {string} [$params->loanType] *spot margin only* 'normal', 'autoLoan', 'autoRepay', or 'autoLoanAndRepay' default is 'normal'
             * @param {string} [$params->holdSide] *contract stopLossPrice, takeProfitPrice only* Two-way position => ('long' or 'short'), one-way position => ('buy' or 'sell')
             * @param {float} [$params->stopLoss.price] *swap only* the execution $price for a stop loss attached to a trigger order
             * @param {float} [$params->takeProfit.price] *swap only* the execution $price for a take profit attached to a trigger order
             * @param {string} [$params->stopLoss.type] *swap only* the $type for a stop loss attached to a trigger order, 'fill_price', 'index_price' or 'mark_price', default is 'mark_price'
             * @param {string} [$params->takeProfit.type] *swap only* the $type for a take profit attached to a trigger order, 'fill_price', 'index_price' or 'mark_price', default is 'mark_price'
             * @param {string} [$params->trailingPercent] *swap and future only* the percent to trail away from the current $market $price, rate can not be greater than 10
             * @param {string} [$params->trailingTriggerPrice] *swap and future only* the $price to trigger a trailing stop order, default uses the $price argument
             * @param {string} [$params->triggerType] *swap and future only* 'fill_price', 'mark_price' or 'index_price'
             * @param {boolean} [$params->oneWayMode] *swap and future only* required to set this to true in one_way_mode and you can leave this in hedge_mode, can adjust the mode using the setPositionMode() method
             * @param {bool} [$params->hedged] *swap and future only* true for hedged mode, false for one way mode, default is false
             * @param {bool} [$params->reduceOnly] true or false whether the order is reduce-only
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {string} [$params->posSide] *$uta only* hedged two-way position $side, long or short
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $marginParams = $this->handle_margin_mode_and_params('createOrder', $params);
            $marginMode = $marginParams[0];
            $triggerPrice = $this->safe_value_2($params, 'stopPrice', 'triggerPrice');
            $stopLossTriggerPrice = $this->safe_value($params, 'stopLossPrice');
            $takeProfitTriggerPrice = $this->safe_value($params, 'takeProfitPrice');
            $trailingPercent = $this->safe_string_2($params, 'trailingPercent', 'callbackRatio');
            $isTrailingPercentOrder = $trailingPercent !== null;
            $isTriggerOrder = $triggerPrice !== null;
            $isStopLossTriggerOrder = $stopLossTriggerPrice !== null;
            $isTakeProfitTriggerOrder = $takeProfitTriggerPrice !== null;
            $isStopLossOrTakeProfitTrigger = $isStopLossTriggerOrder || $isTakeProfitTriggerOrder;
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'createOrder', 'uta', false);
            if ($uta) {
                $request = $this->create_uta_order_request($symbol, $type, $side, $amount, $price, $params);
                if ($isStopLossOrTakeProfitTrigger) {
                    $response = Async\await($this->privateUtaPostV3TradePlaceStrategyOrder ($request));
                } else {
                    $response = Async\await($this->privateUtaPostV3TradePlaceOrder ($request));
                }
            } else {
                $request = $this->create_order_request($symbol, $type, $side, $amount, $price, $params);
                if ($market['spot']) {
                    if ($isTriggerOrder) {
                        $response = Async\await($this->privateSpotPostV2SpotTradePlacePlanOrder ($request));
                    } elseif ($marginMode === 'isolated') {
                        $response = Async\await($this->privateMarginPostV2MarginIsolatedPlaceOrder ($request));
                    } elseif ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginPostV2MarginCrossedPlaceOrder ($request));
                    } else {
                        $response = Async\await($this->privateSpotPostV2SpotTradePlaceOrder ($request));
                    }
                } else {
                    if ($isTriggerOrder || $isTrailingPercentOrder) {
                        $response = Async\await($this->privateMixPostV2MixOrderPlacePlanOrder ($request));
                    } elseif ($isStopLossOrTakeProfitTrigger) {
                        $response = Async\await($this->privateMixPostV2MixOrderPlaceTpslOrder ($request));
                    } else {
                        $response = Async\await($this->privateMixPostV2MixOrderPlaceOrder ($request));
                    }
                }
            }
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1645932209602,
            //         "data" => {
            //             "orderId" => "881669078313766912",
            //             "clientOid" => "iauIBf#a45b595f96474d888d0ada"
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function create_uta_order_request(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        $market = $this->market($symbol);
        $productType = null;
        list($productType, $params) = $this->handle_product_type_and_params($market, $params);
        if ($productType === 'SPOT') {
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('createOrder', $params);
            if ($marginMode !== null) {
                $productType = 'MARGIN';
            }
        }
        $request = array(
            'category' => $productType,
            'symbol' => $market['id'],
            'qty' => $this->amount_to_precision($symbol, $amount),
            'side' => $side,
        );
        $clientOrderId = $this->safe_string_2($params, 'clientOid', 'clientOrderId');
        if ($clientOrderId !== null) {
            $request['clientOid'] = $clientOrderId;
            $params = $this->omit($params, 'clientOrderId');
        }
        $stopLossTriggerPrice = $this->safe_number($params, 'stopLossPrice');
        $takeProfitTriggerPrice = $this->safe_number($params, 'takeProfitPrice');
        $stopLoss = $this->safe_value($params, 'stopLoss');
        $takeProfit = $this->safe_value($params, 'takeProfit');
        $isStopLoss = $stopLoss !== null;
        $isTakeProfit = $takeProfit !== null;
        $isStopLossTrigger = $stopLossTriggerPrice !== null;
        $isTakeProfitTrigger = $takeProfitTriggerPrice !== null;
        $isStopLossOrTakeProfitTrigger = $isStopLossTrigger || $isTakeProfitTrigger;
        if ($isStopLossOrTakeProfitTrigger) {
            if ($isStopLossTrigger) {
                $slType = $this->safe_string($params, 'slTriggerBy', 'mark');
                $request['slTriggerBy'] = $slType;
                $request['stopLoss'] = $this->price_to_precision($symbol, $stopLossTriggerPrice);
                if ($price !== null) {
                    $request['slLimitPrice'] = $this->price_to_precision($symbol, $price);
                    $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'limit');
                } else {
                    $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'market');
                }
            } elseif ($isTakeProfitTrigger) {
                $tpType = $this->safe_string($params, 'tpTriggerBy', 'mark');
                $request['tpTriggerBy'] = $tpType;
                $request['takeProfit'] = $this->price_to_precision($symbol, $takeProfitTriggerPrice);
                if ($price !== null) {
                    $request['tpLimitPrice'] = $this->price_to_precision($symbol, $price);
                    $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'limit');
                } else {
                    $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'market');
                }
            }
            $params = $this->omit($params, array( 'stopLossPrice', 'takeProfitPrice' ));
        } else {
            if ($isStopLoss) {
                $slTriggerPrice = $this->safe_number_2($stopLoss, 'triggerPrice', 'stopPrice');
                $slLimitPrice = $this->safe_number($stopLoss, 'price');
                $request['stopLoss'] = $this->price_to_precision($symbol, $slTriggerPrice);
                if ($slLimitPrice !== null) {
                    $request['slLimitPrice'] = $this->price_to_precision($symbol, $slLimitPrice);
                    $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'limit');
                } else {
                    $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'market');
                }
            }
            if ($isTakeProfit) {
                $tpTriggerPrice = $this->safe_number_2($takeProfit, 'triggerPrice', 'stopPrice');
                $tpLimitPrice = $this->safe_number($takeProfit, 'price');
                $request['takeProfit'] = $this->price_to_precision($symbol, $tpTriggerPrice);
                if ($tpLimitPrice !== null) {
                    $request['tpLimitPrice'] = $this->price_to_precision($symbol, $tpLimitPrice);
                    $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'limit');
                } else {
                    $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'market');
                }
            }
            $isMarketOrder = $type === 'market';
            if (!$isMarketOrder) {
                $request['price'] = $this->price_to_precision($symbol, $price);
            }
            $request['orderType'] = $type;
            $exchangeSpecificTifParam = $this->safe_string($params, 'timeInForce');
            $postOnly = null;
            list($postOnly, $params) = $this->handle_post_only($isMarketOrder, $exchangeSpecificTifParam === 'post_only', $params);
            $defaultTimeInForce = $this->safe_string_upper($this->options, 'defaultTimeInForce');
            $timeInForce = $this->safe_string_upper($params, 'timeInForce', $defaultTimeInForce);
            if ($postOnly) {
                $request['timeInForce'] = 'post_only';
            } elseif ($timeInForce === 'GTC') {
                $request['timeInForce'] = 'gtc';
            } elseif ($timeInForce === 'FOK') {
                $request['timeInForce'] = 'fok';
            } elseif ($timeInForce === 'IOC') {
                $request['timeInForce'] = 'ioc';
            }
        }
        $reduceOnly = $this->safe_bool($params, 'reduceOnly', false);
        $hedged = null;
        list($hedged, $params) = $this->handle_param_bool($params, 'hedged', false);
        if ($reduceOnly) {
            if ($hedged || $isStopLossOrTakeProfitTrigger) {
                $reduceOnlyPosSide = ($side === 'sell') ? 'long' : 'short';
                $request['posSide'] = $reduceOnlyPosSide;
            } elseif (!$isStopLossOrTakeProfitTrigger) {
                $request['reduceOnly'] = 'yes';
            }
        } else {
            if ($hedged) {
                $posSide = ($side === 'buy') ? 'long' : 'short';
                $request['posSide'] = $posSide;
            }
        }
        $params = $this->omit($params, array( 'stopLoss', 'takeProfit', 'postOnly', 'reduceOnly', 'hedged' ));
        return $this->extend($request, $params);
    }

    public function create_order_request(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        $market = $this->market($symbol);
        $marketType = null;
        $marginMode = null;
        list($marketType, $params) = $this->handle_market_type_and_params('createOrder', $market, $params);
        list($marginMode, $params) = $this->handle_margin_mode_and_params('createOrder', $params);
        $request = array(
            'symbol' => $market['id'],
            'orderType' => $type,
        );
        $hedged = null;
        list($hedged, $params) = $this->handle_param_bool($params, 'hedged', false);
        // backward compatibility for `$oneWayMode`
        $oneWayMode = null;
        list($oneWayMode, $params) = $this->handle_param_bool($params, 'oneWayMode');
        if ($oneWayMode !== null) {
            $hedged = !$oneWayMode;
        }
        $isMarketOrder = $type === 'market';
        $triggerPrice = $this->safe_value_2($params, 'stopPrice', 'triggerPrice');
        $stopLossTriggerPrice = $this->safe_value($params, 'stopLossPrice');
        $takeProfitTriggerPrice = $this->safe_value($params, 'takeProfitPrice');
        $stopLoss = $this->safe_value($params, 'stopLoss');
        $takeProfit = $this->safe_value($params, 'takeProfit');
        $isTriggerOrder = $triggerPrice !== null;
        $isStopLossTriggerOrder = $stopLossTriggerPrice !== null;
        $isTakeProfitTriggerOrder = $takeProfitTriggerPrice !== null;
        $isStopLoss = $stopLoss !== null;
        $isTakeProfit = $takeProfit !== null;
        $isStopLossOrTakeProfitTrigger = $isStopLossTriggerOrder || $isTakeProfitTriggerOrder;
        $isStopLossOrTakeProfit = $isStopLoss || $isTakeProfit;
        $trailingTriggerPrice = $this->safe_string($params, 'trailingTriggerPrice', $this->number_to_string($price));
        $trailingPercent = $this->safe_string_2($params, 'trailingPercent', 'callbackRatio');
        $isTrailingPercentOrder = $trailingPercent !== null;
        if ($this->sum($isTriggerOrder, $isStopLossTriggerOrder, $isTakeProfitTriggerOrder, $isTrailingPercentOrder) > 1) {
            throw new ExchangeError($this->id . ' createOrder() $params can only contain one of $triggerPrice, stopLossPrice, takeProfitPrice, trailingPercent');
        }
        if ($type === 'limit') {
            $request['price'] = $this->price_to_precision($symbol, $price);
        }
        $triggerPriceType = $this->safe_string_2($params, 'triggerPriceType', 'triggerType', 'mark_price');
        $reduceOnly = $this->safe_bool($params, 'reduceOnly', false);
        $clientOrderId = $this->safe_string_2($params, 'clientOid', 'clientOrderId');
        $exchangeSpecificTifParam = $this->safe_string_2($params, 'force', 'timeInForce');
        $postOnly = null;
        list($postOnly, $params) = $this->handle_post_only($isMarketOrder, $exchangeSpecificTifParam === 'post_only', $params);
        $defaultTimeInForce = $this->safe_string_upper($this->options, 'defaultTimeInForce');
        $timeInForce = $this->safe_string_upper($params, 'timeInForce', $defaultTimeInForce);
        if ($postOnly) {
            $request['force'] = 'post_only';
        } elseif ($timeInForce === 'GTC') {
            $request['force'] = 'GTC';
        } elseif ($timeInForce === 'FOK') {
            $request['force'] = 'FOK';
        } elseif ($timeInForce === 'IOC') {
            $request['force'] = 'IOC';
        }
        $params = $this->omit($params, array( 'stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'postOnly', 'reduceOnly', 'clientOrderId', 'trailingPercent', 'trailingTriggerPrice' ));
        if (($marketType === 'swap') || ($marketType === 'future')) {
            $request['marginCoin'] = $market['settleId'];
            $request['size'] = $this->amount_to_precision($symbol, $amount);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request['productType'] = $productType;
            if ($clientOrderId !== null) {
                $request['clientOid'] = $clientOrderId;
            }
            if ($isTriggerOrder || $isStopLossOrTakeProfitTrigger || $isTrailingPercentOrder) {
                $request['triggerType'] = $triggerPriceType;
            }
            if ($isTrailingPercentOrder) {
                if (!$isMarketOrder) {
                    throw new BadRequest($this->id . ' createOrder() bitget trailing orders must be $market orders');
                }
                if ($trailingTriggerPrice === null) {
                    throw new ArgumentsRequired($this->id . ' createOrder() bitget trailing orders must have a $trailingTriggerPrice param');
                }
                $request['planType'] = 'track_plan';
                $request['triggerPrice'] = $this->price_to_precision($symbol, $trailingTriggerPrice);
                $request['callbackRatio'] = $trailingPercent;
            } elseif ($isTriggerOrder) {
                $request['planType'] = 'normal_plan';
                $request['triggerPrice'] = $this->price_to_precision($symbol, $triggerPrice);
                if ($price !== null) {
                    $request['executePrice'] = $this->price_to_precision($symbol, $price);
                }
                if ($isStopLoss) {
                    $slTriggerPrice = $this->safe_string_2($stopLoss, 'triggerPrice', 'stopPrice');
                    $request['stopLossTriggerPrice'] = $this->price_to_precision($symbol, $slTriggerPrice);
                    $slPrice = $this->safe_string($stopLoss, 'price');
                    $request['stopLossExecutePrice'] = $this->price_to_precision($symbol, $slPrice);
                    $slType = $this->safe_string($stopLoss, 'type', 'mark_price');
                    $request['stopLossTriggerType'] = $slType;
                }
                if ($isTakeProfit) {
                    $tpTriggerPrice = $this->safe_string_2($takeProfit, 'triggerPrice', 'stopPrice');
                    $request['stopSurplusTriggerPrice'] = $this->price_to_precision($symbol, $tpTriggerPrice);
                    $tpPrice = $this->safe_string($takeProfit, 'price');
                    $request['stopSurplusExecutePrice'] = $this->price_to_precision($symbol, $tpPrice);
                    $tpType = $this->safe_string($takeProfit, 'type', 'mark_price');
                    $request['stopSurplusTriggerType'] = $tpType;
                }
            } elseif ($isStopLossOrTakeProfitTrigger) {
                if (!$isMarketOrder) {
                    throw new ExchangeError($this->id . ' createOrder() bitget $stopLoss or $takeProfit orders must be $market orders');
                }
                if ($hedged) {
                    $request['holdSide'] = ($side === 'sell') ? 'long' : 'short';
                } else {
                    $request['holdSide'] = ($side === 'sell') ? 'buy' : 'sell';
                }
                if ($isStopLossTriggerOrder) {
                    $request['triggerPrice'] = $this->price_to_precision($symbol, $stopLossTriggerPrice);
                    $request['planType'] = 'pos_loss';
                } elseif ($isTakeProfitTriggerOrder) {
                    $request['triggerPrice'] = $this->price_to_precision($symbol, $takeProfitTriggerPrice);
                    $request['planType'] = 'pos_profit';
                }
            } else {
                if ($isStopLoss) {
                    $slTriggerPrice = $this->safe_value_2($stopLoss, 'triggerPrice', 'stopPrice');
                    $request['presetStopLossPrice'] = $this->price_to_precision($symbol, $slTriggerPrice);
                }
                if ($isTakeProfit) {
                    $tpTriggerPrice = $this->safe_value_2($takeProfit, 'triggerPrice', 'stopPrice');
                    $request['presetStopSurplusPrice'] = $this->price_to_precision($symbol, $tpTriggerPrice);
                }
            }
            if (!$isStopLossOrTakeProfitTrigger) {
                if ($marginMode === null) {
                    $marginMode = 'cross';
                }
                $marginModeRequest = ($marginMode === 'cross') ? 'crossed' : 'isolated';
                $request['marginMode'] = $marginModeRequest;
                $requestSide = $side;
                if ($reduceOnly) {
                    if (!$hedged) {
                        $request['reduceOnly'] = 'YES';
                    } else {
                        // on bitget hedge mode if the position is long the $side is always buy, and if the position is short the $side is always sell
                        $requestSide = ($side === 'buy') ? 'sell' : 'buy';
                        $request['tradeSide'] = 'Close';
                    }
                } else {
                    if ($hedged) {
                        $request['tradeSide'] = 'Open';
                    }
                }
                $request['side'] = $requestSide;
            }
        } elseif ($marketType === 'spot') {
            if ($isStopLossOrTakeProfitTrigger || $isStopLossOrTakeProfit) {
                throw new InvalidOrder($this->id . ' createOrder() does not support stop loss/take profit orders on spot markets, only swap markets');
            }
            $request['side'] = $side;
            $quantity = null;
            $planType = null;
            $createMarketBuyOrderRequiresPrice = true;
            list($createMarketBuyOrderRequiresPrice, $params) = $this->handle_option_and_params($params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
            if ($isMarketOrder && ($side === 'buy')) {
                $planType = 'total';
                $cost = $this->safe_number($params, 'cost');
                $params = $this->omit($params, 'cost');
                if ($cost !== null) {
                    $quantity = $this->cost_to_precision($symbol, $cost);
                } elseif ($createMarketBuyOrderRequiresPrice) {
                    if ($price === null) {
                        throw new InvalidOrder($this->id . ' createOrder() requires the $price argument for $market buy orders to calculate the total $cost to spend ($amount * $price), alternatively set the $createMarketBuyOrderRequiresPrice option or param to false and pass the $cost to spend in the $amount argument');
                    } else {
                        $amountString = $this->number_to_string($amount);
                        $priceString = $this->number_to_string($price);
                        $quoteAmount = Precise::string_mul($amountString, $priceString);
                        $quantity = $this->cost_to_precision($symbol, $quoteAmount);
                    }
                } else {
                    $quantity = $this->cost_to_precision($symbol, $amount);
                }
            } else {
                $planType = 'amount';
                $quantity = $this->amount_to_precision($symbol, $amount);
            }
            if ($clientOrderId !== null) {
                $request['clientOid'] = $clientOrderId;
            }
            if ($marginMode !== null) {
                $request['loanType'] = 'normal';
                if ($isMarketOrder && ($side === 'buy')) {
                    $request['quoteSize'] = $quantity;
                } else {
                    $request['baseSize'] = $quantity;
                }
            } else {
                if ($quantity !== null) {
                    $request['size'] = $quantity;
                }
                if ($triggerPrice !== null) {
                    $request['planType'] = $planType;
                    $request['triggerType'] = $triggerPriceType;
                    $request['triggerPrice'] = $this->price_to_precision($symbol, $triggerPrice);
                    if ($price !== null) {
                        $request['executePrice'] = $this->price_to_precision($symbol, $price);
                    }
                }
            }
        } else {
            throw new NotSupported($this->id . ' createOrder() does not support ' . $marketType . ' orders');
        }
        return $this->extend($request, $params);
    }

    public function create_uta_orders(array $orders, $params = array ()) {
        return Async\async(function () use ($orders, $params) {
            Async\await($this->load_markets());
            $ordersRequests = array();
            $symbol = null;
            $marginMode = null;
            for ($i = 0; $i < count($orders); $i++) {
                $rawOrder = $orders[$i];
                $marketId = $this->safe_string($rawOrder, 'symbol');
                if ($symbol === null) {
                    $symbol = $marketId;
                } else {
                    if ($symbol !== $marketId) {
                        throw new BadRequest($this->id . ' createOrders() requires all $orders to have the same symbol');
                    }
                }
                $type = $this->safe_string($rawOrder, 'type');
                $side = $this->safe_string($rawOrder, 'side');
                $amount = $this->safe_value($rawOrder, 'amount');
                $price = $this->safe_value($rawOrder, 'price');
                $orderParams = $this->safe_value($rawOrder, 'params', array());
                $marginResult = $this->handle_margin_mode_and_params('createOrders', $orderParams);
                $currentMarginMode = $marginResult[0];
                if ($currentMarginMode !== null) {
                    if ($marginMode === null) {
                        $marginMode = $currentMarginMode;
                    } else {
                        if ($marginMode !== $currentMarginMode) {
                            throw new BadRequest($this->id . ' createOrders() requires all $orders to have the same margin mode (isolated or cross)');
                        }
                    }
                }
                $orderRequest = $this->create_uta_order_request($marketId, $type, $side, $amount, $price, $orderParams);
                $ordersRequests[] = $orderRequest;
            }
            $market = $this->market($symbol);
            $response = Async\await($this->privateUtaPostV3TradePlaceBatch ($ordersRequests));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1752810184560,
            //         "data" => array(
            //             array(
            //                 "orderId" => "1329947796441513984",
            //                 "clientOid" => "1329947796483457024"
            //             ),
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_orders($data, $market);
        }) ();
    }

    public function create_orders(array $orders, $params = array ()) {
        return Async\async(function () use ($orders, $params) {
            /**
             * create a list of trade $orders (all $orders should be of the same $symbol)
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Batch-Place-Orders
             * @see https://www.bitget.com/api-doc/contract/trade/Batch-Order
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Order
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Order
             * @see https://www.bitget.com/api-doc/uta/trade/Place-Batch
             *
             * @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
             * @param {array} [$params] extra parameters specific to the api endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'createOrders', 'uta', false);
            if ($uta) {
                return Async\await($this->create_uta_orders($orders, $params));
            }
            $ordersRequests = array();
            $symbol = null;
            $marginMode = null;
            for ($i = 0; $i < count($orders); $i++) {
                $rawOrder = $orders[$i];
                $marketId = $this->safe_string($rawOrder, 'symbol');
                if ($symbol === null) {
                    $symbol = $marketId;
                } else {
                    if ($symbol !== $marketId) {
                        throw new BadRequest($this->id . ' createOrders() requires all $orders to have the same symbol');
                    }
                }
                $type = $this->safe_string($rawOrder, 'type');
                $side = $this->safe_string($rawOrder, 'side');
                $amount = $this->safe_value($rawOrder, 'amount');
                $price = $this->safe_value($rawOrder, 'price');
                $orderParams = $this->safe_value($rawOrder, 'params', array());
                $marginResult = $this->handle_margin_mode_and_params('createOrders', $orderParams);
                $currentMarginMode = $marginResult[0];
                if ($currentMarginMode !== null) {
                    if ($marginMode === null) {
                        $marginMode = $currentMarginMode;
                    } else {
                        if ($marginMode !== $currentMarginMode) {
                            throw new BadRequest($this->id . ' createOrders() requires all $orders to have the same margin mode (isolated or cross)');
                        }
                    }
                }
                $orderRequest = $this->create_order_request($marketId, $type, $side, $amount, $price, $orderParams);
                $ordersRequests[] = $orderRequest;
            }
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
                'orderList' => $ordersRequests,
            );
            $response = null;
            if (($market['swap']) || ($market['future'])) {
                if ($marginMode === null) {
                    $marginMode = 'cross';
                }
                $marginModeRequest = ($marginMode === 'cross') ? 'crossed' : 'isolated';
                $request['marginMode'] = $marginModeRequest;
                $request['marginCoin'] = $market['settleId'];
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixPostV2MixOrderBatchPlaceOrder ($request));
            } elseif ($marginMode === 'isolated') {
                $response = Async\await($this->privateMarginPostV2MarginIsolatedBatchPlaceOrder ($request));
            } elseif ($marginMode === 'cross') {
                $response = Async\await($this->privateMarginPostV2MarginCrossedBatchPlaceOrder ($request));
            } else {
                $response = Async\await($this->privateSpotPostV2SpotTradeBatchOrders ($request));
            }
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700703539416,
            //         "data" => {
            //             "successList" => array(
            //                 array(
            //                     "orderId" => "1111397214281175046",
            //                     "clientOid" => "766d3fc3-7321-4406-a689-15c9987a2e75"
            //                 ),
            //             ),
            //             "failureList" => array(
            //                 array(
            //                     "orderId" => "",
            //                     "clientOid" => "d1b75cb3-cc15-4ede-ad4c-3937396f75ab",
            //                     "errorMsg" => "less than the minimum $amount 5 USDT",
            //                     "errorCode" => "45110"
            //                 ),
            //             )
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $failure = $this->safe_value($data, 'failureList', array());
            $orderInfo = $this->safe_value($data, 'successList', array());
            $both = $this->array_concat($orderInfo, $failure);
            return $this->parse_orders($both, $market);
        }) ();
    }

    public function edit_order(string $id, string $symbol, string $type, string $side, ?float $amount = null, ?float $price = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $type, $side, $amount, $price, $params) {
            /**
             * edit a trade order
             *
             * @see https://www.bitget.com/api-doc/spot/plan/Modify-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Modify-Order
             * @see https://www.bitget.com/api-doc/contract/plan/Modify-Tpsl-Order
             * @see https://www.bitget.com/api-doc/contract/plan/Modify-Plan-Order
             * @see https://www.bitget.com/api-doc/uta/trade/Modify-Order
             * @see https://www.bitget.com/api-doc/uta/strategy/Modify-Strategy-Order
             *
             * @param {string} $id cancel order $id
             * @param {string} $symbol unified $symbol of the $market to create an order in
             * @param {string} $type 'market' or 'limit'
             * @param {string} $side 'buy' or 'sell'
             * @param {float} $amount how much you want to trade in units of the base currency
             * @param {float} [$price] the $price at which the order is to be fulfilled, in units of the quote currency, ignored in $market orders
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {float} [$params->triggerPrice] the $price that a trigger order is triggered at
             * @param {float} [$params->stopLossPrice] *swap only* The $price at which a stop loss order is triggered at
             * @param {float} [$params->takeProfitPrice] *swap only* The $price at which a take profit order is triggered at
             * @param {array} [$params->takeProfit] *$takeProfit object in $params* containing the $triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
             * @param {float} [$params->takeProfit.triggerPrice] *swap only* take profit trigger $price
             * @param {array} [$params->stopLoss] *$stopLoss object in $params* containing the $triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
             * @param {float} [$params->stopLoss.triggerPrice] *swap only* stop loss trigger $price
             * @param {float} [$params->stopLoss.price] *swap only* the execution $price for a stop loss attached to a trigger order
             * @param {float} [$params->takeProfit.price] *swap only* the execution $price for a take profit attached to a trigger order
             * @param {string} [$params->stopLoss.type] *swap only* the $type for a stop loss attached to a trigger order, 'fill_price', 'index_price' or 'mark_price', default is 'mark_price'
             * @param {string} [$params->takeProfit.type] *swap only* the $type for a take profit attached to a trigger order, 'fill_price', 'index_price' or 'mark_price', default is 'mark_price'
             * @param {string} [$params->trailingPercent] *swap and future only* the percent to trail away from the current $market $price, rate can not be greater than 10
             * @param {string} [$params->trailingTriggerPrice] *swap and future only* the $price to trigger a trailing stop order, default uses the $price argument
             * @param {string} [$params->newTriggerType] *swap and future only* 'fill_price', 'mark_price' or 'index_price'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} an ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'orderId' => $id,
            );
            $isMarketOrder = $type === 'market';
            $triggerPrice = $this->safe_value_2($params, 'stopPrice', 'triggerPrice');
            $isTriggerOrder = $triggerPrice !== null;
            $stopLossPrice = $this->safe_value($params, 'stopLossPrice');
            $isStopLossOrder = $stopLossPrice !== null;
            $takeProfitPrice = $this->safe_value($params, 'takeProfitPrice');
            $isTakeProfitOrder = $takeProfitPrice !== null;
            $stopLoss = $this->safe_value($params, 'stopLoss');
            $takeProfit = $this->safe_value($params, 'takeProfit');
            $isStopLoss = $stopLoss !== null;
            $isTakeProfit = $takeProfit !== null;
            $trailingTriggerPrice = $this->safe_string($params, 'trailingTriggerPrice', $this->number_to_string($price));
            $trailingPercent = $this->safe_string_2($params, 'trailingPercent', 'newCallbackRatio');
            $isTrailingPercentOrder = $trailingPercent !== null;
            if ($this->sum($isTriggerOrder, $isStopLossOrder, $isTakeProfitOrder, $isTrailingPercentOrder) > 1) {
                throw new ExchangeError($this->id . ' editOrder() $params can only contain one of $triggerPrice, $stopLossPrice, $takeProfitPrice, trailingPercent');
            }
            $clientOrderId = $this->safe_string_2($params, 'clientOid', 'clientOrderId');
            if ($clientOrderId !== null) {
                $request['clientOid'] = $clientOrderId;
            }
            $params = $this->omit($params, array( 'stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent' ));
            $response = null;
            $productType = null;
            $uta = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'editOrder', 'uta', false);
            if ($uta) {
                if ($amount !== null) {
                    $request['qty'] = $this->amount_to_precision($symbol, $amount);
                }
                if ($isStopLossOrder || $isTakeProfitOrder) {
                    if ($isStopLossOrder) {
                        $slType = $this->safe_string($params, 'slTriggerBy', 'mark');
                        $request['slTriggerBy'] = $slType;
                        $request['stopLoss'] = $this->price_to_precision($symbol, $stopLossPrice);
                        if ($price !== null) {
                            $request['slLimitPrice'] = $this->price_to_precision($symbol, $price);
                            $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'limit');
                        } else {
                            $request['slOrderType'] = $this->safe_string($params, 'slOrderType', 'market');
                        }
                    } elseif ($isTakeProfitOrder) {
                        $tpType = $this->safe_string($params, 'tpTriggerBy', 'mark');
                        $request['tpTriggerBy'] = $tpType;
                        $request['takeProfit'] = $this->price_to_precision($symbol, $takeProfitPrice);
                        if ($price !== null) {
                            $request['tpLimitPrice'] = $this->price_to_precision($symbol, $price);
                            $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'limit');
                        } else {
                            $request['tpOrderType'] = $this->safe_string($params, 'tpOrderType', 'market');
                        }
                    }
                    $params = $this->omit($params, array( 'stopLossPrice', 'takeProfitPrice' ));
                    $response = Async\await($this->privateUtaPostV3TradeModifyStrategyOrder ($this->extend($request, $params)));
                } else {
                    if ($price !== null) {
                        $request['price'] = $this->price_to_precision($symbol, $price);
                    }
                    $response = Async\await($this->privateUtaPostV3TradeModifyOrder ($this->extend($request, $params)));
                }
            } elseif ($market['spot']) {
                if ($triggerPrice === null) {
                    throw new NotSupported($this->id . ' editOrder() only supports plan/trigger spot orders');
                }
                $editMarketBuyOrderRequiresPrice = $this->safe_bool($this->options, 'editMarketBuyOrderRequiresPrice', true);
                if ($editMarketBuyOrderRequiresPrice && $isMarketOrder && ($side === 'buy')) {
                    if ($price === null) {
                        throw new InvalidOrder($this->id . ' editOrder() requires $price argument for $market buy orders on spot markets to calculate the total $amount to spend ($amount * $price), alternatively set the $editMarketBuyOrderRequiresPrice option to false and pass in the $cost to spend into the $amount parameter');
                    } else {
                        $amountString = $this->number_to_string($amount);
                        $priceString = $this->number_to_string($price);
                        $cost = $this->parse_number(Precise::string_mul($amountString, $priceString));
                        $request['size'] = $this->price_to_precision($symbol, $cost);
                    }
                } else {
                    $request['size'] = $this->amount_to_precision($symbol, $amount);
                }
                $request['orderType'] = $type;
                $request['triggerPrice'] = $this->price_to_precision($symbol, $triggerPrice);
                $request['executePrice'] = $this->price_to_precision($symbol, $price);
                $response = Async\await($this->privateSpotPostV2SpotTradeModifyPlanOrder ($this->extend($request, $params)));
            } else {
                if ((!$market['swap']) && (!$market['future'])) {
                    throw new NotSupported($this->id . ' editOrder() does not support ' . $market['type'] . ' orders');
                }
                $request['symbol'] = $market['id'];
                $request['productType'] = $productType;
                if (!$isTakeProfitOrder && !$isStopLossOrder) {
                    $request['newSize'] = $this->amount_to_precision($symbol, $amount);
                    if (($price !== null) && !$isTrailingPercentOrder) {
                        $request['newPrice'] = $this->price_to_precision($symbol, $price);
                    }
                }
                if ($isTrailingPercentOrder) {
                    if (!$isMarketOrder) {
                        throw new BadRequest($this->id . ' editOrder() bitget trailing orders must be $market orders');
                    }
                    if ($trailingTriggerPrice !== null) {
                        $request['newTriggerPrice'] = $this->price_to_precision($symbol, $trailingTriggerPrice);
                    }
                    $request['newCallbackRatio'] = $trailingPercent;
                    $response = Async\await($this->privateMixPostV2MixOrderModifyPlanOrder ($this->extend($request, $params)));
                } elseif ($isTakeProfitOrder || $isStopLossOrder) {
                    $request['marginCoin'] = $market['settleId'];
                    $request['size'] = $this->amount_to_precision($symbol, $amount);
                    if ($price !== null) {
                        $request['executePrice'] = $this->price_to_precision($symbol, $price);
                    }
                    if ($isStopLossOrder) {
                        $request['triggerPrice'] = $this->price_to_precision($symbol, $stopLossPrice);
                    } elseif ($isTakeProfitOrder) {
                        $request['triggerPrice'] = $this->price_to_precision($symbol, $takeProfitPrice);
                    }
                    $response = Async\await($this->privateMixPostV2MixOrderModifyTpslOrder ($this->extend($request, $params)));
                } elseif ($isTriggerOrder) {
                    $request['newTriggerPrice'] = $this->price_to_precision($symbol, $triggerPrice);
                    if ($isStopLoss) {
                        $slTriggerPrice = $this->safe_number_2($stopLoss, 'triggerPrice', 'stopPrice');
                        $request['newStopLossTriggerPrice'] = $this->price_to_precision($symbol, $slTriggerPrice);
                        $slPrice = $this->safe_number($stopLoss, 'price');
                        $request['newStopLossExecutePrice'] = $this->price_to_precision($symbol, $slPrice);
                        $slType = $this->safe_string($stopLoss, 'type', 'mark_price');
                        $request['newStopLossTriggerType'] = $slType;
                    }
                    if ($isTakeProfit) {
                        $tpTriggerPrice = $this->safe_number_2($takeProfit, 'triggerPrice', 'stopPrice');
                        $request['newSurplusTriggerPrice'] = $this->price_to_precision($symbol, $tpTriggerPrice);
                        $tpPrice = $this->safe_number($takeProfit, 'price');
                        $request['newStopSurplusExecutePrice'] = $this->price_to_precision($symbol, $tpPrice);
                        $tpType = $this->safe_string($takeProfit, 'type', 'mark_price');
                        $request['newStopSurplusTriggerType'] = $tpType;
                    }
                    $response = Async\await($this->privateMixPostV2MixOrderModifyPlanOrder ($this->extend($request, $params)));
                } else {
                    $defaultNewClientOrderId = $this->uuid();
                    $newClientOrderId = $this->safe_string_2($params, 'newClientOid', 'newClientOrderId', $defaultNewClientOrderId);
                    $params = $this->omit($params, 'newClientOrderId');
                    $request['newClientOid'] = $newClientOrderId;
                    if ($isStopLoss) {
                        $slTriggerPrice = $this->safe_value_2($stopLoss, 'triggerPrice', 'stopPrice');
                        $request['newPresetStopLossPrice'] = $this->price_to_precision($symbol, $slTriggerPrice);
                    }
                    if ($isTakeProfit) {
                        $tpTriggerPrice = $this->safe_value_2($takeProfit, 'triggerPrice', 'stopPrice');
                        $request['newPresetStopSurplusPrice'] = $this->price_to_precision($symbol, $tpTriggerPrice);
                    }
                    $response = Async\await($this->privateMixPostV2MixOrderModifyOrder ($this->extend($request, $params)));
                }
            }
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700708275737,
            //         "data" => {
            //             "clientOid" => "abe95dbe-6081-4a6f-a2d3-ae49601cd459",
            //             "orderId" => null
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function cancel_order(string $id, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $params) {
            /**
             * cancels an open $order
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Cancel-Order
             * @see https://www.bitget.com/api-doc/spot/plan/Cancel-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Cancel-Order
             * @see https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Cross-Cancel-Order
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Cancel-Order
             * @see https://www.bitget.com/api-doc/uta/trade/Cancel-Order
             * @see https://www.bitget.com/api-doc/uta/strategy/Cancel-Strategy-Order
             *
             * @param {string} $id $order $id
             * @param {string} $symbol unified $symbol of the $market the $order was made in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'isolated' or 'cross' for spot margin trading
             * @param {boolean} [$params->trigger] set to true for canceling $trigger orders
             * @param {string} [$params->planType] *swap only* either profit_plan, loss_plan, normal_plan, pos_profit, pos_loss, moving_plan or track_plan
             * @param {boolean} [$params->trailing] set to true if you want to cancel a $trailing $order
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {string} [$params->clientOrderId] the $clientOrderId of the $order, $id does not need to be provided if $clientOrderId is provided
             * @return {array} An ~@link https://docs.ccxt.com/#/?$id=$order-structure $order structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelOrder() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $marginMode = null;
            $response = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('cancelOrder', $params);
            $request = array();
            $trailing = $this->safe_value($params, 'trailing');
            $trigger = $this->safe_value_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger', 'trailing' ));
            if (!($market['spot'] && $trigger)) {
                $request['symbol'] = $market['id'];
            }
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'cancelOrder', 'uta', false);
            $isPlanOrder = $trigger || $trailing;
            $isContract = $market['swap'] || $market['future'];
            $isContractTriggerEndpoint = $isContract && $isPlanOrder && !$uta;
            $clientOrderId = $this->safe_string_2($params, 'clientOrderId', 'clientOid');
            if ($isContractTriggerEndpoint) {
                $orderIdList = array();
                $orderId = array();
                if ($clientOrderId !== null) {
                    $params = $this->omit($params, 'clientOrderId');
                    $orderId['clientOid'] = $clientOrderId;
                } else {
                    $orderId['orderId'] = $id;
                }
                $orderIdList[] = $orderId;
                $request['orderIdList'] = $orderIdList;
            } else {
                if ($clientOrderId !== null) {
                    $params = $this->omit($params, 'clientOrderId');
                    $request['clientOid'] = $clientOrderId;
                } else {
                    $request['orderId'] = $id;
                }
            }
            if ($uta) {
                if ($trigger) {
                    $response = Async\await($this->privateUtaPostV3TradeCancelStrategyOrder ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateUtaPostV3TradeCancelOrder ($this->extend($request, $params)));
                }
            } elseif (($market['swap']) || ($market['future'])) {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                if ($trailing) {
                    $planType = $this->safe_string($params, 'planType', 'track_plan');
                    $request['planType'] = $planType;
                    $response = Async\await($this->privateMixPostV2MixOrderCancelPlanOrder ($this->extend($request, $params)));
                } elseif ($trigger) {
                    $response = Async\await($this->privateMixPostV2MixOrderCancelPlanOrder ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateMixPostV2MixOrderCancelOrder ($this->extend($request, $params)));
                }
            } elseif ($market['spot']) {
                if ($marginMode !== null) {
                    if ($marginMode === 'isolated') {
                        $response = Async\await($this->privateMarginPostV2MarginIsolatedCancelOrder ($this->extend($request, $params)));
                    } elseif ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginPostV2MarginCrossedCancelOrder ($this->extend($request, $params)));
                    }
                } else {
                    if ($trigger) {
                        $response = Async\await($this->privateSpotPostV2SpotTradeCancelPlanOrder ($this->extend($request, $params)));
                    } else {
                        $response = Async\await($this->privateSpotPostV2SpotTradeCancelOrder ($this->extend($request, $params)));
                    }
                }
            } else {
                throw new NotSupported($this->id . ' cancelOrder() does not support ' . $market['type'] . ' orders');
            }
            //
            // spot, swap, future and spot margin
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1697690413177,
            //         "data" => {
            //             "orderId" => "1098758604547850241",
            //             "clientOid" => "1098758604585598977"
            //         }
            //     }
            //
            // swap $trigger
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700711311791,
            //         "data" => {
            //             "successList" => array(
            //                 {
            //                     "clientOid" => "1111428059067125760",
            //                     "orderId" => "1111428059067125761"
            //                 }
            //             ),
            //             "failureList" => array()
            //         }
            //     }
            //
            // spot $trigger
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700711728063,
            //         "data" => {
            //             "result" => "success"
            //         }
            //     }
            //
            // $uta $trigger
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => "1753058267399",
            //         "data" => null
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $order = null;
            if ($isContractTriggerEndpoint) {
                $orderInfo = $this->safe_value($data, 'successList', array());
                $order = $orderInfo[0];
            } else {
                if ($uta && $trigger) {
                    $order = $response;
                } else {
                    $order = $data;
                }
            }
            return $this->parse_order($order, $market);
        }) ();
    }

    public function cancel_uta_orders($ids, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($ids, $symbol, $params) {
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelOrders() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $requestList = array();
            for ($i = 0; $i < count($ids); $i++) {
                $individualId = $ids[$i];
                $order = array(
                    'orderId' => $individualId,
                    'symbol' => $market['id'],
                    'category' => $productType,
                );
                $requestList[] = $order;
            }
            $response = Async\await($this->privateUtaPostV3TradeCancelBatch ($requestList));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1752813731517,
            //         "data" => array(
            //             array(
            //                 "orderId" => "1329948909442023424",
            //                 "clientOid" => "1329948909446217728"
            //             ),
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_orders($data, $market);
        }) ();
    }

    public function cancel_orders($ids, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($ids, $symbol, $params) {
            /**
             * cancel multiple $orders
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Batch-Cancel-Orders
             * @see https://www.bitget.com/api-doc/contract/trade/Batch-Cancel-Orders
             * @see https://www.bitget.com/api-doc/contract/plan/Cancel-Plan-Order
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Cross-Batch-Cancel-Order
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Batch-Cancel-Orders
             * @see https://www.bitget.com/api-doc/uta/trade/Cancel-Batch
             *
             * @param {string[]} $ids order $ids
             * @param {string} $symbol unified $market $symbol, default is null
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'isolated' or 'cross' for spot margin trading
             * @param {boolean} [$params->trigger] *contract only* set to true for canceling $trigger $orders
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} an array of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelOrders() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'cancelOrders', 'uta', false);
            if ($uta) {
                return Async\await($this->cancel_uta_orders($ids, $symbol, $params));
            }
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('cancelOrders', $params);
            $trigger = $this->safe_value_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger' ));
            $orderIdList = array();
            for ($i = 0; $i < count($ids); $i++) {
                $individualId = $ids[$i];
                $orderId = array(
                    'orderId' => $individualId,
                );
                $orderIdList[] = $orderId;
            }
            $request = array(
                'symbol' => $market['id'],
            );
            if ($market['spot'] && ($marginMode === null)) {
                $request['orderList'] = $orderIdList;
            } else {
                $request['orderIdList'] = $orderIdList;
            }
            $response = null;
            if ($market['spot']) {
                if ($marginMode !== null) {
                    if ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginPostV2MarginCrossedBatchCancelOrder ($this->extend($request, $params)));
                    } else {
                        $response = Async\await($this->privateMarginPostV2MarginIsolatedBatchCancelOrder ($this->extend($request, $params)));
                    }
                } else {
                    $response = Async\await($this->privateSpotPostV2SpotTradeBatchCancelOrder ($this->extend($request, $params)));
                }
            } else {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                if ($trigger) {
                    $response = Async\await($this->privateMixPostV2MixOrderCancelPlanOrder ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateMixPostV2MixOrderBatchCancelOrders ($this->extend($request, $params)));
                }
            }
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => "1680008815965",
            //         "data" => {
            //             "successList" => array(
            //                 array(
            //                     "orderId" => "1024598257429823488",
            //                     "clientOid" => "876493ce-c287-4bfc-9f4a-8b1905881313"
            //                 ),
            //             ),
            //             "failureList" => array()
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $orders = $this->safe_list($data, 'successList', array());
            return $this->parse_orders($orders, $market);
        }) ();
    }

    public function cancel_all_orders(?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($symbol, $params) {
            /**
             * cancel all open orders
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Cancel-Symbol-Orders
             * @see https://www.bitget.com/api-doc/spot/plan/Batch-Cancel-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Batch-Cancel-Orders
             * @see https://bitgetlimited.github.io/apidoc/en/margin/#isolated-batch-cancel-orders
             * @see https://bitgetlimited.github.io/apidoc/en/margin/#cross-batch-cancel-order
             * @see https://www.bitget.com/api-doc/uta/trade/Cancel-All-Order
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'isolated' or 'cross' for spot margin trading
             * @param {boolean} [$params->trigger] *contract only* set to true for canceling $trigger orders
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelAllOrders() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('cancelAllOrders', $params);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
            );
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger' ));
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'cancelAllOrders', 'uta', false);
            if ($uta) {
                if ($productType === 'SPOT') {
                    if ($marginMode !== null) {
                        $productType = 'MARGIN';
                    }
                }
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaPostV3TradeCancelSymbolOrder ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1750751578138,
                //         "data" => {
                //             "list" => array(
                //                 {
                //                     "orderId" => "1321313242969427968",
                //                     "clientOid" => "1321313242969427969"
                //                 }
                //             )
                //         }
                //     }
                //
            } elseif ($market['spot']) {
                if ($marginMode !== null) {
                    if ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginPostMarginV1CrossOrderBatchCancelOrder ($this->extend($request, $params)));
                    } else {
                        $response = Async\await($this->privateMarginPostMarginV1IsolatedOrderBatchCancelOrder ($this->extend($request, $params)));
                    }
                    //
                    //     {
                    //         "code" => "00000",
                    //         "msg" => "success",
                    //         "requestTime" => 1700717155622,
                    //         "data" => {
                    //             "resultList" => array(
                    //                 array(
                    //                     "orderId" => "1111453253721796609",
                    //                     "clientOid" => "2ae7fc8a4ff949b6b60d770ca3950e2d"
                    //                 ),
                    //             ),
                    //             "failure" => array()
                    //         }
                    //     }
                    //
                } else {
                    if ($trigger) {
                        $stopRequest = array(
                            'symbolList' => [ $market['id'] ],
                        );
                        $response = Async\await($this->privateSpotPostV2SpotTradeBatchCancelPlanOrder ($this->extend($stopRequest, $params)));
                    } else {
                        $response = Async\await($this->privateSpotPostV2SpotTradeCancelSymbolOrder ($this->extend($request, $params)));
                    }
                    //
                    //     {
                    //         "code" => "00000",
                    //         "msg" => "success",
                    //         "requestTime" => 1700716953996,
                    //         "data" => {
                    //             "symbol" => "BTCUSDT"
                    //         }
                    //     }
                    //
                    $timestamp = $this->safe_integer($response, 'requestTime');
                    $responseData = $this->safe_dict($response, 'data');
                    $marketId = $this->safe_string($responseData, 'symbol');
                    return array(
                        $this->safe_order(array(
                            'info' => $response,
                            'symbol' => $this->safe_symbol($marketId, null, null, 'spot'),
                            'timestamp' => $timestamp,
                            'datetime' => $this->iso8601($timestamp),
                        )),
                    );
                }
            } else {
                $request['productType'] = $productType;
                if ($trigger) {
                    $response = Async\await($this->privateMixPostV2MixOrderCancelPlanOrder ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateMixPostV2MixOrderBatchCancelOrders ($this->extend($request, $params)));
                }
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => "1680008815965",
                //         "data" => {
                //             "successList" => array(
                //                 array(
                //                     "orderId" => "1024598257429823488",
                //                     "clientOid" => "876493ce-c287-4bfc-9f4a-8b1905881313"
                //                 ),
                //             ),
                //             "failureList" => array()
                //         }
                //     }
            }
            $data = $this->safe_dict($response, 'data');
            $resultList = $this->safe_list_n($data, array( 'resultList', 'successList', 'list' ));
            $failureList = $this->safe_list_2($data, 'failure', 'failureList');
            $responseList = null;
            if (($resultList !== null) && ($failureList !== null)) {
                $responseList = $this->array_concat($resultList, $failureList);
            } else {
                $responseList = $resultList;
            }
            return $this->parse_orders($responseList);
        }) ();
    }

    public function fetch_order(string $id, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $params) {
            /**
             * fetches information on an order made by the user
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-Order-Info
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Order-Details
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Order-Details
             *
             * @param {string} $id the order $id
             * @param {string} $symbol unified $symbol of the $market the order was made in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {string} [$params->clientOrderId] the $clientOrderId of the order, $id does not need to be provided if $clientOrderId is provided
             * @return {array} An ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchOrder() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                // 'orderId' => $id,
            );
            $clientOrderId = $this->safe_string_2($params, 'clientOrderId', 'clientOid');
            if ($clientOrderId !== null) {
                $params = $this->omit($params, array( 'clientOrderId' ));
                $request['clientOid'] = $clientOrderId;
            } else {
                $request['orderId'] = $id;
            }
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchOrder', 'uta', false);
            if ($uta) {
                $response = Async\await($this->privateUtaGetV3TradeOrderInfo ($this->extend($request, $params)));
            } elseif ($market['spot']) {
                $response = Async\await($this->privateSpotGetV2SpotTradeOrderInfo ($this->extend($request, $params)));
            } elseif ($market['swap'] || $market['future']) {
                $request['symbol'] = $market['id'];
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixOrderDetail ($this->extend($request, $params)));
            } else {
                throw new NotSupported($this->id . ' fetchOrder() does not support ' . $market['type'] . ' orders');
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700719076263,
            //         "data" => array(
            //             {
            //                 "userId" => "7264631750",
            //                 "symbol" => "BTCUSDT",
            //                 "orderId" => "1111461743123927040",
            //                 "clientOid" => "63f95110-93b5-4309-8f77-46339f1bcf3c",
            //                 "price" => "25000.0000000000000000",
            //                 "size" => "0.0002000000000000",
            //                 "orderType" => "limit",
            //                 "side" => "buy",
            //                 "status" => "live",
            //                 "priceAvg" => "0",
            //                 "baseVolume" => "0.0000000000000000",
            //                 "quoteVolume" => "0.0000000000000000",
            //                 "enterPointSource" => "API",
            //                 "feeDetail" => "",
            //                 "orderSource" => "normal",
            //                 "cTime" => "1700719050198",
            //                 "uTime" => "1700719050198"
            //             }
            //         )
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700719918781,
            //         "data" => {
            //             "symbol" => "BTCUSDT",
            //             "size" => "0.001",
            //             "orderId" => "1111465253393825792",
            //             "clientOid" => "1111465253431574529",
            //             "baseVolume" => "0",
            //             "fee" => "0",
            //             "price" => "27000",
            //             "priceAvg" => "",
            //             "state" => "live",
            //             "side" => "buy",
            //             "force" => "gtc",
            //             "totalProfits" => "0",
            //             "posSide" => "long",
            //             "marginCoin" => "USDT",
            //             "presetStopSurplusPrice" => "",
            //             "presetStopLossPrice" => "",
            //             "quoteVolume" => "0",
            //             "orderType" => "limit",
            //             "leverage" => "20",
            //             "marginMode" => "crossed",
            //             "reduceOnly" => "NO",
            //             "enterPointSource" => "API",
            //             "tradeSide" => "open",
            //             "posMode" => "hedge_mode",
            //             "orderSource" => "normal",
            //             "cTime" => "1700719887120",
            //             "uTime" => "1700719887120"
            //         }
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750496858333,
            //         "data" => {
            //             "orderId" => "1320244799629316096",
            //             "clientOid" => "1320244799633510400",
            //             "category" => "USDT-FUTURES",
            //             "symbol" => "BTCUSDT",
            //             "orderType" => "limit",
            //             "side" => "buy",
            //             "price" => "50000",
            //             "qty" => "0.001",
            //             "amount" => "0",
            //             "cumExecQty" => "0",
            //             "cumExecValue" => "0",
            //             "avgPrice" => "0",
            //             "timeInForce" => "gtc",
            //             "orderStatus" => "live",
            //             "posSide" => "long",
            //             "holdMode" => "hedge_mode",
            //             "reduceOnly" => "NO",
            //             "feeDetail" => [array(
            //                 "feeCoin" => "",
            //                 "fee" => ""
            //             )],
            //             "createdTime" => "1750496809871",
            //             "updatedTime" => "1750496809886",
            //             "cancelReason" => "",
            //             "execType" => "normal",
            //             "stpMode" => "none",
            //             "tpTriggerBy" => null,
            //             "slTriggerBy" => null,
            //             "takeProfit" => null,
            //             "stopLoss" => null,
            //             "tpOrderType" => null,
            //             "slOrderType" => null,
            //             "tpLimitPrice" => null,
            //             "slLimitPrice" => null
            //         }
            //     }
            //
            if (!$uta && (gettype($response) === 'string')) {
                $response = json_decode($response, $as_associative_array = true);
            }
            $data = $this->safe_dict($response, 'data');
            if (($data !== null)) {
                if (gettype($data) !== 'array' || array_keys($data) !== array_keys(array_keys($data))) {
                    return $this->parse_order($data, $market);
                }
            }
            $dataList = $this->safe_list($response, 'data', array());
            $dataListLength = count($dataList);
            if ($dataListLength === 0) {
                throw new OrderNotFound($this->id . ' fetchOrder() could not find order $id ' . $id . ' in ' . $this->json($response));
            }
            $first = $this->safe_dict($dataList, 0, array());
            return $this->parse_order($first, $market);
            // $first = $this->safe_dict($data, 0, $data);
            // return $this->parse_order($first, $market);
        }) ();
    }

    public function fetch_open_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch all unfilled currently open orders
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-Unfilled-Orders
             * @see https://www.bitget.com/api-doc/spot/plan/Get-Current-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Orders-Pending
             * @see https://www.bitget.com/api-doc/contract/plan/get-orders-plan-pending
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Open-Orders
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Open-Orders
             * @see https://www.bitget.com/api-doc/uta/strategy/Get-Unfilled-Strategy-Orders
             *
             * @param {string} $symbol unified $market $symbol
             * @param {int} [$since] the earliest time in ms to fetch open orders for
             * @param {int} [$limit] the maximum number of open order structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch orders for
             * @param {string} [$params->planType] *contract stop only* 'normal_plan' => average $trigger order, 'profit_loss' => opened tp/sl orders, 'track_plan' => $trailing stop order, default is 'normal_plan'
             * @param {boolean} [$params->trigger] set to true for fetching $trigger orders
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {string} [$params->isPlan] *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
             * @param {boolean} [$params->trailing] set to true if you want to fetch $trailing orders
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            Async\await($this->load_markets());
            $market = null;
            $type = null;
            $request = array();
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchOpenOrders', $params);
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchOpenOrders', 'uta', false);
            if ($symbol !== null) {
                $market = $this->market($symbol);
                $request['symbol'] = $market['id'];
                $defaultType = $this->safe_string_2($this->options, 'fetchOpenOrders', 'defaultType', 'spot');
                $marketType = (is_array($market) && array_key_exists('type', $market)) ? $market['type'] : $defaultType;
                $type = $this->safe_string($params, 'type', $marketType);
            } else {
                $defaultType = $this->safe_string_2($this->options, 'fetchOpenOrders', 'defaultType', 'spot');
                $type = $this->safe_string($params, 'type', $defaultType);
            }
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchOpenOrders', 'paginate');
            if ($paginate) {
                $cursorReceived = null;
                $cursorSent = null;
                if ($uta) {
                    $cursorReceived = 'cursor';
                    $cursorSent = 'cursor';
                } elseif ($type === 'spot') {
                    if ($marginMode !== null) {
                        $cursorReceived = 'minId';
                        $cursorSent = 'idLessThan';
                    }
                } else {
                    $cursorReceived = 'endId';
                    $cursorSent = 'idLessThan';
                }
                return Async\await($this->fetch_paginated_call_cursor('fetchOpenOrders', $symbol, $since, $limit, $params, $cursorReceived, $cursorSent));
            }
            $response = null;
            $trailing = $this->safe_bool($params, 'trailing');
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $planTypeDefined = $this->safe_string($params, 'planType') !== null;
            $isTrigger = ($trigger || $planTypeDefined);
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            if (!$uta && (($type === 'swap') || ($type === 'future') || ($marginMode !== null))) {
                $clientOrderId = $this->safe_string_2($params, 'clientOid', 'clientOrderId');
                $params = $this->omit($params, 'clientOrderId');
                if ($clientOrderId !== null) {
                    $request['clientOid'] = $clientOrderId;
                }
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $params = $this->omit($params, array( 'type', 'stop', 'trigger', 'trailing' ));
            if ($uta) {
                if ($type === 'spot') {
                    if ($marginMode !== null) {
                        $productType = 'MARGIN';
                    }
                }
                $request['category'] = $productType;
                if ($trigger) {
                    $response = Async\await($this->privateUtaGetV3TradeUnfilledStrategyOrders ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateUtaGetV3TradeUnfilledOrders ($this->extend($request, $params)));
                }
            } elseif ($type === 'spot') {
                if ($marginMode !== null) {
                    if ($since === null) {
                        $since = $this->milliseconds() - 7776000000;
                        $request['startTime'] = $since;
                    }
                    if ($marginMode === 'isolated') {
                        $response = Async\await($this->privateMarginGetV2MarginIsolatedOpenOrders ($this->extend($request, $params)));
                    } elseif ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginGetV2MarginCrossedOpenOrders ($this->extend($request, $params)));
                    }
                } else {
                    if ($trigger) {
                        $response = Async\await($this->privateSpotGetV2SpotTradeCurrentPlanOrder ($this->extend($request, $params)));
                    } else {
                        $response = Async\await($this->privateSpotGetV2SpotTradeUnfilledOrders ($this->extend($request, $params)));
                    }
                }
            } else {
                $request['productType'] = $productType;
                if ($trailing) {
                    $planType = $this->safe_string($params, 'planType', 'track_plan');
                    $request['planType'] = $planType;
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersPlanPending ($this->extend($request, $params)));
                } elseif ($isTrigger) {
                    $planType = $this->safe_string($params, 'planType', 'normal_plan');
                    $request['planType'] = $planType;
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersPlanPending ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersPending ($this->extend($request, $params)));
                }
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700728123994,
            //         "data" => array(
            //             {
            //                 "userId" => "7264631750",
            //                 "symbol" => "BTCUSDT",
            //                 "orderId" => "1111499608327360513",
            //                 "clientOid" => "d0d4dad5-18d0-4869-a074-ec40bb47cba6",
            //                 "priceAvg" => "25000.0000000000000000",
            //                 "size" => "0.0002000000000000",
            //                 "orderType" => "limit",
            //                 "side" => "buy",
            //                 "status" => "live",
            //                 "basePrice" => "0",
            //                 "baseVolume" => "0.0000000000000000",
            //                 "quoteVolume" => "0.0000000000000000",
            //                 "enterPointSource" => "WEB",
            //                 "orderSource" => "normal",
            //                 "cTime" => "1700728077966",
            //                 "uTime" => "1700728077966"
            //             }
            //         )
            //     }
            //
            // spot stop
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700729361609,
            //         "data" => {
            //             "nextFlag" => false,
            //             "idLessThan" => "1111503385931620352",
            //             "orderList" => array(
            //                 {
            //                     "orderId" => "1111503385931620352",
            //                     "clientOid" => "1111503385910648832",
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.0002",
            //                     "planType" => "AMOUNT",
            //                     "executePrice" => "25000",
            //                     "triggerPrice" => "26000",
            //                     "status" => "live",
            //                     "orderType" => "limit",
            //                     "side" => "buy",
            //                     "triggerType" => "fill_price",
            //                     "enterPointSource" => "API",
            //                     "cTime" => "1700728978617",
            //                     "uTime" => "1700728978617"
            //                 }
            //             )
            //         }
            //     }
            //
            // spot margin
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700729887686,
            //         "data" => {
            //             "orderList" => array(
            //                 {
            //                     "symbol" => "BTCUSDT",
            //                     "orderType" => "limit",
            //                     "enterPointSource" => "WEB",
            //                     "orderId" => "1111506377509580801",
            //                     "clientOid" => "2043a3b59a60445f9d9f7365bf3e960c",
            //                     "loanType" => "autoLoanAndRepay",
            //                     "price" => "25000",
            //                     "side" => "buy",
            //                     "status" => "live",
            //                     "baseSize" => "0.0002",
            //                     "quoteSize" => "5",
            //                     "priceAvg" => "0",
            //                     "size" => "0",
            //                     "amount" => "0",
            //                     "force" => "gtc",
            //                     "cTime" => "1700729691866",
            //                     "uTime" => "1700729691866"
            //                 }
            //             ),
            //             "maxId" => "1111506377509580801",
            //             "minId" => "1111506377509580801"
            //         }
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700725609065,
            //         "data" => {
            //             "entrustedList" => array(
            //                 {
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.002",
            //                     "orderId" => "1111488897767604224",
            //                     "clientOid" => "1111488897805352960",
            //                     "baseVolume" => "0",
            //                     "fee" => "0",
            //                     "price" => "25000",
            //                     "priceAvg" => "",
            //                     "status" => "live",
            //                     "side" => "buy",
            //                     "force" => "gtc",
            //                     "totalProfits" => "0",
            //                     "posSide" => "long",
            //                     "marginCoin" => "USDT",
            //                     "quoteVolume" => "0",
            //                     "leverage" => "20",
            //                     "marginMode" => "crossed",
            //                     "enterPointSource" => "web",
            //                     "tradeSide" => "open",
            //                     "posMode" => "hedge_mode",
            //                     "orderType" => "limit",
            //                     "orderSource" => "normal",
            //                     "presetStopSurplusPrice" => "",
            //                     "presetStopLossPrice" => "",
            //                     "reduceOnly" => "NO",
            //                     "cTime" => "1700725524378",
            //                     "uTime" => "1700725524378"
            //                 }
            //             ),
            //             "endId" => "1111488897767604224"
            //         }
            //     }
            //
            // swap and future stop
            //
            //     {
            //         "code" => "00000",\
            //         "msg" => "success",
            //         "requestTime" => 1700726417495,
            //         "data" => {
            //             "entrustedList" => array(
            //                 {
            //                     "planType" => "normal_plan",
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.001",
            //                     "orderId" => "1111491399869075457",
            //                     "clientOid" => "1111491399869075456",
            //                     "price" => "27000",
            //                     "callbackRatio" => "",
            //                     "triggerPrice" => "24000",
            //                     "triggerType" => "mark_price",
            //                     "planStatus" => "live",
            //                     "side" => "buy",
            //                     "posSide" => "long",
            //                     "marginCoin" => "USDT",
            //                     "marginMode" => "crossed",
            //                     "enterPointSource" => "API",
            //                     "tradeSide" => "open",
            //                     "posMode" => "hedge_mode",
            //                     "orderType" => "limit",
            //                     "stopSurplusTriggerPrice" => "",
            //                     "stopSurplusExecutePrice" => "",
            //                     "stopSurplusTriggerType" => "fill_price",
            //                     "stopLossTriggerPrice" => "",
            //                     "stopLossExecutePrice" => "",
            //                     "stopLossTriggerType" => "fill_price",
            //                     "cTime" => "1700726120917",
            //                     "uTime" => "1700726120917"
            //                 }
            //             ),
            //             "endId" => "1111491399869075457"
            //         }
            //     }
            //
            // $uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750753395850,
            //         "data" => {
            //             "list" => array(
            //                 {
            //                     "orderId" => "1321320757371228160",
            //                     "clientOid" => "1321320757371228161",
            //                     "category" => "USDT-FUTURES",
            //                     "symbol" => "BTCUSDT",
            //                     "orderType" => "limit",
            //                     "side" => "buy",
            //                     "price" => "50000",
            //                     "qty" => "0.001",
            //                     "amount" => "0",
            //                     "cumExecQty" => "0",
            //                     "cumExecValue" => "0",
            //                     "avgPrice" => "0",
            //                     "timeInForce" => "gtc",
            //                     "orderStatus" => "live",
            //                     "posSide" => "long",
            //                     "holdMode" => "hedge_mode",
            //                     "reduceOnly" => "NO",
            //                     "feeDetail" => array(
            //                         {
            //                             "feeCoin" => "",
            //                             "fee" => ""
            //                         }
            //                     ),
            //                     "createdTime" => "1750753338186",
            //                     "updatedTime" => "1750753338203",
            //                     "stpMode" => "none",
            //                     "tpTriggerBy" => null,
            //                     "slTriggerBy" => null,
            //                     "takeProfit" => null,
            //                     "stopLoss" => null,
            //                     "tpOrderType" => null,
            //                     "slOrderType" => null,
            //                     "tpLimitPrice" => null,
            //                     "slLimitPrice" => null
            //                 }
            //             ),
            //             "cursor" => "1321320757371228160"
            //         }
            //     }
            //
            // $uta $trigger
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1753057527060,
            //         "data" => array(
            //             {
            //                 "orderId" => "1330984742276198400",
            //                 "clientOid" => "1330984742276198400",
            //                 "symbol" => "BTCUSDT",
            //                 "category" => "USDT-FUTURES",
            //                 "qty" => "0.001",
            //                 "posSide" => "long",
            //                 "tpTriggerBy" => "market",
            //                 "slTriggerBy" => "mark",
            //                 "takeProfit" => "",
            //                 "stopLoss":"114000",
            //                 "tpOrderType" => "market",
            //                 "slOrderType" => "limit",
            //                 "tpLimitPrice" => "",
            //                 "slLimitPrice" => "113000",
            //                 "createdTime" => "1753057411736",
            //                 "updatedTime" => "1753057411747"
            //             }
            //         )
            //     }
            //
            $data = $this->safe_value($response, 'data');
            if ($uta) {
                $result = null;
                if ($trigger) {
                    $result = $this->safe_list($response, 'data', array());
                } else {
                    $result = $this->safe_list($data, 'list', array());
                }
                return $this->parse_orders($result, $market, $since, $limit);
            } elseif ($type === 'spot') {
                if (($marginMode !== null) || $trigger) {
                    $resultList = $this->safe_list($data, 'orderList', array());
                    return $this->parse_orders($resultList, $market, $since, $limit);
                }
            } else {
                $result = $this->safe_list($data, 'entrustedList', array());
                return $this->parse_orders($result, $market, $since, $limit);
            }
            return $this->parse_orders($data, $market, $since, $limit);
        }) ();
    }

    public function fetch_closed_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches information on multiple closed $orders made by the user
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-History-Orders
             * @see https://www.bitget.com/api-doc/spot/plan/Get-History-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Orders-History
             * @see https://www.bitget.com/api-doc/contract/plan/orders-plan-history
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Order-History
             *
             * @param {string} $symbol unified market $symbol of the closed $orders
             * @param {int} [$since] timestamp in ms of the earliest order
             * @param {int} [$limit] the max number of closed $orders to return
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch $orders for
             * @param {string} [$params->planType] *contract stop only* 'normal_plan' => average trigger order, 'profit_loss' => opened tp/sl $orders, 'track_plan' => trailing stop order, default is 'normal_plan'
             * @param {boolean} [$params->trigger] set to true for fetching trigger $orders
             * @param {boolean} [$params->paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {string} [$params->isPlan] *swap only* 'plan' for stop $orders and 'profit_loss' for tp/sl $orders, default is 'plan'
             * @param {boolean} [$params->trailing] set to true if you want to fetch trailing $orders
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            Async\await($this->load_markets());
            $orders = Async\await($this->fetch_canceled_and_closed_orders($symbol, $since, $limit, $params));
            return $this->filter_by($orders, 'status', 'closed');
        }) ();
    }

    public function fetch_canceled_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches information on multiple canceled $orders made by the user
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-History-Orders
             * @see https://www.bitget.com/api-doc/spot/plan/Get-History-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Orders-History
             * @see https://www.bitget.com/api-doc/contract/plan/orders-plan-history
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Order-History
             *
             * @param {string} $symbol unified market $symbol of the canceled $orders
             * @param {int} [$since] timestamp in ms of the earliest order
             * @param {int} [$limit] the max number of canceled $orders to return
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch $orders for
             * @param {string} [$params->planType] *contract stop only* 'normal_plan' => average trigger order, 'profit_loss' => opened tp/sl $orders, 'track_plan' => trailing stop order, default is 'normal_plan'
             * @param {boolean} [$params->trigger] set to true for fetching trigger $orders
             * @param {boolean} [$params->paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {string} [$params->isPlan] *swap only* 'plan' for stop $orders and 'profit_loss' for tp/sl $orders, default is 'plan'
             * @param {boolean} [$params->trailing] set to true if you want to fetch trailing $orders
             * @return {array} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            Async\await($this->load_markets());
            $orders = Async\await($this->fetch_canceled_and_closed_orders($symbol, $since, $limit, $params));
            return $this->filter_by($orders, 'status', 'canceled');
        }) ();
    }

    public function fetch_canceled_and_closed_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-History-Orders
             * @see https://www.bitget.com/api-doc/spot/plan/Get-History-Plan-Order
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Orders-History
             * @see https://www.bitget.com/api-doc/contract/plan/orders-plan-history
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-History
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Order-History
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Order-History
             * @see https://www.bitget.com/api-doc/uta/strategy/Get-History-Strategy-Orders
             *
             * fetches information on multiple canceled and closed $orders made by the user
             * @param {string} $symbol unified $market $symbol of the $market $orders were made in
             * @param {int} [$since] the earliest time in ms to fetch $orders for
             * @param {int} [$limit] the maximum number of order structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch $orders for
             * @param {string} [$params->planType] *contract stop only* 'normal_plan' => average $trigger order, 'profit_loss' => opened tp/sl $orders, 'track_plan' => $trailing stop order, default is 'normal_plan'
             * @param {boolean} [$params->trigger] set to true for fetching $trigger $orders
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {string} [$params->isPlan] *swap only* 'plan' for stop $orders and 'profit_loss' for tp/sl $orders, default is 'plan'
             * @param {boolean} [$params->trailing] set to true if you want to fetch $trailing $orders
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchCanceledAndClosedOrders', 'uta', false);
            if ($uta) {
                return Async\await($this->fetch_uta_canceled_and_closed_orders($symbol, $since, $limit, $params));
            }
            Async\await($this->load_markets());
            $market = null;
            $request = array();
            if ($symbol !== null) {
                $market = $this->market($symbol);
                $request['symbol'] = $market['id'];
            }
            $marketType = null;
            list($marketType, $params) = $this->handle_market_type_and_params('fetchCanceledAndClosedOrders', $market, $params);
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchCanceledAndClosedOrders', $params);
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchCanceledAndClosedOrders', 'paginate');
            if ($paginate) {
                $cursorReceived = null;
                if ($marketType === 'spot') {
                    if ($marginMode !== null) {
                        $cursorReceived = 'minId';
                    }
                } else {
                    $cursorReceived = 'endId';
                }
                return Async\await($this->fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', $symbol, $since, $limit, $params, $cursorReceived, 'idLessThan'));
            }
            $response = null;
            $trailing = $this->safe_bool($params, 'trailing');
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger', 'trailing' ));
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            if (($marketType === 'swap') || ($marketType === 'future') || ($marginMode !== null)) {
                $clientOrderId = $this->safe_string_2($params, 'clientOid', 'clientOrderId');
                $params = $this->omit($params, 'clientOrderId');
                if ($clientOrderId !== null) {
                    $request['clientOid'] = $clientOrderId;
                }
            }
            $now = $this->milliseconds();
            if ($marketType === 'spot') {
                if ($marginMode !== null) {
                    if ($since === null) {
                        $since = $now - 7776000000;
                        $request['startTime'] = $since;
                    }
                    if ($marginMode === 'isolated') {
                        $response = Async\await($this->privateMarginGetV2MarginIsolatedHistoryOrders ($this->extend($request, $params)));
                    } elseif ($marginMode === 'cross') {
                        $response = Async\await($this->privateMarginGetV2MarginCrossedHistoryOrders ($this->extend($request, $params)));
                    }
                } elseif ($trigger) {
                    if ($symbol === null) {
                        throw new ArgumentsRequired($this->id . ' fetchCanceledAndClosedOrders() requires a $symbol argument');
                    }
                    $endTime = $this->safe_integer_n($params, array( 'endTime', 'until' ));
                    $params = $this->omit($params, array( 'until' ));
                    if ($since === null) {
                        $since = $now - 7776000000;
                        $request['startTime'] = $since;
                    }
                    if ($endTime === null) {
                        $request['endTime'] = $now;
                    }
                    $response = Async\await($this->privateSpotGetV2SpotTradeHistoryPlanOrder ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateSpotGetV2SpotTradeHistoryOrders ($this->extend($request, $params)));
                }
            } else {
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                $planTypeDefined = $this->safe_string($params, 'planType') !== null;
                if ($trailing) {
                    $planType = $this->safe_string($params, 'planType', 'track_plan');
                    $request['planType'] = $planType;
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersPlanHistory ($this->extend($request, $params)));
                } elseif ($trigger || $planTypeDefined) {
                    $planType = $this->safe_string($params, 'planType', 'normal_plan');
                    $request['planType'] = $planType;
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersPlanHistory ($this->extend($request, $params)));
                } else {
                    $response = Async\await($this->privateMixGetV2MixOrderOrdersHistory ($this->extend($request, $params)));
                }
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700791085380,
            //         "data" => array(
            //             array(
            //                 "userId" => "7264631750",
            //                 "symbol" => "BTCUSDT",
            //                 "orderId" => "1111499608327360513",
            //                 "clientOid" => "d0d4dad5-18d0-4869-a074-ec40bb47cba6",
            //                 "price" => "25000.0000000000000000",
            //                 "size" => "0.0002000000000000",
            //                 "orderType" => "limit",
            //                 "side" => "buy",
            //                 "status" => "cancelled",
            //                 "priceAvg" => "0",
            //                 "baseVolume" => "0.0000000000000000",
            //                 "quoteVolume" => "0.0000000000000000",
            //                 "enterPointSource" => "WEB",
            //                 "feeDetail" => "",
            //                 "orderSource" => "normal",
            //                 "cTime" => "1700728077966",
            //                 "uTime" => "1700728911471"
            //             ),
            //         )
            //     }
            //
            // spot stop
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700792099146,
            //         "data" => {
            //             "nextFlag" => false,
            //             "idLessThan" => "1098757597417775104",
            //             "orderList" => array(
            //                 array(
            //                     "orderId" => "1111503385931620352",
            //                     "clientOid" => "1111503385910648832",
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.0002",
            //                     "planType" => "AMOUNT",
            //                     "executePrice" => "25000",
            //                     "triggerPrice" => "26000",
            //                     "status" => "cancelled",
            //                     "orderType" => "limit",
            //                     "side" => "buy",
            //                     "triggerType" => "fill_price",
            //                     "enterPointSource" => "API",
            //                     "cTime" => "1700728978617",
            //                     "uTime" => "1700729666868"
            //                 ),
            //             )
            //         }
            //     }
            //
            // spot margin
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700792381435,
            //         "data" => {
            //             "orderList" => array(
            //                 array(
            //                     "symbol" => "BTCUSDT",
            //                     "orderType" => "limit",
            //                     "enterPointSource" => "WEB",
            //                     "orderId" => "1111456274707001345",
            //                     "clientOid" => "41e428dd305a4f668671b7f1ed00dc50",
            //                     "loanType" => "autoLoanAndRepay",
            //                     "price" => "27000",
            //                     "side" => "buy",
            //                     "status" => "cancelled",
            //                     "baseSize" => "0.0002",
            //                     "quoteSize" => "5.4",
            //                     "priceAvg" => "0",
            //                     "size" => "0",
            //                     "amount" => "0",
            //                     "force" => "gtc",
            //                     "cTime" => "1700717746427",
            //                     "uTime" => "1700717780636"
            //                 ),
            //             ),
            //             "maxId" => "1111456274707001345",
            //             "minId" => "1098396464990269440"
            //         }
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700792674673,
            //         "data" => {
            //             "entrustedList" => array(
            //                 array(
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.002",
            //                     "orderId" => "1111498800817143808",
            //                     "clientOid" => "1111498800850698240",
            //                     "baseVolume" => "0",
            //                     "fee" => "0",
            //                     "price" => "25000",
            //                     "priceAvg" => "",
            //                     "status" => "canceled",
            //                     "side" => "buy",
            //                     "force" => "gtc",
            //                     "totalProfits" => "0",
            //                     "posSide" => "long",
            //                     "marginCoin" => "USDT",
            //                     "quoteVolume" => "0",
            //                     "leverage" => "20",
            //                     "marginMode" => "crossed",
            //                     "enterPointSource" => "web",
            //                     "tradeSide" => "open",
            //                     "posMode" => "hedge_mode",
            //                     "orderType" => "limit",
            //                     "orderSource" => "normal",
            //                     "presetStopSurplusPrice" => "",
            //                     "presetStopLossPrice" => "",
            //                     "reduceOnly" => "NO",
            //                     "cTime" => "1700727885449",
            //                     "uTime" => "1700727944563"
            //                 ),
            //             ),
            //             "endId" => "1098397008323575809"
            //         }
            //     }
            //
            // swap and future stop
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700792938359,
            //         "data" => {
            //             "entrustedList" => array(
            //                 array(
            //                     "planType" => "normal_plan",
            //                     "symbol" => "BTCUSDT",
            //                     "size" => "0.001",
            //                     "orderId" => "1111491399869075457",
            //                     "clientOid" => "1111491399869075456",
            //                     "planStatus" => "cancelled",
            //                     "price" => "27000",
            //                     "feeDetail" => null,
            //                     "baseVolume" => "0",
            //                     "callbackRatio" => "",
            //                     "triggerPrice" => "24000",
            //                     "triggerType" => "mark_price",
            //                     "side" => "buy",
            //                     "posSide" => "long",
            //                     "marginCoin" => "USDT",
            //                     "marginMode" => "crossed",
            //                     "enterPointSource" => "API",
            //                     "tradeSide" => "open",
            //                     "posMode" => "hedge_mode",
            //                     "orderType" => "limit",
            //                     "stopSurplusTriggerPrice" => "",
            //                     "stopSurplusExecutePrice" => "",
            //                     "stopSurplusTriggerType" => "fill_price",
            //                     "stopLossTriggerPrice" => "",
            //                     "stopLossExecutePrice" => "",
            //                     "stopLossTriggerType" => "fill_price",
            //                     "cTime" => "1700726120917",
            //                     "uTime" => "1700727879652"
            //                 ),
            //             ),
            //             "endId" => "1098760007867502593"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            if ($marketType === 'spot') {
                if (($marginMode !== null) || $trigger) {
                    return $this->parse_orders($this->safe_value($data, 'orderList', array()), $market, $since, $limit);
                }
            } else {
                return $this->parse_orders($this->safe_value($data, 'entrustedList', array()), $market, $since, $limit);
            }
            if (gettype($response) === 'string') {
                $response = json_decode($response, $as_associative_array = true);
            }
            $orders = $this->safe_list($response, 'data', array());
            return $this->parse_orders($orders, $market, $since, $limit);
        }) ();
    }

    public function fetch_uta_canceled_and_closed_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            Async\await($this->load_markets());
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            if ($productType === 'SPOT') {
                $marginMode = null;
                list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchCanceledAndClosedOrders', $params);
                if ($marginMode !== null) {
                    $productType = 'MARGIN';
                }
            }
            $request = array(
                'category' => $productType,
            );
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchCanceledAndClosedOrders', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', $symbol, $since, $limit, $params, 'cursor', 'cursor'));
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger' ));
            if ($trigger) {
                $response = Async\await($this->privateUtaGetV3TradeHistoryStrategyOrders ($this->extend($request, $params)));
            } else {
                $response = Async\await($this->privateUtaGetV3TradeHistoryOrders ($this->extend($request, $params)));
            }
            //
            // uta
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1752531592855,
            //         "data" => {
            //             "list" => array(
            //                 {
            //                     "orderId" => "1322441400976261120",
            //                     "clientOid" => "1322441400976261121",
            //                     "category" => "USDT-FUTURES",
            //                     "symbol" => "BTCUSDT",
            //                     "orderType" => "market",
            //                     "side" => "sell",
            //                     "price" => "0",
            //                     "qty" => "0.0001",
            //                     "amount" => "0",
            //                     "cumExecQty" => "0.0001",
            //                     "cumExecValue" => "10.7005",
            //                     "avgPrice" => "107005.4",
            //                     "timeInForce" => "gtc",
            //                     "orderStatus" => "filled",
            //                     "posSide" => "long",
            //                     "holdMode" => "hedge_mode",
            //                     "reduceOnly" => "NO",
            //                     "feeDetail" => array(
            //                         array(
            //                             "feeCoin" => "USDT",
            //                             "fee" => "0.00642032"
            //                         }
            //                     ),
            //                     "createdTime" => "1751020520442",
            //                     "updatedTime" => "1751020520457",
            //                     "cancelReason" => "",
            //                     "execType" => "normal",
            //                     "stpMode" => "none",
            //                     "tpTriggerBy" => null,
            //                     "slTriggerBy" => null,
            //                     "takeProfit" => null,
            //                     "stopLoss" => null,
            //                     "tpOrderType" => null,
            //                     "slOrderType" => null,
            //                     "tpLimitPrice" => null,
            //                     "slLimitPrice" => null
            //                 ),
            //             ),
            //             "cursor" => "1322441328637100035"
            //         }
            //     }
            //
            // uta $trigger
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1753058447920,
            //         "data" => {
            //             "list" => array(
            //                 array(
            //                     "orderId" => "1330984742276198400",
            //                     "clientOid" => "1330984742276198400",
            //                     "symbol" => "BTCUSDT",
            //                     "category" => "USDT-FUTURES",
            //                     "qty" => "0.001",
            //                     "posSide" => "long",
            //                     "tpTriggerBy" => "market",
            //                     "slTriggerBy" => "mark",
            //                     "takeProfit" => "",
            //                     "stopLoss" => "112000",
            //                     "tpOrderType" => "market",
            //                     "slOrderType" => "limit",
            //                     "tpLimitPrice" => "",
            //                     "slLimitPrice" => "111000",
            //                     "createdTime" => "1753057411736",
            //                     "updatedTime" => "1753058267412"
            //                 ),
            //             ),
            //             "cursor" => 1330960754317619202
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $orders = $this->safe_list($data, 'list', array());
            return $this->parse_orders($orders, $market, $since, $limit);
        }) ();
    }

    public function fetch_ledger(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch the history of changes, actions done by the user or operations that altered the balance of the user
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Account-Bills
             * @see https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
             *
             * @param {string} [$code] unified $currency $code, default is null
             * @param {int} [$since] timestamp in ms of the earliest ledger entry, default is null
             * @param {int} [$limit] max number of ledger entries to return, default is null
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] end time in ms
             * @param {string} [$params->symbol] *contract only* unified $market $symbol
             * @param {string} [$params->productType] *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=ledger ledger structure~
             */
            Async\await($this->load_markets());
            $symbol = $this->safe_string($params, 'symbol');
            $params = $this->omit($params, 'symbol');
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
            }
            $marketType = null;
            list($marketType, $params) = $this->handle_market_type_and_params('fetchLedger', $market, $params);
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchLedger', 'paginate');
            if ($paginate) {
                $cursorReceived = null;
                if ($marketType !== 'spot') {
                    $cursorReceived = 'endId';
                }
                return Async\await($this->fetch_paginated_call_cursor('fetchLedger', $symbol, $since, $limit, $params, $cursorReceived, 'idLessThan'));
            }
            $currency = null;
            $request = array();
            if ($code !== null) {
                $currency = $this->currency($code);
                $request['coin'] = $currency['id'];
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            if ($marketType === 'spot') {
                $response = Async\await($this->privateSpotGetV2SpotAccountBills ($this->extend($request, $params)));
            } else {
                if ($symbol !== null) {
                    $request['symbol'] = $market['id'];
                }
                $productType = null;
                list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixAccountBill ($this->extend($request, $params)));
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700795836415,
            //         "data" => array(
            //             array(
            //                 "billId" => "1111506298997215233",
            //                 "coin" => "USDT",
            //                 "groupType" => "transfer",
            //                 "businessType" => "transfer_out",
            //                 "size" => "-11.64958799",
            //                 "balance" => "0.00000000",
            //                 "fees" => "0.00000000",
            //                 "cTime" => "1700729673028"
            //             ),
            //         )
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700795977890,
            //         "data" => {
            //             "bills" => array(
            //                 array(
            //                     "billId" => "1111499428100472833",
            //                     "symbol" => "",
            //                     "amount" => "-11.64958799",
            //                     "fee" => "0",
            //                     "feeByCoupon" => "",
            //                     "businessType" => "trans_to_exchange",
            //                     "coin" => "USDT",
            //                     "cTime" => "1700728034996"
            //                 ),
            //             ),
            //             "endId" => "1098396773329305606"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data');
            if (($marketType === 'swap') || ($marketType === 'future')) {
                $bills = $this->safe_value($data, 'bills', array());
                return $this->parse_ledger($bills, $currency, $since, $limit);
            }
            return $this->parse_ledger($data, $currency, $since, $limit);
        }) ();
    }

    public function parse_ledger_entry(array $item, ?array $currency = null): array {
        //
        // spot
        //
        //     {
        //         "billId" => "1111506298997215233",
        //         "coin" => "USDT",
        //         "groupType" => "transfer",
        //         "businessType" => "transfer_out",
        //         "size" => "-11.64958799",
        //         "balance" => "0.00000000",
        //         "fees" => "0.00000000",
        //         "cTime" => "1700729673028"
        //     }
        //
        // swap and future
        //
        //     {
        //         "billId" => "1111499428100472833",
        //         "symbol" => "",
        //         "amount" => "-11.64958799",
        //         "fee" => "0",
        //         "feeByCoupon" => "",
        //         "businessType" => "trans_to_exchange",
        //         "coin" => "USDT",
        //         "cTime" => "1700728034996"
        //     }
        //
        $currencyId = $this->safe_string($item, 'coin');
        $code = $this->safe_currency_code($currencyId, $currency);
        $currency = $this->safe_currency($currencyId, $currency);
        $timestamp = $this->safe_integer($item, 'cTime');
        $after = $this->safe_number($item, 'balance');
        $fee = $this->safe_number_2($item, 'fees', 'fee');
        $amountRaw = $this->safe_string_2($item, 'size', 'amount');
        $amount = $this->parse_number(Precise::string_abs($amountRaw));
        $direction = 'in';
        if (mb_strpos($amountRaw, '-') !== false) {
            $direction = 'out';
        }
        return $this->safe_ledger_entry(array(
            'info' => $item,
            'id' => $this->safe_string($item, 'billId'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'direction' => $direction,
            'account' => null,
            'referenceId' => null,
            'referenceAccount' => null,
            'type' => $this->parse_ledger_type($this->safe_string($item, 'businessType')),
            'currency' => $code,
            'amount' => $amount,
            'before' => null,
            'after' => $after,
            'status' => null,
            'fee' => array(
                'currency' => $code,
                'cost' => $fee,
            ),
        ), $currency);
    }

    public function parse_ledger_type($type) {
        $types = array(
            'trans_to_cross' => 'transfer',
            'trans_from_cross' => 'transfer',
            'trans_to_exchange' => 'transfer',
            'trans_from_exchange' => 'transfer',
            'trans_to_isolated' => 'transfer',
            'trans_from_isolated' => 'transfer',
            'trans_to_contract' => 'transfer',
            'trans_from_contract' => 'transfer',
            'trans_to_otc' => 'transfer',
            'trans_from_otc' => 'transfer',
            'open_long' => 'trade',
            'close_long' => 'trade',
            'open_short' => 'trade',
            'close_short' => 'trade',
            'force_close_long' => 'trade',
            'force_close_short' => 'trade',
            'burst_long_loss_query' => 'trade',
            'burst_short_loss_query' => 'trade',
            'force_buy' => 'trade',
            'force_sell' => 'trade',
            'burst_buy' => 'trade',
            'burst_sell' => 'trade',
            'delivery_long' => 'settlement',
            'delivery_short' => 'settlement',
            'contract_settle_fee' => 'fee',
            'append_margin' => 'transaction',
            'adjust_down_lever_append_margin' => 'transaction',
            'reduce_margin' => 'transaction',
            'auto_append_margin' => 'transaction',
            'cash_gift_issue' => 'cashback',
            'cash_gift_recycle' => 'cashback',
            'bonus_issue' => 'rebate',
            'bonus_recycle' => 'rebate',
            'bonus_expired' => 'rebate',
            'transfer_in' => 'transfer',
            'transfer_out' => 'transfer',
            'deposit' => 'deposit',
            'withdraw' => 'withdrawal',
            'buy' => 'trade',
            'sell' => 'trade',
        );
        return $this->safe_string($types, $type, $type);
    }

    public function fetch_my_trades(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch all trades made by the user
             *
             * @see https://www.bitget.com/api-doc/spot/trade/Get-Fills
             * @see https://www.bitget.com/api-doc/contract/trade/Get-Order-Fills
             * @see https://www.bitget.com/api-doc/margin/cross/trade/Get-Cross-Order-Fills
             * @see https://www.bitget.com/api-doc/margin/isolated/trade/Get-Isolated-Transaction-Details
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Order-Fills
             *
             * @param {string} $symbol unified $market $symbol
             * @param {int} [$since] the earliest time in ms to fetch trades for
             * @param {int} [$limit] the maximum number of trades structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch trades for
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=trade-structure trade structures~
             */
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchMyTrades', 'uta', false);
            if (!$uta && ($symbol === null)) {
                throw new ArgumentsRequired($this->id . ' fetchMyTrades() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array();
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $paginate = false;
            $marginMode = null;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchMyTrades', 'paginate');
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchMyTrades', $params);
            if ($paginate) {
                $cursorReceived = null;
                $cursorSent = null;
                if ($uta) {
                    $cursorReceived = 'cursor';
                    $cursorSent = 'cursor';
                } elseif ($market['spot']) {
                    if ($marginMode !== null) {
                        $cursorReceived = 'minId';
                        $cursorSent = 'idLessThan';
                    }
                } else {
                    $cursorReceived = 'endId';
                    $cursorSent = 'idLessThan';
                }
                return Async\await($this->fetch_paginated_call_cursor('fetchMyTrades', $symbol, $since, $limit, $params, $cursorReceived, $cursorSent));
            }
            $response = null;
            if ($uta) {
                $response = Async\await($this->privateUtaGetV3TradeFills ($this->extend($request, $params)));
            } else {
                $request['symbol'] = $market['id'];
                if ($market['spot']) {
                    if ($marginMode !== null) {
                        if ($since === null) {
                            $request['startTime'] = $this->milliseconds() - 7776000000;
                        }
                        if ($marginMode === 'isolated') {
                            $response = Async\await($this->privateMarginGetV2MarginIsolatedFills ($this->extend($request, $params)));
                        } elseif ($marginMode === 'cross') {
                            $response = Async\await($this->privateMarginGetV2MarginCrossedFills ($this->extend($request, $params)));
                        }
                    } else {
                        $response = Async\await($this->privateSpotGetV2SpotTradeFills ($this->extend($request, $params)));
                    }
                } else {
                    $productType = null;
                    list($productType, $params) = $this->handle_product_type_and_params($market, $params);
                    $request['productType'] = $productType;
                    $response = Async\await($this->privateMixGetV2MixOrderFills ($this->extend($request, $params)));
                }
            }
            //
            // spot
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700802995406,
            //         "data" => array(
            //             {
            //                 "userId" => "7264631751",
            //                 "symbol" => "BTCUSDT",
            //                 "orderId" => "1098394344925597696",
            //                 "tradeId" => "1098394344974925824",
            //                 "orderType" => "market",
            //                 "side" => "sell",
            //                 "priceAvg" => "28467.68",
            //                 "size" => "0.0002",
            //                 "amount" => "5.693536",
            //                 "feeDetail" => array(
            //                     "deduction" => "no",
            //                     "feeCoin" => "USDT",
            //                     "totalDeductionFee" => "",
            //                     "totalFee" => "-0.005693536"
            //                 ),
            //                 "tradeScope" => "taker",
            //                 "cTime" => "1697603539699",
            //                 "uTime" => "1697603539754"
            //             }
            //         )
            //     }
            //
            // spot margin
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700803176399,
            //         "data" => {
            //             "fills" => array(
            //                 array(
            //                     "orderId" => "1099353730455318528",
            //                     "tradeId" => "1099353730627092481",
            //                     "orderType" => "market",
            //                     "side" => "sell",
            //                     "priceAvg" => "29543.7",
            //                     "size" => "0.0001",
            //                     "amount" => "2.95437",
            //                     "tradeScope" => "taker",
            //                     "feeDetail" => array(
            //                         "deduction" => "no",
            //                         "feeCoin" => "USDT",
            //                         "totalDeductionFee" => "0",
            //                         "totalFee" => "-0.00295437"
            //                     ),
            //                     "cTime" => "1697832275063",
            //                     "uTime" => "1697832275150"
            //                 ),
            //             ),
            //             "minId" => "1099353591699161118",
            //             "maxId" => "1099353730627092481"
            //         }
            //     }
            //
            // swap and future
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700803357487,
            //         "data" => {
            //             "fillList" => array(
            //                 {
            //                     "tradeId" => "1111468664328269825",
            //                     "symbol" => "BTCUSDT",
            //                     "orderId" => "1111468664264753162",
            //                     "price" => "37271.4",
            //                     "baseVolume" => "0.001",
            //                     "feeDetail" => array(
            //                         array(
            //                             "deduction" => "no",
            //                             "feeCoin" => "USDT",
            //                             "totalDeductionFee" => null,
            //                             "totalFee" => "-0.02236284"
            //                         }
            //                     ),
            //                     "side" => "buy",
            //                     "quoteVolume" => "37.2714",
            //                     "profit" => "-0.0007",
            //                     "enterPointSource" => "web",
            //                     "tradeSide" => "close",
            //                     "posMode" => "hedge_mode",
            //                     "tradeScope" => "taker",
            //                     "cTime" => "1700720700342"
            //                 ),
            //             ),
            //             "endId" => "1099351587643699201"
            //         }
            //     }
            //
            // $uta
            //
            //      {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1751099666579,
            //         "data" => {
            //             "list" => [
            //                 array(
            //                     "execId" => "1322441401010528257",
            //                     "orderId" => "1322441400976261120",
            //                     "category" => "USDT-FUTURES",
            //                     "symbol" => "BTCUSDT",
            //                     "orderType" => "market",
            //                     "side" => "sell",
            //                     "execPrice" => "107005.4",
            //                     "execQty" => "0.0001",
            //                     "execValue" => "10.7005",
            //                     "tradeScope" => "taker",
            //                     "feeDetail" => [array(
            //                         "feeCoin" => "USDT",
            //                         "fee":"0.00642032"
            //                     )],
            //                     "createdTime" => "1751020520451",
            //                     "updatedTime" => "1751020520458",
            //                     "execPnl" => "0.00017"
            //                 ),
            //             ],
            //             "cursor" => "1322061241878880257"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data');
            if ($uta) {
                $fills = $this->safe_list($data, 'list', array());
                return $this->parse_trades($fills, $market, $since, $limit);
            } elseif (($market['swap'] || ($market['future']))) {
                $fills = $this->safe_list($data, 'fillList', array());
                return $this->parse_trades($fills, $market, $since, $limit);
            } elseif ($marginMode !== null) {
                $fills = $this->safe_list($data, 'fills', array());
                return $this->parse_trades($fills, $market, $since, $limit);
            }
            return $this->parse_trades($data, $market, $since, $limit);
        }) ();
    }

    public function fetch_position(string $symbol, $params = array ()) {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch $data on a single open contract trade position
             *
             * @see https://www.bitget.com/api-doc/contract/position/get-single-position
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Position
             *
             * @param {string} $symbol unified $market $symbol of the $market the position is held in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=position-structure position structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
            );
            $response = null;
            $uta = null;
            $result = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchPosition', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaGetV3PositionCurrentPosition ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1750929905423,
                //         "data" => {
                //             "list" => array(
                //                 {
                //                     "category" => "USDT-FUTURES",
                //                     "symbol" => "BTCUSDT",
                //                     "marginCoin" => "USDT",
                //                     "holdMode" => "hedge_mode",
                //                     "posSide" => "long",
                //                     "marginMode" => "crossed",
                //                     "positionBalance" => "5.435199",
                //                     "available" => "0.001",
                //                     "frozen" => "0",
                //                     "total" => "0.001",
                //                     "leverage" => "20",
                //                     "curRealisedPnl" => "0",
                //                     "avgPrice" => "107410.3",
                //                     "positionStatus" => "normal",
                //                     "unrealisedPnl" => "0.0047",
                //                     "liquidationPrice" => "0",
                //                     "mmr" => "0.004",
                //                     "profitRate" => "0.0008647337475591",
                //                     "markPrice" => "107415.3",
                //                     "breakEvenPrice" => "107539.2",
                //                     "totalFunding" => "0",
                //                     "openFeeTotal" => "-0.06444618",
                //                     "closeFeeTotal" => "0",
                //                     "createdTime" => "1750495670699",
                //                     "updatedTime" => "1750929883465"
                //                 }
                //             )
                //         }
                //     }
                //
                $data = $this->safe_dict($response, 'data', array());
                $result = $this->safe_list($data, 'list', array());
            } else {
                $request['marginCoin'] = $market['settleId'];
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixPositionSinglePosition ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1700807531673,
                //         "data" => array(
                //             {
                //                 "marginCoin" => "USDT",
                //                 "symbol" => "BTCUSDT",
                //                 "holdSide" => "long",
                //                 "openDelegateSize" => "0",
                //                 "marginSize" => "3.73555",
                //                 "available" => "0.002",
                //                 "locked" => "0",
                //                 "total" => "0.002",
                //                 "leverage" => "20",
                //                 "achievedProfits" => "0",
                //                 "openPriceAvg" => "37355.5",
                //                 "marginMode" => "crossed",
                //                 "posMode" => "hedge_mode",
                //                 "unrealizedPL" => "0.007",
                //                 "liquidationPrice" => "31724.970702417",
                //                 "keepMarginRate" => "0.004",
                //                 "markPrice" => "37359",
                //                 "marginRatio" => "0.029599540355",
                //                 "cTime" => "1700807507275"
                //             }
                //         )
                //     }
                //
                $result = $this->safe_list($response, 'data', array());
            }
            $first = $this->safe_dict($result, 0, array());
            return $this->parse_position($first, $market);
        }) ();
    }

    public function fetch_positions(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetch all open positions
             *
             * @see https://www.bitget.com/api-doc/contract/position/get-all-$position
             * @see https://www.bitget.com/api-doc/contract/position/Get-History-Position
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Position
             *
             * @param {string[]} [$symbols] list of unified $market $symbols
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginCoin] the settle currency of the positions, needs to match the $productType
             * @param {string} [$params->productType] 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {boolean} [$params->useHistoryEndpoint] default false, when true  will use the historic endpoint to fetch positions
             * @param {string} [$params->method] either (default) 'privateMixGetV2MixPositionAllPosition', 'privateMixGetV2MixPositionHistoryPosition', or 'privateUtaGetV3PositionCurrentPosition'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=$position-structure $position structure~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchPositions', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchPositions', null, null, null, $params, 'endId', 'idLessThan'));
            }
            $method = null;
            $useHistoryEndpoint = $this->safe_bool($params, 'useHistoryEndpoint', false);
            if ($useHistoryEndpoint) {
                $method = 'privateMixGetV2MixPositionHistoryPosition';
            } else {
                list($method, $params) = $this->handle_option_and_params($params, 'fetchPositions', 'method', 'privateMixGetV2MixPositionAllPosition');
            }
            $market = null;
            if ($symbols !== null) {
                $first = $this->safe_string($symbols, 0);
                $market = $this->market($first);
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array();
            $response = null;
            $isHistory = false;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchPositions', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaGetV3PositionCurrentPosition ($this->extend($request, $params)));
            } elseif ($method === 'privateMixGetV2MixPositionAllPosition') {
                $marginCoin = $this->safe_string($params, 'marginCoin', 'USDT');
                if ($symbols !== null) {
                    $marginCoin = $market['settleId'];
                } elseif ($productType === 'USDT-FUTURES') {
                    $marginCoin = 'USDT';
                } elseif ($productType === 'USDC-FUTURES') {
                    $marginCoin = 'USDC';
                } elseif ($productType === 'SUSDT-FUTURES') {
                    $marginCoin = 'SUSDT';
                } elseif ($productType === 'SUSDC-FUTURES') {
                    $marginCoin = 'SUSDC';
                } elseif (($productType === 'SCOIN-FUTURES') || ($productType === 'COIN-FUTURES')) {
                    if ($marginCoin === null) {
                        throw new ArgumentsRequired($this->id . ' fetchPositions() requires a $marginCoin parameter that matches the productType');
                    }
                }
                $request['marginCoin'] = $marginCoin;
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixPositionAllPosition ($this->extend($request, $params)));
            } else {
                $isHistory = true;
                if ($market !== null) {
                    $request['symbol'] = $market['id'];
                }
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixGetV2MixPositionHistoryPosition ($this->extend($request, $params)));
            }
            //
            // privateMixGetV2MixPositionAllPosition
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700807810221,
            //         "data" => array(
            //             {
            //                 "marginCoin" => "USDT",
            //                 "symbol" => "BTCUSDT",
            //                 "holdSide" => "long",
            //                 "openDelegateSize" => "0",
            //                 "marginSize" => "3.73555",
            //                 "available" => "0.002",
            //                 "locked" => "0",
            //                 "total" => "0.002",
            //                 "leverage" => "20",
            //                 "achievedProfits" => "0",
            //                 "openPriceAvg" => "37355.5",
            //                 "marginMode" => "crossed",
            //                 "posMode" => "hedge_mode",
            //                 "unrealizedPL" => "0.03",
            //                 "liquidationPrice" => "31725.023602417",
            //                 "keepMarginRate" => "0.004",
            //                 "markPrice" => "37370.5",
            //                 "marginRatio" => "0.029550120396",
            //                 "cTime" => "1700807507275"
            //             }
            //         )
            //     }
            //
            // privateMixGetV2MixPositionHistoryPosition
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700808051002,
            //         "data" => {
            //             "list" => array(
            //                 array(
            //                     "symbol" => "BTCUSDT",
            //                     "marginCoin" => "USDT",
            //                     "holdSide" => "long",
            //                     "openAvgPrice" => "37272.1",
            //                     "closeAvgPrice" => "37271.4",
            //                     "marginMode" => "crossed",
            //                     "openTotalPos" => "0.001",
            //                     "closeTotalPos" => "0.001",
            //                     "pnl" => "-0.0007",
            //                     "netProfit" => "-0.0454261",
            //                     "totalFunding" => "0",
            //                     "openFee" => "-0.02236326",
            //                     "closeFee" => "-0.02236284",
            //                     "utime" => "1700720700400",
            //                     "ctime" => "1700720651684"
            //                 ),
            //             ),
            //             "endId" => "1099351653866962944"
            //         }
            //     }
            //
            // privateUtaGetV3PositionCurrentPosition
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1750929905423,
            //         "data" => {
            //             "list" => array(
            //                 {
            //                     "category" => "USDT-FUTURES",
            //                     "symbol" => "BTCUSDT",
            //                     "marginCoin" => "USDT",
            //                     "holdMode" => "hedge_mode",
            //                     "posSide" => "long",
            //                     "marginMode" => "crossed",
            //                     "positionBalance" => "5.435199",
            //                     "available" => "0.001",
            //                     "frozen" => "0",
            //                     "total" => "0.001",
            //                     "leverage" => "20",
            //                     "curRealisedPnl" => "0",
            //                     "avgPrice" => "107410.3",
            //                     "positionStatus" => "normal",
            //                     "unrealisedPnl" => "0.0047",
            //                     "liquidationPrice" => "0",
            //                     "mmr" => "0.004",
            //                     "profitRate" => "0.0008647337475591",
            //                     "markPrice" => "107415.3",
            //                     "breakEvenPrice" => "107539.2",
            //                     "totalFunding" => "0",
            //                     "openFeeTotal" => "-0.06444618",
            //                     "closeFeeTotal" => "0",
            //                     "createdTime" => "1750495670699",
            //                     "updatedTime" => "1750929883465"
            //                 }
            //             )
            //         }
            //     }
            //
            $position = array();
            if ($uta || $isHistory) {
                $data = $this->safe_dict($response, 'data', array());
                $position = $this->safe_list($data, 'list', array());
            } else {
                $position = $this->safe_list($response, 'data', array());
            }
            $result = array();
            for ($i = 0; $i < count($position); $i++) {
                $result[] = $this->parse_position($position[$i], $market);
            }
            $symbols = $this->market_symbols($symbols);
            return $this->filter_by_array_positions($result, 'symbol', $symbols, false);
        }) ();
    }

    public function parse_position(array $position, ?array $market = null) {
        //
        // fetchPosition
        //
        //     {
        //         "marginCoin" => "USDT",
        //         "symbol" => "BTCUSDT",
        //         "holdSide" => "long",
        //         "openDelegateSize" => "0",
        //         "marginSize" => "3.73555",
        //         "available" => "0.002",
        //         "locked" => "0",
        //         "total" => "0.002",
        //         "leverage" => "20",
        //         "achievedProfits" => "0",
        //         "openPriceAvg" => "37355.5",
        //         "marginMode" => "crossed",
        //         "posMode" => "hedge_mode",
        //         "unrealizedPL" => "0.007",
        //         "liquidationPrice" => "31724.970702417",
        //         "keepMarginRate" => "0.004",
        //         "markPrice" => "37359",
        //         "marginRatio" => "0.029599540355",
        //         "cTime" => "1700807507275"
        //     }
        //
        // uta => fetchPosition
        //
        //     {
        //         "category" => "USDT-FUTURES",
        //         "symbol" => "BTCUSDT",
        //         "marginCoin" => "USDT",
        //         "holdMode" => "hedge_mode",
        //         "posSide" => "long",
        //         "marginMode" => "crossed",
        //         "positionBalance" => "5.435199",
        //         "available" => "0.001",
        //         "frozen" => "0",
        //         "total" => "0.001",
        //         "leverage" => "20",
        //         "curRealisedPnl" => "0",
        //         "avgPrice" => "107410.3",
        //         "positionStatus" => "normal",
        //         "unrealisedPnl" => "0.0047",
        //         "liquidationPrice" => "0",
        //         "mmr" => "0.004",
        //         "profitRate" => "0.0008647337475591",
        //         "markPrice" => "107415.3",
        //         "breakEvenPrice" => "107539.2",
        //         "totalFunding" => "0",
        //         "openFeeTotal" => "-0.06444618",
        //         "closeFeeTotal" => "0",
        //         "createdTime" => "1750495670699",
        //         "updatedTime" => "1750929883465"
        //     }
        //
        // fetchPositions => privateMixGetV2MixPositionAllPosition
        //
        //     {
        //         "marginCoin" => "USDT",
        //         "symbol" => "BTCUSDT",
        //         "holdSide" => "long",
        //         "openDelegateSize" => "0",
        //         "marginSize" => "3.73555",
        //         "available" => "0.002",
        //         "locked" => "0",
        //         "total" => "0.002",
        //         "leverage" => "20",
        //         "achievedProfits" => "0",
        //         "openPriceAvg" => "37355.5",
        //         "marginMode" => "crossed",
        //         "posMode" => "hedge_mode",
        //         "unrealizedPL" => "0.03",
        //         "liquidationPrice" => "31725.023602417",
        //         "keepMarginRate" => "0.004",
        //         "markPrice" => "37370.5",
        //         "marginRatio" => "0.029550120396",
        //         "cTime" => "1700807507275"
        //     }
        //
        // fetchPositionsHistory => privateMixGetV2MixPositionHistoryPosition
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "marginCoin" => "USDT",
        //         "holdSide" => "long",
        //         "openAvgPrice" => "37272.1",
        //         "closeAvgPrice" => "37271.4",
        //         "marginMode" => "crossed",
        //         "openTotalPos" => "0.001",
        //         "closeTotalPos" => "0.001",
        //         "pnl" => "-0.0007",
        //         "netProfit" => "-0.0454261",
        //         "totalFunding" => "0",
        //         "openFee" => "-0.02236326",
        //         "closeFee" => "-0.02236284",
        //         "utime" => "1700720700400",
        //         "ctime" => "1700720651684"
        //     }
        //
        // closeAllPositions
        //
        //     {
        //         "orderId" => "1120923953904893955",
        //         "clientOid" => "1120923953904893956"
        //     }
        //
        // uta => fetchPositionsHistory
        //
        //     {
        //         "positionId" => "1322441328637100049",
        //         "category" => "USDT-FUTURES",
        //         "symbol" => "BTCUSDT",
        //         "marginCoin" => "USDT",
        //         "holdMode" => "hedge_mode",
        //         "posSide" => "long",
        //         "marginMode" => "crossed",
        //         "openPriceAvg" => "107003.7",
        //         "closePriceAvg" => "107005.4",
        //         "openTotalPos" => "0.0001",
        //         "closeTotalPos" => "0.0001",
        //         "cumRealisedPnl" => "0.00017",
        //         "netProfit" => "-0.01267055",
        //         "totalFunding" => "0",
        //         "openFeeTotal" => "-0.00642022",
        //         "closeFeeTotal" => "-0.00642032",
        //         "createdTime" => "1751020503195",
        //         "updatedTime" => "1751020520458"
        //     }
        //
        $marketId = $this->safe_string($position, 'symbol');
        $market = $this->safe_market($marketId, $market, null, 'contract');
        $symbol = $market['symbol'];
        $timestamp = $this->safe_integer_n($position, array( 'cTime', 'ctime', 'createdTime' ));
        $marginMode = $this->safe_string($position, 'marginMode');
        $collateral = null;
        $initialMargin = null;
        $unrealizedPnl = $this->safe_string_2($position, 'unrealizedPL', 'unrealisedPnl');
        $rawCollateral = $this->safe_string_2($position, 'marginSize', 'positionBalance');
        if ($marginMode === 'isolated') {
            $collateral = Precise::string_add($rawCollateral, $unrealizedPnl);
        } elseif ($marginMode === 'crossed') {
            $marginMode = 'cross';
            $initialMargin = $rawCollateral;
        }
        $holdMode = $this->safe_string_2($position, 'posMode', 'holdMode');
        $hedged = null;
        if ($holdMode === 'hedge_mode') {
            $hedged = true;
        } elseif ($holdMode === 'one_way_mode') {
            $hedged = false;
        }
        $side = $this->safe_string_2($position, 'holdSide', 'posSide');
        $leverage = $this->safe_string($position, 'leverage');
        $contractSizeNumber = $this->safe_value($market, 'contractSize');
        $contractSize = $this->number_to_string($contractSizeNumber);
        $baseAmount = $this->safe_string_2($position, 'total', 'openTotalPos');
        $entryPrice = $this->safe_string_n($position, array( 'openPriceAvg', 'openAvgPrice', 'avgPrice' ));
        $maintenanceMarginPercentage = $this->safe_string($position, 'keepMarginRate');
        $openNotional = Precise::string_mul($entryPrice, $baseAmount);
        if ($initialMargin === null) {
            $initialMargin = Precise::string_div($openNotional, $leverage);
        }
        $contracts = $this->parse_number(Precise::string_div($baseAmount, $contractSize));
        if ($contracts === null) {
            $contracts = $this->safe_number($position, 'closeTotalPos');
        }
        $markPrice = $this->safe_string($position, 'markPrice');
        $notional = Precise::string_mul($baseAmount, $markPrice);
        $initialMarginPercentage = Precise::string_div($initialMargin, $notional);
        $liquidationPrice = $this->parse_number($this->omit_zero($this->safe_string($position, 'liquidationPrice')));
        $calcTakerFeeRate = '0.0006';
        $calcTakerFeeMult = '0.9994';
        if (($liquidationPrice === null) && ($marginMode === 'isolated') && Precise::string_gt($baseAmount, '0')) {
            $signedMargin = Precise::string_div($rawCollateral, $baseAmount);
            $signedMmp = $maintenanceMarginPercentage;
            if ($side === 'short') {
                $signedMargin = Precise::string_neg($signedMargin);
                $signedMmp = Precise::string_neg($signedMmp);
            }
            $mmrMinusOne = Precise::string_sub('1', $signedMmp);
            $numerator = Precise::string_sub($entryPrice, $signedMargin);
            if ($side === 'long') {
                $mmrMinusOne = Precise::string_mul($mmrMinusOne, $calcTakerFeeMult);
            } else {
                $numerator = Precise::string_mul($numerator, $calcTakerFeeMult);
            }
            $liquidationPrice = $this->parse_number(Precise::string_div($numerator, $mmrMinusOne));
        }
        $feeToClose = Precise::string_mul($notional, $calcTakerFeeRate);
        $maintenanceMargin = Precise::string_add(Precise::string_mul($maintenanceMarginPercentage, $notional), $feeToClose);
        $percentage = Precise::string_mul(Precise::string_div($unrealizedPnl, $initialMargin, 4), '100');
        return $this->safe_position(array(
            'info' => $position,
            'id' => $this->safe_string_2($position, 'orderId', 'positionId'),
            'symbol' => $symbol,
            'notional' => $this->parse_number($notional),
            'marginMode' => $marginMode,
            'liquidationPrice' => $liquidationPrice,
            'entryPrice' => $this->parse_number($entryPrice),
            'unrealizedPnl' => $this->parse_number($unrealizedPnl),
            'realizedPnl' => $this->safe_number_n($position, array( 'pnl', 'curRealisedPnl', 'cumRealisedPnl' )),
            'percentage' => $this->parse_number($percentage),
            'contracts' => $contracts,
            'contractSize' => $contractSizeNumber,
            'markPrice' => $this->parse_number($markPrice),
            'lastPrice' => $this->safe_number_2($position, 'closeAvgPrice', 'closePriceAvg'),
            'side' => $side,
            'hedged' => $hedged,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'lastUpdateTimestamp' => $this->safe_integer_2($position, 'utime', 'updatedTime'),
            'maintenanceMargin' => $this->parse_number($maintenanceMargin),
            'maintenanceMarginPercentage' => $this->parse_number($maintenanceMarginPercentage),
            'collateral' => $this->parse_number($collateral),
            'initialMargin' => $this->parse_number($initialMargin),
            'initialMarginPercentage' => $this->parse_number($initialMarginPercentage),
            'leverage' => $this->parse_number($leverage),
            'marginRatio' => $this->safe_number_2($position, 'marginRatio', 'mmr'),
            'stopLossPrice' => null,
            'takeProfitPrice' => null,
        ));
    }

    public function fetch_funding_rate_history(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches historical funding rate prices
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-History-Funding-Rate
             * @see https://www.bitget.com/api-doc/uta/public/Get-History-Funding-Rate
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the funding rate history for
             * @param {int} [$since] $timestamp in ms of the earliest funding rate to fetch
             * @param {int} [$limit] the maximum amount of funding rate structures to fetch
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=funding-rate-history-structure funding rate structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchFundingRateHistory() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $productType = null;
            $uta = null;
            $response = null;
            $result = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchFundingRateHistory', 'uta', false);
            if ($uta) {
                if ($limit !== null) {
                    $request['limit'] = $limit;
                }
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketHistoryFundRate ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1750435113658,
                //         "data" => {
                //             "resultList" => array(
                //                 array(
                //                     "symbol" => "BTCUSDT",
                //                     "fundingRate" => "-0.000017",
                //                     "fundingRateTimestamp" => "1750431600000"
                //                 ),
                //             )
                //         }
                //     }
                //
                $data = $this->safe_dict($response, 'data', array());
                $result = $this->safe_list($data, 'resultList', array());
            } else {
                $paginate = false;
                list($paginate, $params) = $this->handle_option_and_params($params, 'fetchFundingRateHistory', 'paginate');
                if ($paginate) {
                    return Async\await($this->fetch_paginated_call_incremental('fetchFundingRateHistory', $symbol, $since, $limit, $params, 'pageNo', 100));
                }
                if ($limit !== null) {
                    $request['pageSize'] = $limit;
                }
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketHistoryFundRate ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1652406728393,
                //         "data" => array(
                //             array(
                //                 "symbol" => "BTCUSDT",
                //                 "fundingRate" => "-0.0003",
                //                 "fundingTime" => "1652396400000"
                //             ),
                //         )
                //     }
                //
                $result = $this->safe_list($response, 'data', array());
            }
            $rates = array();
            for ($i = 0; $i < count($result); $i++) {
                $entry = $result[$i];
                $marketId = $this->safe_string($entry, 'symbol');
                $symbolInner = $this->safe_symbol($marketId, $market);
                $timestamp = $this->safe_integer_2($entry, 'fundingTime', 'fundingRateTimestamp');
                $rates[] = array(
                    'info' => $entry,
                    'symbol' => $symbolInner,
                    'fundingRate' => $this->safe_number($entry, 'fundingRate'),
                    'timestamp' => $timestamp,
                    'datetime' => $this->iso8601($timestamp),
                );
            }
            $sorted = $this->sort_by($rates, 'timestamp');
            return $this->filter_by_symbol_since_limit($sorted, $market['symbol'], $since, $limit);
        }) ();
    }

    public function fetch_funding_rate(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the current funding rate
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-Current-Funding-Rate
             * @see https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
             * @see https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {string} [$params->method] either (default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=funding-rate-structure funding rate structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['swap']) {
                throw new BadSymbol($this->id . ' fetchFundingRate() supports swap contracts only');
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
            );
            $uta = null;
            $response = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchFundingRate', 'uta', false);
            if ($uta) {
                $response = Async\await($this->publicUtaGetV3MarketCurrentFundRate ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1750897372153,
                //         "data" => array(
                //             {
                //                 "symbol" => "BTCUSDT",
                //                 "fundingRate" => "0.00001",
                //                 "fundingRateInterval" => "8",
                //                 "nextUpdate" => "1750924800000",
                //                 "minFundingRate" => "-0.003",
                //                 "maxFundingRate" => "0.003"
                //             }
                //         )
                //     }
                //
            } else {
                $request['productType'] = $productType;
                $method = null;
                list($method, $params) = $this->handle_option_and_params($params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate');
                if ($method === 'publicMixGetV2MixMarketCurrentFundRate') {
                    $response = Async\await($this->publicMixGetV2MixMarketCurrentFundRate ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => "00000",
                    //         "msg" => "success",
                    //         "requestTime" => 1745500709429,
                    //         "data" => array(
                    //             {
                    //                 "symbol" => "BTCUSDT",
                    //                 "fundingRate" => "-0.000013",
                    //                 "fundingRateInterval" => "8",
                    //                 "nextUpdate" => "1745510400000",
                    //                 "minFundingRate" => "-0.003",
                    //                 "maxFundingRate" => "0.003"
                    //             }
                    //         )
                    //     }
                    //
                } elseif ($method === 'publicMixGetV2MixMarketFundingTime') {
                    $response = Async\await($this->publicMixGetV2MixMarketFundingTime ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => "00000",
                    //         "msg" => "success",
                    //         "requestTime" => 1745402092428,
                    //         "data" => array(
                    //             {
                    //                 "symbol" => "BTCUSDT",
                    //                 "nextFundingTime" => "1745424000000",
                    //                 "ratePeriod" => "8"
                    //             }
                    //         )
                    //     }
                    //
                }
            }
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_funding_rate($data[0], $market);
        }) ();
    }

    public function fetch_funding_rates(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetch the current funding rates for all markets
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-All-Symbol-Ticker
             *
             * @param {string[]} [$symbols] list of unified $market $symbols
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->subType] *contract only* 'linear', 'inverse'
             * @param {string} [$params->productType] *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=funding-rates-structure funding rate structures~, indexed by $market $symbols
             */
            Async\await($this->load_markets());
            $market = null;
            if ($symbols !== null) {
                $symbol = $this->safe_value($symbols, 0);
                $market = $this->market($symbol);
            }
            $request = array();
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request['productType'] = $productType;
            $response = Async\await($this->publicMixGetV2MixMarketTickers ($this->extend($request, $params)));
            // {
            //     "code" => "00000",
            //     "msg" => "success",
            //     "requestTime" => 1700533773477,
            //     "data" => array(
            //         array(
            //             "symbol" => "BTCUSD",
            //             "lastPr" => "29904.5",
            //             "askPr" => "29904.5",
            //             "bidPr" => "29903.5",
            //             "bidSz" => "0.5091",
            //             "askSz" => "2.2694",
            //             "high24h" => "0",
            //             "low24h" => "0",
            //             "ts" => "1695794271400",
            //             "change24h" => "0",
            //             "baseVolume" => "0",
            //             "quoteVolume" => "0",
            //             "usdtVolume" => "0",
            //             "openUtc" => "0",
            //             "changeUtc24h" => "0",
            //             "indexPrice" => "29132.353333",
            //             "fundingRate" => "-0.0007",
            //             "holdingAmount" => "125.6844",
            //             "deliveryStartTime" => null,
            //             "deliveryTime" => null,
            //             "deliveryStatus" => "delivery_normal",
            //             "open24h" => "0",
            //             "markPrice" => "12345"
            //         ),
            //     )
            // }
            $symbols = $this->market_symbols($symbols);
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_funding_rates($data, $symbols);
        }) ();
    }

    public function parse_funding_rate($contract, ?array $market = null): array {
        //
        // fetchFundingRate => publicMixGetV2MixMarketCurrentFundRate, publicUtaGetV3MarketCurrentFundRate
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "fundingRate" => "-0.000013",
        //         "fundingRateInterval" => "8",
        //         "nextUpdate" => "1745510400000",
        //         "minFundingRate" => "-0.003",
        //         "maxFundingRate" => "0.003"
        //     }
        //
        // fetchFundingRate => publicMixGetV2MixMarketFundingTime
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "nextFundingTime" => "1745424000000",
        //         "ratePeriod" => "8"
        //     }
        //
        // fetchFundingInterval
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "nextFundingTime" => "1727942400000",
        //         "ratePeriod" => "8"
        //     }
        //
        // fetchFundingRates
        //
        //     {
        //         "symbol" => "BTCUSD",
        //         "lastPr" => "29904.5",
        //         "askPr" => "29904.5",
        //         "bidPr" => "29903.5",
        //         "bidSz" => "0.5091",
        //         "askSz" => "2.2694",
        //         "high24h" => "0",
        //         "low24h" => "0",
        //         "ts" => "1695794271400",
        //         "change24h" => "0",
        //         "baseVolume" => "0",
        //         "quoteVolume" => "0",
        //         "usdtVolume" => "0",
        //         "openUtc" => "0",
        //         "changeUtc24h" => "0",
        //         "indexPrice" => "29132.353333",
        //         "fundingRate" => "-0.0007",
        //         "holdingAmount" => "125.6844",
        //         "deliveryStartTime" => null,
        //         "deliveryTime" => null,
        //         "deliveryStatus" => "delivery_normal",
        //         "open24h" => "0",
        //         "markPrice" => "12345"
        //     }
        //
        $marketId = $this->safe_string($contract, 'symbol');
        $symbol = $this->safe_symbol($marketId, $market, null, 'swap');
        $fundingTimestamp = $this->safe_integer_2($contract, 'nextFundingTime', 'nextUpdate');
        $interval = $this->safe_string_2($contract, 'ratePeriod', 'fundingRateInterval');
        $timestamp = $this->safe_integer($contract, 'ts');
        $markPrice = $this->safe_number($contract, 'markPrice');
        $indexPrice = $this->safe_number($contract, 'indexPrice');
        $intervalString = null;
        if ($interval !== null) {
            $intervalString = $interval . 'h';
        }
        return array(
            'info' => $contract,
            'symbol' => $symbol,
            'markPrice' => $markPrice,
            'indexPrice' => $indexPrice,
            'interestRate' => null,
            'estimatedSettlePrice' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'fundingRate' => $this->safe_number($contract, 'fundingRate'),
            'fundingTimestamp' => $fundingTimestamp,
            'fundingDatetime' => $this->iso8601($fundingTimestamp),
            'nextFundingRate' => null,
            'nextFundingTimestamp' => null,
            'nextFundingDatetime' => null,
            'previousFundingRate' => null,
            'previousFundingTimestamp' => null,
            'previousFundingDatetime' => null,
            'interval' => $intervalString,
        );
    }

    public function fetch_funding_history(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch the funding history
             *
             * @see https://www.bitget.com/api-doc/contract/account/Get-Account-Bill
             *
             * @param {string} $symbol unified $market $symbol
             * @param {int} [$since] the starting timestamp in milliseconds
             * @param {int} [$limit] the number of entries to return
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch funding history for
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=funding-history-structure funding history structures~
             */
            Async\await($this->load_markets());
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchFundingHistory() requires a $symbol argument');
            }
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchFundingHistory', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchFundingHistory', $symbol, $since, $limit, $params, 'endId', 'idLessThan'));
            }
            $market = $this->market($symbol);
            if (!$market['swap']) {
                throw new BadSymbol($this->id . ' fetchFundingHistory() supports swap contracts only');
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'marginCoin' => $market['settleId'],
                'businessType' => 'contract_settle_fee',
                'productType' => $productType,
            );
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->privateMixGetV2MixAccountBill ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700795977890,
            //         "data" => {
            //             "bills" => array(
            //                 array(
            //                     "billId" => "1111499428100472833",
            //                     "symbol" => "BTCUSDT",
            //                     "amount" => "-0.004992",
            //                     "fee" => "0",
            //                     "feeByCoupon" => "",
            //                     "businessType" => "contract_settle_fee",
            //                     "coin" => "USDT",
            //                     "cTime" => "1700728034996"
            //                 ),
            //             ),
            //             "endId" => "1098396773329305606"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $result = $this->safe_value($data, 'bills', array());
            return $this->parse_funding_histories($result, $market, $since, $limit);
        }) ();
    }

    public function parse_funding_history($contract, ?array $market = null) {
        //
        //     {
        //         "billId" => "1111499428100472833",
        //         "symbol" => "BTCUSDT",
        //         "amount" => "-0.004992",
        //         "fee" => "0",
        //         "feeByCoupon" => "",
        //         "businessType" => "contract_settle_fee",
        //         "coin" => "USDT",
        //         "cTime" => "1700728034996"
        //     }
        //
        $marketId = $this->safe_string($contract, 'symbol');
        $currencyId = $this->safe_string($contract, 'coin');
        $timestamp = $this->safe_integer($contract, 'cTime');
        return array(
            'info' => $contract,
            'symbol' => $this->safe_symbol($marketId, $market, null, 'swap'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'code' => $this->safe_currency_code($currencyId),
            'amount' => $this->safe_number($contract, 'amount'),
            'id' => $this->safe_string($contract, 'billId'),
        );
    }

    public function parse_funding_histories($contracts, $market = null, ?int $since = null, ?int $limit = null): array {
        $result = array();
        for ($i = 0; $i < count($contracts); $i++) {
            $contract = $contracts[$i];
            $business = $this->safe_string($contract, 'businessType');
            if ($business !== 'contract_settle_fee') {
                continue;
            }
            $result[] = $this->parse_funding_history($contract, $market);
        }
        $sorted = $this->sort_by($result, 'timestamp');
        $symbol = null;
        if ($market !== null) {
            $symbol = $market['symbol'];
        }
        return $this->filter_by_symbol_since_limit($sorted, $symbol, $since, $limit);
    }

    public function modify_margin_helper(string $symbol, $amount, $type, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $amount, $type, $params) {
            Async\await($this->load_markets());
            $holdSide = $this->safe_string($params, 'holdSide');
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'marginCoin' => $market['settleId'],
                'amount' => $this->amount_to_precision($symbol, $amount), // positive value for adding margin, negative for reducing
                'holdSide' => $holdSide, // long or short
                'productType' => $productType,
            );
            $params = $this->omit($params, 'holdSide');
            $response = Async\await($this->privateMixPostV2MixAccountSetMargin ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700813444618,
            //         "data" => ""
            //     }
            //
            return $this->extend($this->parse_margin_modification($response, $market), array(
                'amount' => $this->parse_number($amount),
                'type' => $type,
            ));
        }) ();
    }

    public function parse_margin_modification(array $data, ?array $market = null): array {
        //
        // addMargin/reduceMargin
        //
        //     {
        //         "code" => "00000",
        //         "msg" => "success",
        //         "requestTime" => 1700813444618,
        //         "data" => ""
        //     }
        //
        $errorCode = $this->safe_string($data, 'code');
        $status = ($errorCode === '00000') ? 'ok' : 'failed';
        return array(
            'info' => $data,
            'symbol' => $market['symbol'],
            'type' => null,
            'marginMode' => 'isolated',
            'amount' => null,
            'total' => null,
            'code' => $market['settle'],
            'status' => $status,
            'timestamp' => null,
            'datetime' => null,
        );
    }

    public function reduce_margin(string $symbol, float $amount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $amount, $params) {
            /**
             * remove margin from a position
             *
             * @see https://www.bitget.com/api-doc/contract/account/Change-Margin
             *
             * @param {string} $symbol unified market $symbol
             * @param {float} $amount the $amount of margin to remove
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=reduce-margin-structure margin structure~
             */
            if ($amount > 0) {
                throw new BadRequest($this->id . ' reduceMargin() $amount parameter must be a negative value');
            }
            $holdSide = $this->safe_string($params, 'holdSide');
            if ($holdSide === null) {
                throw new ArgumentsRequired($this->id . ' reduceMargin() requires a $holdSide parameter, either long or short');
            }
            return Async\await($this->modify_margin_helper($symbol, $amount, 'reduce', $params));
        }) ();
    }

    public function add_margin(string $symbol, float $amount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $amount, $params) {
            /**
             * add margin
             *
             * @see https://www.bitget.com/api-doc/contract/account/Change-Margin
             *
             * @param {string} $symbol unified market $symbol
             * @param {float} $amount the $amount of margin to add
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=add-margin-structure margin structure~
             */
            $holdSide = $this->safe_string($params, 'holdSide');
            if ($holdSide === null) {
                throw new ArgumentsRequired($this->id . ' addMargin() requires a $holdSide parameter, either long or short');
            }
            return Async\await($this->modify_margin_helper($symbol, $amount, 'add', $params));
        }) ();
    }

    public function fetch_leverage(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the set leverage for a $market
             *
             * @see https://www.bitget.com/api-doc/contract/account/Get-Single-Account
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=leverage-structure leverage structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'marginCoin' => $market['settleId'],
                'productType' => $productType,
            );
            $response = Async\await($this->privateMixGetV2MixAccountAccount ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1709366911964,
            //         "data" => {
            //             "marginCoin" => "USDT",
            //             "locked" => "0",
            //             "available" => "0",
            //             "crossedMaxAvailable" => "0",
            //             "isolatedMaxAvailable" => "0",
            //             "maxTransferOut" => "0",
            //             "accountEquity" => "0",
            //             "usdtEquity" => "0.000000009166",
            //             "btcEquity" => "0",
            //             "crossedRiskRate" => "0",
            //             "crossedMarginLeverage" => 20,
            //             "isolatedLongLever" => 20,
            //             "isolatedShortLever" => 20,
            //             "marginMode" => "crossed",
            //             "posMode" => "hedge_mode",
            //             "unrealizedPL" => "0",
            //             "coupon" => "0",
            //             "crossedUnrealizedPL" => "0",
            //             "isolatedUnrealizedPL" => ""
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_leverage($data, $market);
        }) ();
    }

    public function parse_leverage(array $leverage, ?array $market = null): array {
        $isCrossMarginMode = $this->safe_string($leverage, 'marginMode') === 'crossed';
        $longLevKey = $isCrossMarginMode ? 'crossedMarginLeverage' : 'isolatedLongLever';
        $shortLevKey = $isCrossMarginMode ? 'crossedMarginLeverage' : 'isolatedShortLever';
        return array(
            'info' => $leverage,
            'symbol' => $market['symbol'],
            'marginMode' => $isCrossMarginMode ? 'cross' : 'isolated',
            'longLeverage' => $this->safe_integer($leverage, $longLevKey),
            'shortLeverage' => $this->safe_integer($leverage, $shortLevKey),
        );
    }

    public function set_leverage(int $leverage, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($leverage, $symbol, $params) {
            /**
             * set the level of $leverage for a $market
             *
             * @see https://www.bitget.com/api-doc/contract/account/Change-Leverage
             * @see https://www.bitget.com/api-doc/uta/account/Change-Leverage
             *
             * @param {int} $leverage the rate of $leverage
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->holdSide] *isolated only* position direction, 'long' or 'short'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @param {boolean} [$params->posSide] required for $uta isolated margin, long or short
             * @return {array} $response from the exchange
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' setLeverage() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'leverage' => $this->number_to_string($leverage),
            );
            $uta = null;
            $response = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'setLeverage', 'uta', false);
            if ($uta) {
                if ($productType === 'SPOT') {
                    $marginMode = null;
                    list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchTrades', $params);
                    if ($marginMode !== null) {
                        $productType = 'MARGIN';
                    }
                }
                $request['coin'] = $market['settleId'];
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaPostV3AccountSetLeverage ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1752815940833,
                //         "data" => "success"
                //     }
                //
            } else {
                $request['marginCoin'] = $market['settleId'];
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixPostV2MixAccountSetLeverage ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1700864711517,
                //         "data" => {
                //             "symbol" => "BTCUSDT",
                //             "marginCoin" => "USDT",
                //             "longLeverage" => "25",
                //             "shortLeverage" => "25",
                //             "crossMarginLeverage" => "25",
                //             "marginMode" => "crossed"
                //         }
                //     }
                //
            }
            return $response;
        }) ();
    }

    public function set_margin_mode(string $marginMode, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($marginMode, $symbol, $params) {
            /**
             * set margin mode to 'cross' or 'isolated'
             *
             * @see https://www.bitget.com/api-doc/contract/account/Change-Margin-Mode
             *
             * @param {string} $marginMode 'cross' or 'isolated'
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} $response from the exchange
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' setMarginMode() requires a $symbol argument');
            }
            $marginMode = strtolower($marginMode);
            if ($marginMode === 'cross') {
                $marginMode = 'crossed';
            }
            if (($marginMode !== 'isolated') && ($marginMode !== 'crossed')) {
                throw new ArgumentsRequired($this->id . ' setMarginMode() $marginMode must be either isolated or crossed (cross)');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'marginCoin' => $market['settleId'],
                'marginMode' => $marginMode,
                'productType' => $productType,
            );
            $response = Async\await($this->privateMixPostV2MixAccountSetMarginMode ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700865205552,
            //         "data" => {
            //             "symbol" => "BTCUSDT",
            //             "marginCoin" => "USDT",
            //             "longLeverage" => "20",
            //             "shortLeverage" => "3",
            //             "marginMode" => "isolated"
            //         }
            //     }
            //
            return $response;
        }) ();
    }

    public function set_position_mode(bool $hedged, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($hedged, $symbol, $params) {
            /**
             * set $hedged to true or false for a $market
             *
             * @see https://www.bitget.com/api-doc/contract/account/Change-Hold-Mode
             * @see https://www.bitget.com/api-doc/uta/account/Change-Position-Mode
             *
             * @param {bool} $hedged set to true to use dualSidePosition
             * @param {string} $symbol not used by bitget setPositionMode ()
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->productType] required if not $uta and $symbol is null => 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} $response from the exchange
             */
            Async\await($this->load_markets());
            $posMode = $hedged ? 'hedge_mode' : 'one_way_mode';
            $request = array();
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
            }
            $productType = null;
            $uta = null;
            $response = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'setPositionMode', 'uta', false);
            if ($uta) {
                $request['holdMode'] = $posMode;
                $response = Async\await($this->privateUtaPostV3AccountSetHoldMode ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1752816734592,
                //         "data" => "success"
                //     }
                //
            } else {
                $request['posMode'] = $posMode;
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixPostV2MixAccountSetPositionMode ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1700865608009,
                //         "data" => {
                //             "posMode" => "hedge_mode"
                //         }
                //     }
                //
            }
            return $response;
        }) ();
    }

    public function fetch_open_interest(string $symbol, $params = array ()) {
        return Async\async(function () use ($symbol, $params) {
            /**
             * retrieves the open interest of a contract trading pair
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-Open-Interest
             * @see https://www.bitget.com/api-doc/uta/public/Get-Open-Interest
             *
             * @param {string} $symbol unified CCXT $market $symbol
             * @param {array} [$params] exchange specific parameters
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} an open interest structurearray(@link https://docs.ccxt.com/#/?id=open-interest-structure)
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['contract']) {
                throw new BadRequest($this->id . ' fetchOpenInterest() supports contract markets only');
            }
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
            );
            $uta = null;
            $response = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchOpenInterest', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->publicUtaGetV3MarketOpenInterest ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1751101221545,
                //         "data" => {
                //             "list" => array(
                //                 {
                //                     "symbol" => "BTCUSDT",
                //                     "openInterest" => "18166.3583"
                //                 }
                //             ),
                //             "ts" => "1751101220993"
                //         }
                //     }
                //
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketOpenInterest ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1700866041022,
                //         "data" => {
                //             "openInterestList" => array(
                //                 {
                //                     "symbol" => "BTCUSDT",
                //                     "size" => "52234.134"
                //                 }
                //             ),
                //             "ts" => "1700866041023"
                //         }
                //     }
                //
            }
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_open_interest($data, $market);
        }) ();
    }

    public function parse_open_interest($interest, ?array $market = null) {
        //
        // default
        //
        //     {
        //         "openInterestList" => array(
        //             {
        //                 "symbol" => "BTCUSDT",
        //                 "size" => "52234.134"
        //             }
        //         ),
        //         "ts" => "1700866041023"
        //     }
        //
        // uta
        //
        //     {
        //         "list" => array(
        //             {
        //                 "symbol" => "BTCUSDT",
        //                 "openInterest" => "18166.3583"
        //             }
        //         ),
        //         "ts" => "1751101220993"
        //     }
        //
        $data = $this->safe_list_2($interest, 'openInterestList', 'list', array());
        $timestamp = $this->safe_integer($interest, 'ts');
        $marketId = $this->safe_string($data[0], 'symbol');
        return $this->safe_open_interest(array(
            'symbol' => $this->safe_symbol($marketId, $market, null, 'contract'),
            'openInterestAmount' => $this->safe_number_2($data[0], 'size', 'openInterest'),
            'openInterestValue' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'info' => $interest,
        ), $market);
    }

    public function fetch_transfers(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch a history of internal transfers made on an account
             *
             * @see https://www.bitget.com/api-doc/spot/account/Get-Account-TransferRecords
             *
             * @param {string} $code unified $currency $code of the $currency transferred
             * @param {int} [$since] the earliest time in ms to fetch transfers for
             * @param {int} [$limit] the maximum number of transfers structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] the latest time in ms to fetch entries for
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transfer-structure transfer structures~
             */
            if ($code === null) {
                throw new ArgumentsRequired($this->id . ' fetchTransfers() requires a $code argument');
            }
            Async\await($this->load_markets());
            $type = null;
            list($type, $params) = $this->handle_market_type_and_params('fetchTransfers', null, $params);
            $fromAccount = $this->safe_string($params, 'fromAccount', $type);
            $params = $this->omit($params, 'fromAccount');
            $accountsByType = $this->safe_value($this->options, 'accountsByType', array());
            $type = $this->safe_string($accountsByType, $fromAccount);
            $currency = $this->currency($code);
            $request = array(
                'coin' => $currency['id'],
                'fromType' => $type,
            );
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            $response = Async\await($this->privateSpotGetV2SpotAccountTransferRecords ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700873854651,
            //         "data" => array(
            //             array(
            //                 "coin" => "USDT",
            //                 "status" => "Successful",
            //                 "toType" => "crossed_margin",
            //                 "toSymbol" => "",
            //                 "fromType" => "spot",
            //                 "fromSymbol" => "",
            //                 "size" => "11.64958799",
            //                 "ts" => "1700729673028",
            //                 "clientOid" => "1111506298504744960",
            //                 "transferId" => "24930940"
            //             ),
            //         )
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_transfers($data, $currency, $since, $limit);
        }) ();
    }

    public function transfer(string $code, float $amount, string $fromAccount, string $toAccount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $amount, $fromAccount, $toAccount, $params) {
            /**
             * transfer $currency internally between wallets on the same account
             *
             * @see https://www.bitget.com/api-doc/spot/account/Wallet-Transfer
             *
             * @param {string} $code unified $currency $code
             * @param {float} $amount amount to transfer
             * @param {string} $fromAccount account to transfer from
             * @param {string} $toAccount account to transfer to
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->symbol] unified CCXT $market $symbol, required when transferring to or from an account type that is a leveraged position-by-position account
             * @param {string} [$params->clientOid] custom id
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=transfer-structure transfer structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $accountsByType = $this->safe_value($this->options, 'accountsByType', array());
            $fromType = $this->safe_string($accountsByType, $fromAccount);
            $toType = $this->safe_string($accountsByType, $toAccount);
            $request = array(
                'fromType' => $fromType,
                'toType' => $toType,
                'amount' => $amount,
                'coin' => $currency['id'],
            );
            $symbol = $this->safe_string($params, 'symbol');
            $params = $this->omit($params, 'symbol');
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
                $request['symbol'] = $market['id'];
            }
            $response = Async\await($this->privateSpotPostV2SpotWalletTransfer ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700874302021,
            //         "data" => {
            //             "transferId" => "1112112916581847040",
            //             "clientOrderId" => null
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $data['ts'] = $this->safe_integer($response, 'requestTime');
            return $this->parse_transfer($data, $currency);
        }) ();
    }

    public function parse_transfer(array $transfer, ?array $currency = null): array {
        //
        // $transfer
        //
        //     {
        //         "transferId" => "1112112916581847040",
        //         "clientOrderId" => null,
        //         "ts" => 1700874302021
        //     }
        //
        // fetchTransfers
        //
        //     {
        //         "coin" => "USDT",
        //         "status" => "Successful",
        //         "toType" => "crossed_margin",
        //         "toSymbol" => "",
        //         "fromType" => "spot",
        //         "fromSymbol" => "",
        //         "size" => "11.64958799",
        //         "ts" => "1700729673028",
        //         "clientOid" => "1111506298504744960",
        //         "transferId" => "24930940"
        //     }
        //
        $timestamp = $this->safe_integer($transfer, 'ts');
        $status = $this->safe_string_lower($transfer, 'status');
        $currencyId = $this->safe_string($transfer, 'coin');
        $fromAccountRaw = $this->safe_string($transfer, 'fromType');
        $accountsById = $this->safe_value($this->options, 'accountsById', array());
        $fromAccount = $this->safe_string($accountsById, $fromAccountRaw, $fromAccountRaw);
        $toAccountRaw = $this->safe_string($transfer, 'toType');
        $toAccount = $this->safe_string($accountsById, $toAccountRaw, $toAccountRaw);
        return array(
            'info' => $transfer,
            'id' => $this->safe_string($transfer, 'transferId'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'currency' => $this->safe_currency_code($currencyId, $currency),
            'amount' => $this->safe_number($transfer, 'size'),
            'fromAccount' => $fromAccount,
            'toAccount' => $toAccount,
            'status' => $this->parse_transfer_status($status),
        );
    }

    public function parse_transfer_status(?string $status): ?string {
        $statuses = array(
            'successful' => 'ok',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function parse_deposit_withdraw_fee($fee, ?array $currency = null) {
        //
        //     {
        //         "chains" => array(
        //             array(
        //                 "browserUrl" => "https://blockchair.com/bitcoin/transaction/",
        //                 "chain" => "BTC",
        //                 "depositConfirm" => "1",
        //                 "extraWithdrawFee" => "0",
        //                 "minDepositAmount" => "0.0001",
        //                 "minWithdrawAmount" => "0.005",
        //                 "needTag" => "false",
        //                 "rechargeable" => "true",
        //                 "withdrawConfirm" => "1",
        //                 "withdrawFee" => "0.0004",
        //                 "withdrawable" => "true"
        //             ),
        //         ),
        //         "coin" => "BTC",
        //         "coinId" => "1",
        //         "transfer" => "true""
        //     }
        //
        $chains = $this->safe_value($fee, 'chains', array());
        $chainsLength = count($chains);
        $result = array(
            'info' => $fee,
            'withdraw' => array(
                'fee' => null,
                'percentage' => null,
            ),
            'deposit' => array(
                'fee' => null,
                'percentage' => null,
            ),
            'networks' => array(),
        );
        for ($i = 0; $i < $chainsLength; $i++) {
            $chain = $chains[$i];
            $networkId = $this->safe_string($chain, 'chain');
            $currencyCode = $this->safe_string($currency, 'code');
            $networkCode = $this->network_id_to_code($networkId, $currencyCode);
            $result['networks'][$networkCode] = array(
                'deposit' => array( 'fee' => null, 'percentage' => null ),
                'withdraw' => array( 'fee' => $this->safe_number($chain, 'withdrawFee'), 'percentage' => false ),
            );
            if ($chainsLength === 1) {
                $result['withdraw']['fee'] = $this->safe_number($chain, 'withdrawFee');
                $result['withdraw']['percentage'] = false;
            }
        }
        return $result;
    }

    public function fetch_deposit_withdraw_fees(?array $codes = null, $params = array ()) {
        return Async\async(function () use ($codes, $params) {
            /**
             * fetch deposit and withdraw fees
             *
             * @see https://www.bitget.com/api-doc/spot/market/Get-Coin-List
             *
             * @param {string[]|null} $codes list of unified currency $codes
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a list of ~@link https://docs.ccxt.com/#/?id=fee-structure fee structures~
             */
            Async\await($this->load_markets());
            $response = Async\await($this->publicSpotGetV2SpotPublicCoins ($params));
            //
            //     {
            //         "code" => "00000",
            //         "data" => array(
            //             {
            //                 "chains" => array(
            //                     array(
            //                         "browserUrl" => "https://blockchair.com/bitcoin/transaction/",
            //                         "chain" => "BTC",
            //                         "depositConfirm" => "1",
            //                         "extraWithdrawFee" => "0",
            //                         "minDepositAmount" => "0.0001",
            //                         "minWithdrawAmount" => "0.005",
            //                         "needTag" => "false",
            //                         "rechargeable" => "true",
            //                         "withdrawConfirm" => "1",
            //                         "withdrawFee" => "0.0004",
            //                         "withdrawable" => "true"
            //                     ),
            //                 ),
            //                 "coin" => "BTC",
            //                 "coinId" => "1",
            //                 "transfer" => "true""
            //             }
            //         ),
            //         "msg" => "success",
            //         "requestTime" => "1700120731773"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_deposit_withdraw_fees($data, $codes, 'coin');
        }) ();
    }

    public function borrow_cross_margin(string $code, float $amount, $params = array ()) {
        return Async\async(function () use ($code, $amount, $params) {
            /**
             * create a loan to borrow margin
             *
             * @see https://www.bitget.com/api-doc/margin/cross/account/Cross-Borrow
             *
             * @param {string} $code unified $currency $code of the $currency to borrow
             * @param {string} $amount the $amount to borrow
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'coin' => $currency['id'],
                'borrowAmount' => $this->currency_to_precision($code, $amount),
            );
            $response = Async\await($this->privateMarginPostV2MarginCrossedAccountBorrow ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700876470931,
            //         "data" => {
            //             "loanId" => "1112122013642272769",
            //             "coin" => "USDT",
            //             "borrowAmount" => "4"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_margin_loan($data, $currency);
        }) ();
    }

    public function borrow_isolated_margin(string $symbol, string $code, float $amount, $params = array ()) {
        return Async\async(function () use ($symbol, $code, $amount, $params) {
            /**
             * create a loan to borrow margin
             *
             * @see https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Borrow
             *
             * @param {string} $symbol unified $market $symbol
             * @param {string} $code unified $currency $code of the $currency to borrow
             * @param {string} $amount the $amount to borrow
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $market = $this->market($symbol);
            $request = array(
                'coin' => $currency['id'],
                'borrowAmount' => $this->currency_to_precision($code, $amount),
                'symbol' => $market['id'],
            );
            $response = Async\await($this->privateMarginPostV2MarginIsolatedAccountBorrow ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700877255605,
            //         "data" => {
            //             "loanId" => "1112125304879067137",
            //             "symbol" => "BTCUSDT",
            //             "coin" => "USDT",
            //             "borrowAmount" => "4"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_margin_loan($data, $currency, $market);
        }) ();
    }

    public function repay_isolated_margin(string $symbol, string $code, $amount, $params = array ()) {
        return Async\async(function () use ($symbol, $code, $amount, $params) {
            /**
             * repay borrowed margin and interest
             *
             * @see https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Repay
             *
             * @param {string} $symbol unified $market $symbol
             * @param {string} $code unified $currency $code of the $currency to repay
             * @param {string} $amount the $amount to repay
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $market = $this->market($symbol);
            $request = array(
                'coin' => $currency['id'],
                'repayAmount' => $this->currency_to_precision($code, $amount),
                'symbol' => $market['id'],
            );
            $response = Async\await($this->privateMarginPostV2MarginIsolatedAccountRepay ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700877518012,
            //         "data" => {
            //             "remainDebtAmount" => "0",
            //             "repayId" => "1112126405439270912",
            //             "symbol" => "BTCUSDT",
            //             "coin" => "USDT",
            //             "repayAmount" => "8.000137"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_margin_loan($data, $currency, $market);
        }) ();
    }

    public function repay_cross_margin(string $code, $amount, $params = array ()) {
        return Async\async(function () use ($code, $amount, $params) {
            /**
             * repay borrowed margin and interest
             *
             * @see https://www.bitget.com/api-doc/margin/cross/account/Cross-Repay
             *
             * @param {string} $code unified $currency $code of the $currency to repay
             * @param {string} $amount the $amount to repay
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'coin' => $currency['id'],
                'repayAmount' => $this->currency_to_precision($code, $amount),
            );
            $response = Async\await($this->privateMarginPostV2MarginCrossedAccountRepay ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700876704885,
            //         "data" => {
            //             "remainDebtAmount" => "0",
            //             "repayId" => "1112122994945830912",
            //             "coin" => "USDT",
            //             "repayAmount" => "4.00006834"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            return $this->parse_margin_loan($data, $currency);
        }) ();
    }

    public function parse_margin_loan($info, ?array $currency = null, ?array $market = null) {
        //
        // isolated => borrowMargin
        //
        //     {
        //         "loanId" => "1112125304879067137",
        //         "symbol" => "BTCUSDT",
        //         "coin" => "USDT",
        //         "borrowAmount" => "4"
        //     }
        //
        // cross => borrowMargin
        //
        //     {
        //         "loanId" => "1112122013642272769",
        //         "coin" => "USDT",
        //         "borrowAmount" => "4"
        //     }
        //
        // isolated => repayMargin
        //
        //     {
        //         "remainDebtAmount" => "0",
        //         "repayId" => "1112126405439270912",
        //         "symbol" => "BTCUSDT",
        //         "coin" => "USDT",
        //         "repayAmount" => "8.000137"
        //     }
        //
        // cross => repayMargin
        //
        //     {
        //         "remainDebtAmount" => "0",
        //         "repayId" => "1112122994945830912",
        //         "coin" => "USDT",
        //         "repayAmount" => "4.00006834"
        //     }
        //
        $currencyId = $this->safe_string($info, 'coin');
        $marketId = $this->safe_string($info, 'symbol');
        $symbol = null;
        if ($marketId !== null) {
            $symbol = $this->safe_symbol($marketId, $market, null, 'spot');
        }
        return array(
            'id' => $this->safe_string_2($info, 'loanId', 'repayId'),
            'currency' => $this->safe_currency_code($currencyId, $currency),
            'amount' => $this->safe_number_2($info, 'borrowAmount', 'repayAmount'),
            'symbol' => $symbol,
            'timestamp' => null,
            'datetime' => null,
            'info' => $info,
        );
    }

    public function fetch_my_liquidations(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * retrieves the users liquidated positions
             *
             * @see https://www.bitget.com/api-doc/margin/cross/record/Get-Cross-Liquidation-Records
             * @see https://www.bitget.com/api-doc/margin/isolated/record/Get-Isolated-Liquidation-Records
             *
             * @param {string} [$symbol] unified CCXT $market $symbol
             * @param {int} [$since] the earliest time in ms to fetch $liquidations for
             * @param {int} [$limit] the maximum number of liquidation structures to retrieve
             * @param {array} [$params] exchange specific parameters for the bitget api endpoint
             * @param {int} [$params->until] timestamp in ms of the latest liquidation
             * @param {string} [$params->marginMode] 'cross' or 'isolated' default value is 'cross'
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array} an array of ~@link https://docs.ccxt.com/#/?id=liquidation-structure liquidation structures~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchMyLiquidations', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchMyLiquidations', $symbol, $since, $limit, $params, 'minId', 'idLessThan'));
            }
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
            }
            $type = null;
            list($type, $params) = $this->handle_market_type_and_params('fetchMyLiquidations', $market, $params);
            if ($type !== 'spot') {
                throw new NotSupported($this->id . ' fetchMyLiquidations() supports spot margin markets only');
            }
            $request = array();
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            if ($since !== null) {
                $request['startTime'] = $since;
            } else {
                $request['startTime'] = $this->milliseconds() - 7776000000;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchMyLiquidations', $params, 'cross');
            if ($marginMode === 'isolated') {
                if ($symbol === null) {
                    throw new ArgumentsRequired($this->id . ' fetchMyLiquidations() requires a $symbol argument');
                }
                $request['symbol'] = $market['id'];
                $response = Async\await($this->privateMarginGetV2MarginIsolatedLiquidationHistory ($this->extend($request, $params)));
            } elseif ($marginMode === 'cross') {
                $response = Async\await($this->privateMarginGetV2MarginCrossedLiquidationHistory ($this->extend($request, $params)));
            }
            //
            // isolated
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1698114119193,
            //         "data" => {
            //             "resultList" => array(
            //                 {
            //                     "liqId" => "123",
            //                     "symbol" => "BTCUSDT",
            //                     "liqStartTime" => "1653453245342",
            //                     "liqEndTime" => "16312423423432",
            //                     "liqRiskRatio" => "1.01",
            //                     "totalAssets" => "1242.34",
            //                     "totalDebt" => "1100",
            //                     "liqFee" => "1.2",
            //                     "uTime" => "1668134458717",
            //                     "cTime" => "1653453245342"
            //                 }
            //             ),
            //             "maxId" => "0",
            //             "minId" => "0"
            //         }
            //     }
            //
            // cross
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1698114119193,
            //         "data" => {
            //             "resultList" => array(
            //                 {
            //                     "liqId" => "123",
            //                     "liqStartTime" => "1653453245342",
            //                     "liqEndTime" => "16312423423432",
            //                     "liqRiskRatio" => "1.01",
            //                     "totalAssets" => "1242.34",
            //                     "totalDebt" => "1100",
            //                     "LiqFee" => "1.2",
            //                     "uTime" => "1668134458717",
            //                     "cTime" => "1653453245342"
            //                 }
            //             ),
            //             "maxId" => "0",
            //             "minId" => "0"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $liquidations = $this->safe_list($data, 'resultList', array());
            return $this->parse_liquidations($liquidations, $market, $since, $limit);
        }) ();
    }

    public function parse_liquidation($liquidation, ?array $market = null) {
        //
        // isolated
        //
        //     {
        //         "liqId" => "123",
        //         "symbol" => "BTCUSDT",
        //         "liqStartTime" => "1653453245342",
        //         "liqEndTime" => "16312423423432",
        //         "liqRiskRatio" => "1.01",
        //         "totalAssets" => "1242.34",
        //         "totalDebt" => "1100",
        //         "liqFee" => "1.2",
        //         "uTime" => "1692690126000"
        //         "cTime" => "1653453245342"
        //     }
        //
        // cross
        //
        //     {
        //         "liqId" => "123",
        //         "liqStartTime" => "1653453245342",
        //         "liqEndTime" => "16312423423432",
        //         "liqRiskRatio" => "1.01",
        //         "totalAssets" => "1242.34",
        //         "totalDebt" => "1100",
        //         "LiqFee" => "1.2",
        //         "uTime" => "1692690126000"
        //         "cTime" => "1653453245342"
        //     }
        //
        $marketId = $this->safe_string($liquidation, 'symbol');
        $timestamp = $this->safe_integer($liquidation, 'liqEndTime');
        $liquidationFee = $this->safe_string_2($liquidation, 'LiqFee', 'liqFee');
        $totalDebt = $this->safe_string($liquidation, 'totalDebt');
        $quoteValueString = Precise::string_add($liquidationFee, $totalDebt);
        return $this->safe_liquidation(array(
            'info' => $liquidation,
            'symbol' => $this->safe_symbol($marketId, $market),
            'contracts' => null,
            'contractSize' => null,
            'price' => null,
            'baseValue' => null,
            'quoteValue' => $this->parse_number($quoteValueString),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
        ));
    }

    public function fetch_isolated_borrow_rate(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the rate of interest to borrow a currency for margin trading
             *
             * @see https://www.bitget.com/api-doc/margin/isolated/account/Isolated-Margin-Interest-Rate-And-Max-Borrowable-Amount
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=isolated-borrow-rate-structure isolated borrow rate structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $response = Async\await($this->privateMarginGetV2MarginIsolatedInterestRateAndLimit ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700878692567,
            //         "data" => array(
            //             {
            //                 "symbol" => "BTCUSDT",
            //                 "leverage" => "10",
            //                 "baseCoin" => "BTC",
            //                 "baseTransferable" => true,
            //                 "baseBorrowable" => true,
            //                 "baseDailyInterestRate" => "0.00007",
            //                 "baseAnnuallyInterestRate" => "0.02555",
            //                 "baseMaxBorrowableAmount" => "27",
            //                 "baseVipList" => array(
            //                     array("level":"0","dailyInterestRate":"0.00007","limit":"27","annuallyInterestRate":"0.02555","discountRate":"1"),
            //                     array("level":"1","dailyInterestRate":"0.0000679","limit":"27.81","annuallyInterestRate":"0.0247835","discountRate":"0.97"),
            //                     array("level":"2","dailyInterestRate":"0.0000644","limit":"29.16","annuallyInterestRate":"0.023506","discountRate":"0.92"),
            //                     array("level":"3","dailyInterestRate":"0.0000602","limit":"31.32","annuallyInterestRate":"0.021973","discountRate":"0.86"),
            //                     array("level":"4","dailyInterestRate":"0.0000525","limit":"35.91","annuallyInterestRate":"0.0191625","discountRate":"0.75"),
            //                     array("level":"5","dailyInterestRate":"0.000042","limit":"44.82","annuallyInterestRate":"0.01533","discountRate":"0.6")
            //                 ),
            //                 "quoteCoin" => "USDT",
            //                 "quoteTransferable" => true,
            //                 "quoteBorrowable" => true,
            //                 "quoteDailyInterestRate" => "0.00041095",
            //                 "quoteAnnuallyInterestRate" => "0.14999675",
            //                 "quoteMaxBorrowableAmount" => "300000",
            //                 "quoteList" => array(
            //                     array("level":"0","dailyInterestRate":"0.00041095","limit":"300000","annuallyInterestRate":"0.14999675","discountRate":"1"),
            //                     array("level":"1","dailyInterestRate":"0.00039863","limit":"309000","annuallyInterestRate":"0.14549995","discountRate":"0.97"),
            //                     array("level":"2","dailyInterestRate":"0.00037808","limit":"324000","annuallyInterestRate":"0.1379992","discountRate":"0.92"),
            //                     array("level":"3","dailyInterestRate":"0.00035342","limit":"348000","annuallyInterestRate":"0.1289983","discountRate":"0.86"),
            //                     array("level":"4","dailyInterestRate":"0.00030822","limit":"399000","annuallyInterestRate":"0.1125003","discountRate":"0.75"),
            //                     array("level":"5","dailyInterestRate":"0.00024657","limit":"498000","annuallyInterestRate":"0.08999805","discountRate":"0.6")
            //                 )
            //             }
            //         )
            //     }
            //
            $timestamp = $this->safe_integer($response, 'requestTime');
            $data = $this->safe_value($response, 'data', array());
            $first = $this->safe_value($data, 0, array());
            $first['timestamp'] = $timestamp;
            return $this->parse_isolated_borrow_rate($first, $market);
        }) ();
    }

    public function parse_isolated_borrow_rate(array $info, ?array $market = null): array {
        //
        //     {
        //         "symbol" => "BTCUSDT",
        //         "leverage" => "10",
        //         "baseCoin" => "BTC",
        //         "baseTransferable" => true,
        //         "baseBorrowable" => true,
        //         "baseDailyInterestRate" => "0.00007",
        //         "baseAnnuallyInterestRate" => "0.02555",
        //         "baseMaxBorrowableAmount" => "27",
        //         "baseVipList" => array(
        //             array("level":"0","dailyInterestRate":"0.00007","limit":"27","annuallyInterestRate":"0.02555","discountRate":"1"),
        //             array("level":"1","dailyInterestRate":"0.0000679","limit":"27.81","annuallyInterestRate":"0.0247835","discountRate":"0.97"),
        //             array("level":"2","dailyInterestRate":"0.0000644","limit":"29.16","annuallyInterestRate":"0.023506","discountRate":"0.92"),
        //             array("level":"3","dailyInterestRate":"0.0000602","limit":"31.32","annuallyInterestRate":"0.021973","discountRate":"0.86"),
        //             array("level":"4","dailyInterestRate":"0.0000525","limit":"35.91","annuallyInterestRate":"0.0191625","discountRate":"0.75"),
        //             array("level":"5","dailyInterestRate":"0.000042","limit":"44.82","annuallyInterestRate":"0.01533","discountRate":"0.6")
        //         ),
        //         "quoteCoin" => "USDT",
        //         "quoteTransferable" => true,
        //         "quoteBorrowable" => true,
        //         "quoteDailyInterestRate" => "0.00041095",
        //         "quoteAnnuallyInterestRate" => "0.14999675",
        //         "quoteMaxBorrowableAmount" => "300000",
        //         "quoteList" => array(
        //             array("level":"0","dailyInterestRate":"0.00041095","limit":"300000","annuallyInterestRate":"0.14999675","discountRate":"1"),
        //             array("level":"1","dailyInterestRate":"0.00039863","limit":"309000","annuallyInterestRate":"0.14549995","discountRate":"0.97"),
        //             array("level":"2","dailyInterestRate":"0.00037808","limit":"324000","annuallyInterestRate":"0.1379992","discountRate":"0.92"),
        //             array("level":"3","dailyInterestRate":"0.00035342","limit":"348000","annuallyInterestRate":"0.1289983","discountRate":"0.86"),
        //             array("level":"4","dailyInterestRate":"0.00030822","limit":"399000","annuallyInterestRate":"0.1125003","discountRate":"0.75"),
        //             array("level":"5","dailyInterestRate":"0.00024657","limit":"498000","annuallyInterestRate":"0.08999805","discountRate":"0.6")
        //         )
        //     }
        //
        $marketId = $this->safe_string($info, 'symbol');
        $symbol = $this->safe_symbol($marketId, $market, null, 'spot');
        $baseId = $this->safe_string($info, 'baseCoin');
        $quoteId = $this->safe_string($info, 'quoteCoin');
        $timestamp = $this->safe_integer($info, 'timestamp');
        return array(
            'symbol' => $symbol,
            'base' => $this->safe_currency_code($baseId),
            'baseRate' => $this->safe_number($info, 'baseDailyInterestRate'),
            'quote' => $this->safe_currency_code($quoteId),
            'quoteRate' => $this->safe_number($info, 'quoteDailyInterestRate'),
            'period' => 86400000, // 1-Day
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'info' => $info,
        );
    }

    public function fetch_cross_borrow_rate(string $code, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $params) {
            /**
             * fetch the rate of interest to borrow a $currency for margin trading
             *
             * @see https://www.bitget.com/api-doc/margin/cross/account/Get-Cross-Margin-Interest-Rate-And-Borrowable
             * @see https://www.bitget.com/api-doc/uta/public/Get-Margin-Loans
             *
             * @param {string} $code unified $currency $code
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a {@link https://github.com/ccxt/ccxt/wiki/Manual#borrow-rate-structure borrow rate structure}
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'coin' => $currency['id'],
            );
            $uta = null;
            $response = null;
            $result = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchCrossBorrowRate', 'uta', false);
            if ($uta) {
                $response = Async\await($this->publicUtaGetV3MarketMarginLoans ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1752817798893,
                //         "data" => {
                //             "dailyInterest" => "0.00100008",
                //             "annualInterest" => "0.3650292",
                //             "limit" => "100"
                //         }
                //     }
                //
                $result = $this->safe_dict($response, 'data', array());
            } else {
                $response = Async\await($this->privateMarginGetV2MarginCrossedInterestRateAndLimit ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1700879047861,
                //         "data" => array(
                //             {
                //                 "coin" => "BTC",
                //                 "leverage" => "3",
                //                 "transferable" => true,
                //                 "borrowable" => true,
                //                 "dailyInterestRate" => "0.00007",
                //                 "annualInterestRate" => "0.02555",
                //                 "maxBorrowableAmount" => "26",
                //                 "vipList" => array(
                //                     array("level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"),
                //                     array("level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"),
                //                     array("level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"),
                //                     array("level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"),
                //                     array("level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"),
                //                     array("level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6")
                //                 )
                //             }
                //         )
                //     }
                //
                $data = $this->safe_value($response, 'data', array());
                $result = $this->safe_value($data, 0, array());
            }
            $timestamp = $this->safe_integer($response, 'requestTime');
            $result['timestamp'] = $timestamp;
            return $this->parse_borrow_rate($result, $currency);
        }) ();
    }

    public function parse_borrow_rate($info, ?array $currency = null) {
        //
        // default
        //
        //     {
        //         "coin" => "BTC",
        //         "leverage" => "3",
        //         "transferable" => true,
        //         "borrowable" => true,
        //         "dailyInterestRate" => "0.00007",
        //         "annualInterestRate" => "0.02555",
        //         "maxBorrowableAmount" => "26",
        //         "vipList" => array(
        //             array("level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"),
        //             array("level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"),
        //             array("level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"),
        //             array("level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"),
        //             array("level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"),
        //             array("level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6")
        //         )
        //     }
        //
        // uta
        //
        //     {
        //         "dailyInterest" => "0.00100008",
        //         "annualInterest" => "0.3650292",
        //         "limit" => "100"
        //     }
        //
        $currencyId = $this->safe_string($info, 'coin');
        $timestamp = $this->safe_integer($info, 'timestamp');
        return array(
            'currency' => $this->safe_currency_code($currencyId, $currency),
            'rate' => $this->safe_number_2($info, 'dailyInterestRate', 'dailyInterest'),
            'period' => 86400000, // 1-Day
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'info' => $info,
        );
    }

    public function fetch_borrow_interest(?string $code = null, ?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $symbol, $since, $limit, $params) {
            /**
             * fetch the $interest owed by the user for borrowing $currency for margin trading
             *
             * @see https://www.bitget.com/api-doc/margin/cross/record/Get-Cross-Interest-Records
             * @see https://www.bitget.com/api-doc/margin/isolated/record/Get-Isolated-Interest-Records
             *
             * @param {string} [$code] unified $currency $code
             * @param {string} [$symbol] unified $market $symbol when fetching $interest in isolated markets
             * @param {int} [$since] the earliest time in ms to fetch borrow $interest for
             * @param {int} [$limit] the maximum number of structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=borrow-$interest-structure borrow $interest structures~
             */
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchBorrowInterest', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_cursor('fetchBorrowInterest', $symbol, $since, $limit, $params, 'minId', 'idLessThan'));
            }
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
            }
            $request = array();
            $currency = null;
            if ($code !== null) {
                $currency = $this->currency($code);
                $request['coin'] = $currency['id'];
            }
            if ($since !== null) {
                $request['startTime'] = $since;
            } else {
                $request['startTime'] = $this->milliseconds() - 7776000000;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchBorrowInterest', $params, 'cross');
            if ($marginMode === 'isolated') {
                if ($symbol === null) {
                    throw new ArgumentsRequired($this->id . ' fetchBorrowInterest() requires a $symbol argument');
                }
                $request['symbol'] = $market['id'];
                $response = Async\await($this->privateMarginGetV2MarginIsolatedInterestHistory ($this->extend($request, $params)));
            } elseif ($marginMode === 'cross') {
                $response = Async\await($this->privateMarginGetV2MarginCrossedInterestHistory ($this->extend($request, $params)));
            }
            //
            // isolated
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700879935189,
            //         "data" => {
            //             "resultList" => array(
            //                 array(
            //                     "interestId" => "1112125304879067137",
            //                     "interestCoin" => "USDT",
            //                     "dailyInterestRate" => "0.00041095",
            //                     "loanCoin" => "USDT",
            //                     "interestAmount" => "0.0000685",
            //                     "interstType" => "first",
            //                     "symbol" => "BTCUSDT",
            //                     "cTime" => "1700877255648",
            //                     "uTime" => "1700877255648"
            //                 ),
            //             ),
            //             "maxId" => "1112125304879067137",
            //             "minId" => "1100138015672119298"
            //         }
            //     }
            //
            // cross
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1700879597044,
            //         "data" => {
            //             "resultList" => array(
            //                 array(
            //                     "interestId" => "1112122013642272769",
            //                     "interestCoin" => "USDT",
            //                     "dailyInterestRate" => "0.00041",
            //                     "loanCoin" => "USDT",
            //                     "interestAmount" => "0.00006834",
            //                     "interstType" => "first",
            //                     "cTime" => "1700876470957",
            //                     "uTime" => "1700876470957"
            //                 ),
            //             ),
            //             "maxId" => "1112122013642272769",
            //             "minId" => "1096917004629716993"
            //         }
            //     }
            //
            $data = $this->safe_value($response, 'data', array());
            $rows = $this->safe_value($data, 'resultList', array());
            $interest = $this->parse_borrow_interests($rows, $market);
            return $this->filter_by_currency_since_limit($interest, $code, $since, $limit);
        }) ();
    }

    public function parse_borrow_interest(array $info, ?array $market = null): array {
        //
        // isolated
        //
        //     {
        //         "interestId" => "1112125304879067137",
        //         "interestCoin" => "USDT",
        //         "dailyInterestRate" => "0.00041095",
        //         "loanCoin" => "USDT",
        //         "interestAmount" => "0.0000685",
        //         "interstType" => "first",
        //         "symbol" => "BTCUSDT",
        //         "cTime" => "1700877255648",
        //         "uTime" => "1700877255648"
        //     }
        //
        // cross
        //
        //     {
        //         "interestId" => "1112122013642272769",
        //         "interestCoin" => "USDT",
        //         "dailyInterestRate" => "0.00041",
        //         "loanCoin" => "USDT",
        //         "interestAmount" => "0.00006834",
        //         "interstType" => "first",
        //         "cTime" => "1700876470957",
        //         "uTime" => "1700876470957"
        //     }
        //
        $marketId = $this->safe_string($info, 'symbol');
        $market = $this->safe_market($marketId, $market);
        $marginMode = ($marketId !== null) ? 'isolated' : 'cross';
        $timestamp = $this->safe_integer($info, 'cTime');
        return array(
            'info' => $info,
            'symbol' => $this->safe_string($market, 'symbol'),
            'currency' => $this->safe_currency_code($this->safe_string($info, 'interestCoin')),
            'interest' => $this->safe_number($info, 'interestAmount'),
            'interestRate' => $this->safe_number($info, 'dailyInterestRate'),
            'amountBorrowed' => null,
            'marginMode' => $marginMode,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
        );
    }

    public function close_position(string $symbol, ?string $side = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $side, $params) {
            /**
             * closes an open position for a $market
             *
             * @see https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
             * @see https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
             *
             * @param {string} $symbol unified CCXT $market $symbol
             * @param {string} [$side] one-way mode => 'buy' or 'sell', hedge-mode => 'long' or 'short'
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} An ~@link https://docs.ccxt.com/#/?id=$order-structure $order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            $productType = null;
            $uta = null;
            $response = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'closePosition', 'uta', false);
            if ($uta) {
                if ($side !== null) {
                    $request['posSide'] = $side;
                }
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaPostV3TradeClosePositions ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1751020218384,
                //         "data" => {
                //             "list" => array(
                //                 {
                //                     "orderId" => "1322440134099320832",
                //                     "clientOid" => "1322440134099320833"
                //                 }
                //             )
                //         }
                //     }
                //
            } else {
                if ($side !== null) {
                    $request['holdSide'] = $side;
                }
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixPostV2MixOrderClosePositions ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1702975017017,
                //         "data" => {
                //             "successList" => array(
                //                 {
                //                     "orderId" => "1120923953904893955",
                //                     "clientOid" => "1120923953904893956"
                //                 }
                //             ),
                //             "failureList" => array(),
                //             "result" => false
                //         }
                //     }
                //
            }
            $data = $this->safe_value($response, 'data', array());
            $order = $this->safe_list_2($data, 'successList', 'list', array());
            return $this->parse_order($order[0], $market);
        }) ();
    }

    public function close_all_positions($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * closes all open positions for a market type
             *
             * @see https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
             * @see https://www.bitget.com/api-doc/uta/trade/Close-All-Positions
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->productType] 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array[]} A list of ~@link https://docs.ccxt.com/#/?id=position-structure position structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $productType = null;
            $uta = null;
            $response = null;
            list($productType, $params) = $this->handle_product_type_and_params(null, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'closeAllPositions', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaPostV3TradeClosePositions ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1751020218384,
                //         "data" => {
                //             "list" => array(
                //                 {
                //                     "orderId" => "1322440134099320832",
                //                     "clientOid" => "1322440134099320833"
                //                 }
                //             )
                //         }
                //     }
                //
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->privateMixPostV2MixOrderClosePositions ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1702975017017,
                //         "data" => {
                //             "successList" => array(
                //                 {
                //                     "orderId" => "1120923953904893955",
                //                     "clientOid" => "1120923953904893956"
                //                 }
                //             ),
                //             "failureList" => array(),
                //             "result" => false
                //         }
                //     }
                //
            }
            $data = $this->safe_value($response, 'data', array());
            $orderInfo = $this->safe_list_2($data, 'successList', 'list', array());
            return $this->parse_positions($orderInfo, null, $params);
        }) ();
    }

    public function fetch_margin_mode(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetches the margin mode of a trading pair
             *
             * @see https://www.bitget.com/api-doc/contract/account/Get-Single-Account
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the margin mode for
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-mode-structure margin mode structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
                'marginCoin' => $market['settleId'],
                'productType' => $productType,
            );
            $response = Async\await($this->privateMixGetV2MixAccountAccount ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1709791216652,
            //         "data" => {
            //             "marginCoin" => "USDT",
            //             "locked" => "0",
            //             "available" => "19.88811074",
            //             "crossedMaxAvailable" => "19.88811074",
            //             "isolatedMaxAvailable" => "19.88811074",
            //             "maxTransferOut" => "19.88811074",
            //             "accountEquity" => "19.88811074",
            //             "usdtEquity" => "19.888110749166",
            //             "btcEquity" => "0.000302183391",
            //             "crossedRiskRate" => "0",
            //             "crossedMarginLeverage" => 20,
            //             "isolatedLongLever" => 20,
            //             "isolatedShortLever" => 20,
            //             "marginMode" => "crossed",
            //             "posMode" => "hedge_mode",
            //             "unrealizedPL" => "0",
            //             "coupon" => "0",
            //             "crossedUnrealizedPL" => "0",
            //             "isolatedUnrealizedPL" => ""
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_margin_mode($data, $market);
        }) ();
    }

    public function parse_margin_mode(array $marginMode, $market = null): array {
        $marginType = $this->safe_string($marginMode, 'marginMode');
        $marginType = ($marginType === 'crossed') ? 'cross' : $marginType;
        return array(
            'info' => $marginMode,
            'symbol' => $market['symbol'],
            'marginMode' => $marginType,
        );
    }

    public function fetch_positions_history(?array $symbols = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $since, $limit, $params) {
            /**
             * fetches historical $positions
             *
             * @see https://www.bitget.com/api-doc/contract/position/Get-History-Position
             * @see https://www.bitget.com/api-doc/uta/trade/Get-Position-History
             *
             * @param {string[]} [$symbols] unified contract $symbols
             * @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
             * @param {int} [$limit] the maximum amount of records to fetch, default=20, max=100
             * @param {array} $params extra parameters specific to the exchange api endpoint
             * @param {int} [$params->until] timestamp in ms of the latest position to fetch, max range for $params["until"] - $since is 3 months
             * @param {string} [$params->productType] USDT-FUTURES (default), COIN-FUTURES, USDC-FUTURES, SUSDT-FUTURES, SCOIN-FUTURES, or SUSDC-FUTURES
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=position-structure position structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $market = null;
            $productType = null;
            $uta = null;
            $response = null;
            if ($symbols !== null) {
                $symbolsLength = count($symbols);
                if ($symbolsLength > 0) {
                    $market = $this->market($symbols[0]);
                    $request['symbol'] = $market['id'];
                }
            }
            if ($since !== null) {
                $request['startTime'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            list($request, $params) = $this->handle_until_option('endTime', $request, $params);
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchPositionsHistory', 'uta', false);
            if ($uta) {
                $request['category'] = $productType;
                $response = Async\await($this->privateUtaGetV3PositionHistoryPosition ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1751020950427,
                //         "data" => {
                //             "list" => array(
                //                 array(
                //                     "positionId" => "1322441328637100049",
                //                     "category" => "USDT-FUTURES",
                //                     "symbol" => "BTCUSDT",
                //                     "marginCoin" => "USDT",
                //                     "holdMode" => "hedge_mode",
                //                     "posSide" => "long",
                //                     "marginMode" => "crossed",
                //                     "openPriceAvg" => "107003.7",
                //                     "closePriceAvg" => "107005.4",
                //                     "openTotalPos" => "0.0001",
                //                     "closeTotalPos" => "0.0001",
                //                     "cumRealisedPnl" => "0.00017",
                //                     "netProfit" => "-0.01267055",
                //                     "totalFunding" => "0",
                //                     "openFeeTotal" => "-0.00642022",
                //                     "closeFeeTotal" => "-0.00642032",
                //                     "createdTime" => "1751020503195",
                //                     "updatedTime" => "1751020520458"
                //                 ),
                //             ),
                //             "cursor" => "1322440134158041089"
                //         }
                //     }
                //
            } else {
                $response = Async\await($this->privateMixGetV2MixPositionHistoryPosition ($this->extend($request, $params)));
                //
                //    {
                //        code => '00000',
                //        msg => 'success',
                //        requestTime => '1712794148791',
                //        $data => {
                //            list => array(
                //                array(
                //                    symbol => 'XRPUSDT',
                //                    marginCoin => 'USDT',
                //                    holdSide => 'long',
                //                    openAvgPrice => '0.64967',
                //                    closeAvgPrice => '0.58799',
                //                    marginMode => 'isolated',
                //                    openTotalPos => '10',
                //                    closeTotalPos => '10',
                //                    pnl => '-0.62976205',
                //                    netProfit => '-0.65356802',
                //                    totalFunding => '-0.01638',
                //                    openFee => '-0.00389802',
                //                    closeFee => '-0.00352794',
                //                    ctime => '1709590322199',
                //                    utime => '1709667583395'
                //                ),
                //                ...
                //            )
                //        }
                //    }
                //
            }
            $data = $this->safe_dict($response, 'data', array());
            $responseList = $this->safe_list($data, 'list', array());
            $positions = $this->parse_positions($responseList, $symbols, $params);
            return $this->filter_by_since_limit($positions, $since, $limit);
        }) ();
    }

    public function fetch_convert_quote(string $fromCode, string $toCode, ?float $amount = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($fromCode, $toCode, $amount, $params) {
            /**
             * fetch a quote for converting from one currency to another
             *
             * @see https://www.bitget.com/api-doc/common/convert/Get-Quoted-Price
             *
             * @param {string} $fromCode the currency that you want to sell and convert from
             * @param {string} $toCode the currency that you want to buy and convert into
             * @param {float} [$amount] how much you want to trade in units of the from currency
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=conversion-structure conversion structure~
             */
            Async\await($this->load_markets());
            $request = array(
                'fromCoin' => $fromCode,
                'toCoin' => $toCode,
                'fromCoinSize' => $this->number_to_string($amount),
            );
            $response = Async\await($this->privateConvertGetV2ConvertQuotedPrice ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1712121940158,
            //         "data" => {
            //             "fromCoin" => "USDT",
            //             "fromCoinSize" => "5",
            //             "cnvtPrice" => "0.9993007892377704",
            //             "toCoin" => "USDC",
            //             "toCoinSize" => "4.99650394",
            //             "traceId" => "1159288930228187140",
            //             "fee" => "0"
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $fromCurrencyId = $this->safe_string($data, 'fromCoin', $fromCode);
            $fromCurrency = $this->currency($fromCurrencyId);
            $toCurrencyId = $this->safe_string($data, 'toCoin', $toCode);
            $toCurrency = $this->currency($toCurrencyId);
            return $this->parse_conversion($data, $fromCurrency, $toCurrency);
        }) ();
    }

    public function create_convert_trade(string $id, string $fromCode, string $toCode, ?float $amount = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($id, $fromCode, $toCode, $amount, $params) {
            /**
             * convert from one currency to another
             *
             * @see https://www.bitget.com/api-doc/common/convert/Trade
             *
             * @param {string} $id the $id of the trade that you want to make
             * @param {string} $fromCode the currency that you want to sell and convert from
             * @param {string} $toCode the currency that you want to buy and convert into
             * @param {float} $amount how much you want to trade in units of the from currency
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} $params->price the $price of the conversion, obtained from fetchConvertQuote()
             * @param {string} $params->toAmount the $amount you want to trade in units of the $toCurrency, obtained from fetchConvertQuote()
             * @return {array} a ~@link https://docs.ccxt.com/#/?$id=conversion-structure conversion structure~
             */
            Async\await($this->load_markets());
            $price = $this->safe_string_2($params, 'price', 'cnvtPrice');
            if ($price === null) {
                throw new ArgumentsRequired($this->id . ' createConvertTrade() requires a $price parameter');
            }
            $toAmount = $this->safe_string_2($params, 'toAmount', 'toCoinSize');
            if ($toAmount === null) {
                throw new ArgumentsRequired($this->id . ' createConvertTrade() requires a $toAmount parameter');
            }
            $params = $this->omit($params, array( 'price', 'toAmount' ));
            $request = array(
                'traceId' => $id,
                'fromCoin' => $fromCode,
                'toCoin' => $toCode,
                'fromCoinSize' => $this->number_to_string($amount),
                'toCoinSize' => $toAmount,
                'cnvtPrice' => $price,
            );
            $response = Async\await($this->privateConvertPostV2ConvertTrade ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1712123746203,
            //         "data" => {
            //             "cnvtPrice" => "0.99940076",
            //             "toCoin" => "USDC",
            //             "toCoinSize" => "4.99700379",
            //             "ts" => "1712123746217"
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $toCurrencyId = $this->safe_string($data, 'toCoin', $toCode);
            $toCurrency = $this->currency($toCurrencyId);
            return $this->parse_conversion($data, null, $toCurrency);
        }) ();
    }

    public function fetch_convert_trade_history(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch the users history of conversion trades
             *
             * @see https://www.bitget.com/api-doc/common/convert/Get-Convert-Record
             *
             * @param {string} [$code] the unified currency $code
             * @param {int} [$since] the earliest time in ms to fetch conversions for
             * @param {int} [$limit] the maximum number of conversion structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=conversion-structure conversion structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $msInDay = 86400000;
            $now = $this->milliseconds();
            if ($since !== null) {
                $request['startTime'] = $since;
            } else {
                $request['startTime'] = $now - $msInDay;
            }
            $endTime = $this->safe_string_2($params, 'endTime', 'until');
            if ($endTime !== null) {
                $request['endTime'] = $endTime;
            } else {
                $request['endTime'] = $now;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $params = $this->omit($params, 'until');
            $response = Async\await($this->privateConvertGetV2ConvertConvertRecord ($this->extend($request, $params)));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1712124371799,
            //         "data" => {
            //             "dataList" => array(
            //                 {
            //                     "id" => "1159296505255219205",
            //                     "fromCoin" => "USDT",
            //                     "fromCoinSize" => "5",
            //                     "cnvtPrice" => "0.99940076",
            //                     "toCoin" => "USDC",
            //                     "toCoinSize" => "4.99700379",
            //                     "ts" => "1712123746217",
            //                     "fee" => "0"
            //                 }
            //             ),
            //             "endId" => "1159296505255219205"
            //         }
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $dataList = $this->safe_list($data, 'dataList', array());
            return $this->parse_conversions($dataList, $code, 'fromCoin', 'toCoin', $since, $limit);
        }) ();
    }

    public function parse_conversion(array $conversion, ?array $fromCurrency = null, ?array $toCurrency = null): array {
        //
        // fetchConvertQuote
        //
        //     {
        //         "fromCoin" => "USDT",
        //         "fromCoinSize" => "5",
        //         "cnvtPrice" => "0.9993007892377704",
        //         "toCoin" => "USDC",
        //         "toCoinSize" => "4.99650394",
        //         "traceId" => "1159288930228187140",
        //         "fee" => "0"
        //     }
        //
        // createConvertTrade
        //
        //     {
        //         "cnvtPrice" => "0.99940076",
        //         "toCoin" => "USDC",
        //         "toCoinSize" => "4.99700379",
        //         "ts" => "1712123746217"
        //     }
        //
        // fetchConvertTradeHistory
        //
        //     {
        //         "id" => "1159296505255219205",
        //         "fromCoin" => "USDT",
        //         "fromCoinSize" => "5",
        //         "cnvtPrice" => "0.99940076",
        //         "toCoin" => "USDC",
        //         "toCoinSize" => "4.99700379",
        //         "ts" => "1712123746217",
        //         "fee" => "0"
        //     }
        //
        $timestamp = $this->safe_integer($conversion, 'ts');
        $fromCoin = $this->safe_string($conversion, 'fromCoin');
        $fromCode = $this->safe_currency_code($fromCoin, $fromCurrency);
        $to = $this->safe_string($conversion, 'toCoin');
        $toCode = $this->safe_currency_code($to, $toCurrency);
        return array(
            'info' => $conversion,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'id' => $this->safe_string_2($conversion, 'id', 'traceId'),
            'fromCurrency' => $fromCode,
            'fromAmount' => $this->safe_number($conversion, 'fromCoinSize'),
            'toCurrency' => $toCode,
            'toAmount' => $this->safe_number($conversion, 'toCoinSize'),
            'price' => $this->safe_number($conversion, 'cnvtPrice'),
            'fee' => $this->safe_number($conversion, 'fee'),
        );
    }

    public function fetch_convert_currencies($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetches all available currencies that can be converted
             *
             * @see https://www.bitget.com/api-doc/common/convert/Get-Convert-Currencies
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an associative dictionary of currencies
             */
            Async\await($this->load_markets());
            $response = Async\await($this->privateConvertGetV2ConvertCurrencies ($params));
            //
            //     {
            //         "code" => "00000",
            //         "msg" => "success",
            //         "requestTime" => 1712121755897,
            //         "data" => array(
            //             array(
            //                 "coin" => "BTC",
            //                 "available" => "0.00009850",
            //                 "maxAmount" => "0.756266",
            //                 "minAmount" => "0.00001"
            //             ),
            //         )
            //     }
            //
            $result = array();
            $data = $this->safe_list($response, 'data', array());
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $id = $this->safe_string($entry, 'coin');
                $code = $this->safe_currency_code($id);
                $result[$code] = array(
                    'info' => $entry,
                    'id' => $id,
                    'code' => $code,
                    'networks' => null,
                    'type' => null,
                    'name' => null,
                    'active' => null,
                    'deposit' => null,
                    'withdraw' => $this->safe_number($entry, 'available'),
                    'fee' => null,
                    'precision' => null,
                    'limits' => array(
                        'amount' => array(
                            'min' => $this->safe_number($entry, 'minAmount'),
                            'max' => $this->safe_number($entry, 'maxAmount'),
                        ),
                        'withdraw' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'deposit' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'created' => null,
                );
            }
            return $result;
        }) ();
    }

    public function fetch_funding_interval(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the current funding rate interval
             *
             * @see https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
             * @see https://www.bitget.com/api-doc/uta/public/Get-Current-Funding-Rate
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->uta] set to true for the unified trading account ($uta), defaults to false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=funding-rate-structure funding rate structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $productType = null;
            list($productType, $params) = $this->handle_product_type_and_params($market, $params);
            $request = array(
                'symbol' => $market['id'],
            );
            $response = null;
            $uta = null;
            list($uta, $params) = $this->handle_option_and_params($params, 'fetchFundingInterval', 'uta', false);
            if ($uta) {
                $response = Async\await($this->publicUtaGetV3MarketCurrentFundRate ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1752880157959,
                //         "data" => array(
                //             {
                //                 "symbol" => "BTCUSDT",
                //                 "fundingRate" => "0.0001",
                //                 "fundingRateInterval" => "8",
                //                 "nextUpdate" => "1752883200000",
                //                 "minFundingRate" => "-0.003",
                //                 "maxFundingRate" => "0.003"
                //             }
                //         )
                //     }
                //
            } else {
                $request['productType'] = $productType;
                $response = Async\await($this->publicMixGetV2MixMarketFundingTime ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1727930153888,
                //         "data" => array(
                //             {
                //                 "symbol" => "BTCUSDT",
                //                 "nextFundingTime" => "1727942400000",
                //                 "ratePeriod" => "8"
                //             }
                //         )
                //     }
                //
            }
            $data = $this->safe_list($response, 'data', array());
            $first = $this->safe_dict($data, 0, array());
            return $this->parse_funding_rate($first, $market);
        }) ();
    }

    public function fetch_long_short_ratio_history(?string $symbol = null, ?string $timeframe = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $timeframe, $since, $limit, $params) {
            /**
             * fetches the long short ratio history for a unified $market $symbol
             *
             * @see https://www.bitget.com/api-doc/common/apidata/Margin-Ls-Ratio
             * @see https://www.bitget.com/api-doc/common/apidata/Account-Long-Short
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the long short ratio for
             * @param {string} [$timeframe] the period for the ratio
             * @param {int} [$since] the earliest time in ms to fetch ratios for
             * @param {int} [$limit] the maximum number of long short ratio structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} an array of ~@link https://docs.ccxt.com/#/?id=long-short-ratio-structure long short ratio structures~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'symbol' => $market['id'],
            );
            if ($timeframe !== null) {
                $request['period'] = $timeframe;
            }
            $response = null;
            if ($market['swap'] || $market['future']) {
                $response = Async\await($this->publicMixGetV2MixMarketAccountLongShort ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1729321233281,
                //         "data" => array(
                //             array(
                //                 "longAccountRatio" => "0.58",
                //                 "shortAccountRatio" => "0.42",
                //                 "longShortAccountRatio" => "0.0138",
                //                 "ts" => "1729312200000"
                //             ),
                //         )
                //     }
                //
            } else {
                $response = Async\await($this->publicMarginGetV2MarginMarketLongShortRatio ($this->extend($request, $params)));
                //
                //     {
                //         "code" => "00000",
                //         "msg" => "success",
                //         "requestTime" => 1729306974712,
                //         "data" => array(
                //             array(
                //                 "longShortRatio" => "40.66",
                //                 "ts" => "1729306800000"
                //             ),
                //         )
                //     }
                //
            }
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_long_short_ratio_history($data, $market);
        }) ();
    }

    public function parse_long_short_ratio(array $info, ?array $market = null): array {
        $marketId = $this->safe_string($info, 'symbol');
        $timestamp = $this->safe_integer_omit_zero($info, 'ts');
        return array(
            'info' => $info,
            'symbol' => $this->safe_symbol($marketId, $market, null, 'contract'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'timeframe' => null,
            'longShortRatio' => $this->safe_number_2($info, 'longShortRatio', 'longShortAccountRatio'),
        );
    }

    public function handle_errors(int $code, string $reason, string $url, string $method, array $headers, string $body, $response, $requestHeaders, $requestBody) {
        if (!$response) {
            return null; // fallback to default error handler
        }
        //
        // spot
        //
        //     array("code":"00000","msg":"success","requestTime":1713294492511,"data":[...])"
        //
        //     array("status":"fail","err_code":"01001","err_msg":"系统异常，请稍后重试")
        //     array("status":"error","ts":1595594160149,"err_code":"invalid-parameter","err_msg":"invalid size, valid range => [1,2000]")
        //     array("status":"error","ts":1595684716042,"err_code":"invalid-parameter","err_msg":"illegal sign invalid")
        //     array("status":"error","ts":1595700216275,"err_code":"bad-request","err_msg":"your balance is low!")
        //     array("status":"error","ts":1595700344504,"err_code":"invalid-parameter","err_msg":"invalid type")
        //     array("status":"error","ts":1595703343035,"err_code":"bad-request","err_msg":"order cancel fail")
        //     array("status":"error","ts":1595704360508,"err_code":"invalid-parameter","err_msg":"accesskey not null")
        //     array("status":"error","ts":1595704490084,"err_code":"invalid-parameter","err_msg":"permissions not right")
        //     array("status":"error","ts":1595711862763,"err_code":"system exception","err_msg":"system exception")
        //     array("status":"error","ts":1595730308979,"err_code":"bad-request","err_msg":"20003")
        //
        // swap
        //
        //     array("code":"40015","msg":"","requestTime":1595698564931,"data":null)
        //     array("code":"40017","msg":"Order id must not be blank","requestTime":1595702477835,"data":null)
        //     array("code":"40017","msg":"Order Type must not be blank","requestTime":1595698516162,"data":null)
        //     array("code":"40301","msg":"","requestTime":1595667662503,"data":null)
        //     array("code":"40017","msg":"Contract $code must not be blank","requestTime":1595703151651,"data":null)
        //     array("code":"40108","msg":"","requestTime":1595885064600,"data":null)
        //     array("order_id":"513468410013679613","client_oid":null,"symbol":"ethusd","result":false,"err_code":"order_no_exist_error","err_msg":"订单不存在！")
        //
        $message = $this->safe_string_2($response, 'err_msg', 'msg');
        $feedback = $this->id . ' ' . $body;
        $nonEmptyMessage = (($message !== null) && ($message !== '') && ($message !== 'success'));
        if ($nonEmptyMessage) {
            $this->throw_exactly_matched_exception($this->exceptions['exact'], $message, $feedback);
            $this->throw_broadly_matched_exception($this->exceptions['broad'], $message, $feedback);
        }
        $errorCode = $this->safe_string_2($response, 'code', 'err_code');
        $nonZeroErrorCode = ($errorCode !== null) && ($errorCode !== '00000');
        if ($nonZeroErrorCode) {
            $this->throw_exactly_matched_exception($this->exceptions['exact'], $errorCode, $feedback);
        }
        if ($nonZeroErrorCode || $nonEmptyMessage) {
            throw new ExchangeError($feedback); // unknown $message
        }
        return null;
    }

    public function nonce() {
        return $this->milliseconds() - $this->options['timeDifference'];
    }

    public function sign($path, $api = [], $method = 'GET', $params = array (), $headers = null, $body = null) {
        $signed = $api[0] === 'private';
        $endpoint = $api[1];
        $pathPart = '/api';
        $request = '/' . $this->implode_params($path, $params);
        $payload = $pathPart . $request;
        $url = $this->implode_hostname($this->urls['api'][$endpoint]) . $payload;
        $query = $this->omit($params, $this->extract_params($path));
        if (!$signed && ($method === 'GET')) {
            $keys = is_array($query) ? array_keys($query) : array();
            $keysLength = count($keys);
            if ($keysLength > 0) {
                $url = $url . '?' . $this->urlencode($query);
            }
        }
        if ($signed) {
            $this->check_required_credentials();
            $timestamp = (string) $this->nonce();
            $auth = $timestamp . $method . $payload;
            if ($method === 'POST') {
                $body = $this->json($params);
                $auth .= $body;
            } else {
                if ($params) {
                    $queryInner = '?' . $this->urlencode($this->keysort($params));
                    // check #21169 pr
                    if (mb_strpos($queryInner, '%24') > -1) {
                        $queryInner = str_replace('%24', '$', $queryInner);
                    }
                    $url .= $queryInner;
                    $auth .= $queryInner;
                }
            }
            $signature = $this->hmac($this->encode($auth), $this->encode($this->secret), 'sha256', 'base64');
            $broker = $this->safe_string($this->options, 'broker');
            $headers = array(
                'ACCESS-KEY' => $this->apiKey,
                'ACCESS-SIGN' => $signature,
                'ACCESS-TIMESTAMP' => $timestamp,
                'ACCESS-PASSPHRASE' => $this->password,
                'X-CHANNEL-API-CODE' => $broker,
            );
            if ($method === 'POST') {
                $headers['Content-Type'] = 'application/json';
            }
        }
        $sandboxMode = $this->safe_bool_2($this->options, 'sandboxMode', 'sandbox', false);
        if ($sandboxMode && ($path !== 'v2/public/time') && ($path !== 'v3/market/current-fund-rate')) {
            // https://github.com/ccxt/ccxt/issues/25252#issuecomment-2662742336
            if ($headers === null) {
                $headers = array();
            }
            $productType = $this->safe_string($params, 'productType');
            if (($productType !== 'SCOIN-FUTURES') && ($productType !== 'SUSDT-FUTURES') && ($productType !== 'SUSDC-FUTURES')) {
                $headers['PAPTRADING'] = '1';
            }
        }
        return array( 'url' => $url, 'method' => $method, 'body' => $body, 'headers' => $headers );
    }
}
