astro-perp-ccxt-dev
Version:
9,506 lines • 457 kB
JavaScript
'use strict';
var bitget$1 = require('./abstract/bitget.js');
var errors = require('./base/errors.js');
var Precise = require('./base/Precise.js');
var number = require('./base/functions/number.js');
var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
// ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
* @class bitget
* @augments Exchange
*/
class bitget extends bitget$1 {
describe() {
return this.deepExtend(super.describe(), {
'id': 'bitget',
'name': 'Bitget',
'countries': ['SG'],
'version': 'v2',
'rateLimit': 50,
'certified': true,
'pro': true,
'has': {
'CORS': undefined,
'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': {
'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': {
'logo': 'https://github.com/user-attachments/assets/fbaa10cc-a277-441d-a5b7-997dd9a87658',
'api': {
'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': [
'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': {
'public': {
'common': {
'get': {
'v2/public/annoucements': 1,
'v2/public/time': 1,
},
},
'spot': {
'get': {
'spot/v1/notice/queryAllNotices': 1,
'spot/v1/public/time': 1,
'spot/v1/public/currencies': 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,
'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,
'spot/v1/public/loan/hour-interest': 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': {
'get': {
'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': {
'get': {
'margin/v1/cross/public/interestRateAndLimit': 2,
'margin/v1/isolated/public/interestRateAndLimit': 2,
'margin/v1/cross/public/tierData': 2,
'margin/v1/isolated/public/tierData': 2,
'margin/v1/public/currencies': 1,
'v2/margin/currencies': 2,
'v2/margin/market/long-short-ratio': 20,
},
},
'earn': {
'get': {
'v2/earn/loan/public/coinInfos': 2,
'v2/earn/loan/public/hour-interest': 2,
},
},
'uta': {
'get': {
'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': {
'spot': {
'get': {
'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,
'spot/v1/account/transferRecords': 1,
'spot/v1/convert/currencies': 2,
'spot/v1/convert/convert-record': 2,
'spot/v1/loan/ongoing-orders': 2,
'spot/v1/loan/repay-history': 2,
'spot/v1/loan/revise-history': 2,
'spot/v1/loan/borrow-history': 2,
'spot/v1/loan/debts': 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': {
'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,
'spot/v1/convert/quoted-price': 4,
'spot/v1/convert/trade': 4,
'spot/v1/loan/borrow': 2,
'spot/v1/loan/repay': 2,
'spot/v1/loan/revise-pledge': 2,
'spot/v1/trace/order/orderCurrentList': 2,
'spot/v1/trace/order/orderHistoryList': 2,
'spot/v1/trace/order/closeTrackingOrder': 2,
'spot/v1/trace/order/updateTpsl': 2,
'spot/v1/trace/order/followerEndOrder': 2,
'spot/v1/trace/order/spotInfoList': 2,
'spot/v1/trace/config/getTraderSettings': 2,
'spot/v1/trace/config/getFollowerSettings': 2,
'spot/v1/trace/user/myTraders': 2,
'spot/v1/trace/config/setFollowerConfig': 2,
'spot/v1/trace/user/myFollowers': 2,
'spot/v1/trace/config/setProductCode': 2,
'spot/v1/trace/user/removeTrader': 2,
'spot/v1/trace/getRemovableFollower': 2,
'spot/v1/trace/user/removeFollower': 2,
'spot/v1/trace/profit/totalProfitInfo': 2,
'spot/v1/trace/profit/totalProfitList': 2,
'spot/v1/trace/profit/profitHisList': 2,
'spot/v1/trace/profit/profitHisDetailList': 2,
'spot/v1/trace/profit/waitProfitDetailList': 2,
'spot/v1/trace/user/getTraderInfo': 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': {
'get': {
'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,
'mix/v1/position/allPosition-v2': 4,
'mix/v1/position/history-position': 1,
'mix/v1/account/accountBill': 2,
'mix/v1/account/accountBusinessBill': 4,
'mix/v1/order/current': 1,
'mix/v1/order/marginCoinCurrent': 1,
'mix/v1/order/history': 2,
'mix/v1/order/historyProductType': 4,
'mix/v1/order/detail': 2,
'mix/v1/order/fills': 2,
'mix/v1/order/allFills': 2,
'mix/v1/plan/currentPlan': 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,
'mix/v1/trace/profitSettleTokenIdGroup': 1,
'mix/v1/trace/profitDateGroupList': 1,
'mix/v1/trade/profitDateList': 2,
'mix/v1/trace/waitProfitDateList': 1,
'mix/v1/trace/traderSymbols': 1,
'mix/v1/trace/traderList': 2,
'mix/v1/trace/traderDetail': 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': {
'mix/v1/account/sub-account-contract-assets': 200,
'mix/v1/account/open-count': 1,
'mix/v1/account/setLeverage': 4,
'mix/v1/account/setMargin': 4,
'mix/v1/account/setMarginMode': 4,
'mix/v1/account/setPositionMode': 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,
'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,
'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,
'mix/v1/trace/traderUpdateConfig': 2,
'mix/v1/trace/myTraderList': 2,
'mix/v1/trace/myFollowerList': 2,
'mix/v1/trace/removeFollower': 2,
'mix/v1/trace/public/getFollowerConfig': 2,
'mix/v1/trace/report/order/historyList': 2,
'mix/v1/trace/report/order/currentList': 2,
'mix/v1/trace/queryTraderTpslRatioConfig': 2,
'mix/v1/trace/traderUpdateTpslRatioConfig': 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': {
'get': {
'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': {
'user/v1/sub/virtual-create': 4,
'user/v1/sub/virtual-modify': 4,
'user/v1/sub/virtual-api-batch-create': 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': {
'get': {
'p2p/v1/merchant/merchantList': 2,
'p2p/v1/merchant/merchantInfo': 2,
'p2p/v1/merchant/advList': 2,
'p2p/v1/merchant/orderList': 2,
'v2/p2p/merchantList': 2,
'v2/p2p/merchantInfo': 2,
'v2/p2p/orderList': 2,
'v2/p2p/advList': 2,
},
},
'broker': {
'get': {
'broker/v1/account/info': 2,
'broker/v1/account/sub-list': 20,
'broker/v1/account/sub-email': 20,
'broker/v1/account/sub-spot-assets': 2,
'broker/v1/account/sub-future-assets': 2,
'broker/v1/account/subaccount-transfer': 1,
'broker/v1/account/subaccount-deposit': 1,
'broker/v1/account/subaccount-withdrawal': 1,
'broker/v1/account/sub-api-list': 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': {
'broker/v1/account/sub-create': 20,
'broker/v1/account/sub-modify': 20,
'broker/v1/account/sub-modify-email': 20,
'broker/v1/account/sub-address': 2,
'broker/v1/account/sub-withdrawal': 2,
'broker/v1/account/sub-auto-transfer': 4,
'broker/v1/account/sub-api-create': 2,
'broker/v1/account/sub-api-modify': 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': {
'get': {
'margin/v1/cross/account/riskRate': 2,
'margin/v1/cross/account/maxTransferOutAmount': 2,
'margin/v1/isolated/account/maxTransferOutAmount': 2,
'margin/v1/isolated/order/openOrders': 2,
'margin/v1/isolated/order/history': 2,
'margin/v1/isolated/order/fills': 2,
'margin/v1/isolated/loan/list': 2,
'margin/v1/isolated/repay/list': 2,
'margin/v1/isolated/interest/list': 2,
'margin/v1/isolated/liquidation/list': 2,
'margin/v1/isolated/fin/list': 2,
'margin/v1/cross/order/openOrders': 2,
'margin/v1/cross/order/history': 2,
'margin/v1/cross/order/fills': 2,
'margin/v1/cross/loan/list': 2,
'margin/v1/cross/repay/list': 2,
'margin/v1/cross/interest/list': 2,
'margin/v1/cross/liquidation/list': 2,
'margin/v1/cross/fin/list': 2,
'margin/v1/cross/account/assets': 2,
'margin/v1/isolated/account/assets': 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': {
'margin/v1/cross/account/borrow': 2,
'margin/v1/isolated/account/borrow': 2,
'margin/v1/cross/account/repay': 2,
'margin/v1/isolated/account/repay': 2,
'margin/v1/isolated/account/riskRate': 2,
'margin/v1/cross/account/maxBorrowableAmount': 2,
'margin/v1/isolated/account/maxBorrowableAmount': 2,
'margin/v1/isolated/account/flashRepay': 2,
'margin/v1/isolated/account/queryFlashRepayStatus': 2,
'margin/v1/cross/account/flashRepay': 2,
'margin/v1/cross/account/queryFlashRepayStatus': 2,
'margin/v1/isolated/order/placeOrder': 4,
'margin/v1/isolated/order/batchPlaceOrder': 4,
'margin/v1/isolated/order/cancelOrder': 2,
'margin/v1/isolated/order/batchCancelOrder': 2,
'margin/v1/cross/order/placeOrder': 2,
'margin/v1/cross/order/batchPlaceOrder': 2,
'margin/v1/cross/order/cancelOrder': 2,
'margin/v1/cross/order/batchCancelOrder': 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': {
'get': {
'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': {
'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': {
'get': {
'v2/tax/spot-record': 20,
'v2/tax/future-record': 20,
'v2/tax/margin-record': 20,
'v2/tax/p2p-record': 20,
},
},
'convert': {
'get': {
'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': {
'v2/convert/trade': 2,
'v2/convert/bgb-convert': 2,
},
},
'earn': {
'get': {
'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': {
'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': {
'get': {
'v2/common/trade-rate': 2,
},
},
'uta': {
'get': {
'v3/account/assets': 1,
'v3/account/settings': 1,
'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/history-orders': 1,
'v3/trade/fills': 1,
'v3/user/sub-list': 2,
'v3/user/sub-api-list': 2,
},
'post': {
'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/modify-order': 2,
'v3/trade/cancel-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': {
'spot': {
'taker': this.parseNumber('0.002'),
'maker': this.parseNumber('0.002'),
},
'swap': {
'taker': this.parseNumber('0.0006'),
'maker': this.parseNumber('0.0004'),
},
},
'requiredCredentials': {
'apiKey': true,
'secret': true,
'password': true,
},
'exceptions': {
// 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': {
'1': errors.ExchangeError,
// undocumented
'failure to get a peer from the ring-balancer': errors.ExchangeNotAvailable,
'4010': errors.PermissionDenied,
// common
// '0': ExchangeError, // 200 successful,when the order placement / cancellation / operation is successful
'4001': errors.ExchangeError,
'4002': errors.ExchangeError,
// --------------------------------------------------------
'30001': errors.AuthenticationError,
'30002': errors.AuthenticationError,
'30003': errors.AuthenticationError,
'30004': errors.AuthenticationError,
'30005': errors.InvalidNonce,
'30006': errors.AuthenticationError,
'30007': errors.BadRequest,
'30008': errors.RequestTimeout,
'30009': errors.ExchangeError,
'30010': errors.AuthenticationError,
'30011': errors.PermissionDenied,
'30012': errors.AuthenticationError,
'30013': errors.AuthenticationError,
'30014': errors.DDoSProtection,
'30015': errors.AuthenticationError,
'30016': errors.ExchangeError,
'30017': errors.ExchangeError,
'30018': errors.ExchangeError,
'30019': errors.ExchangeNotAvailable,
'30020': errors.BadRequest,
'30021': errors.BadRequest,
'30022': errors.PermissionDenied,
'30023': errors.BadRequest,
'30024': errors.BadSymbol,
'30025': errors.BadRequest,
'30026': errors.DDoSProtection,
'30027': errors.AuthenticationError,
'30028': errors.PermissionDenied,
'30029': errors.AccountSuspended,
'30030': errors.ExchangeError,
'30031': errors.BadRequest,
'30032': errors.BadSymbol,
'30033': errors.BadRequest,
'30034': errors.ExchangeError,
'30035': errors.ExchangeError,
'30036': errors.ExchangeError,
'30037': errors.ExchangeNotAvailable,
// '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
'30038': errors.OnMaintenance,
// futures
'32001': errors.AccountSuspended,
'32002': errors.PermissionDenied,
'32003': errors.CancelPending,
'32004': errors.ExchangeError,
'32005': errors.InvalidOrder,
'32006': errors.InvalidOrder,
'32007': errors.InvalidOrder,
'32008': errors.InvalidOrder,
'32009': errors.InvalidOrder,
'32010': errors.ExchangeError,
'32011': errors.ExchangeError,
'32012': errors.ExchangeError,
'32013': errors.ExchangeError,
'32014': errors.ExchangeError,
'32015': errors.ExchangeError,
'32016': errors.ExchangeError,
'32017': errors.ExchangeError,
'32018': errors.ExchangeError,
'32019': errors.ExchangeError,
'32020': errors.ExchangeError,
'32021': errors.ExchangeError,
'32022': errors.ExchangeError,
'32023': errors.ExchangeError,
'32024': errors.ExchangeError,
'32025': errors.ExchangeError,
'32026': errors.ExchangeError,
'32027': errors.ExchangeError,
'32028': errors.AccountSuspended,
'32029': errors.ExchangeError,
'32030': errors.InvalidOrder,
'32031': errors.ArgumentsRequired,
'32038': errors.AuthenticationError,
'32040': errors.ExchangeError,
'32044': errors.ExchangeError,
'32045': errors.ExchangeError,
'32046': errors.ExchangeError,
'32047': errors.ExchangeError,
'32048': errors.InvalidOrder,
'32049': errors.ExchangeError,
'32050': errors.InvalidOrder,
'32051': errors.InvalidOrder,
'32052': errors.ExchangeError,
'32053': errors.ExchangeError,
'32057': errors.ExchangeError,
'32054': errors.ExchangeError,
'32055': errors.InvalidOrder,
'32056': errors.ExchangeError,
'32058': errors.ExchangeError,
'32059': errors.InvalidOrder,
'32060': errors.InvalidOrder,
'32061': errors.InvalidOrder,
'32062': errors.InvalidOrder,
'32063': errors.InvalidOrder,
'32064': errors.ExchangeError,
'32065': errors.ExchangeError,
'32066': errors.ExchangeError,
'32067': errors.ExchangeError,
'32068': errors.ExchangeError,
'32069': errors.ExchangeError,
'32070': errors.ExchangeError,
'32071': errors.ExchangeError,
'32072': errors.ExchangeError,
'32073': errors.ExchangeError,
'32074': errors.ExchangeError,
'32075': errors.ExchangeError,
'32076': errors.ExchangeError,
'32077': errors.ExchangeError,
'32078': errors.ExchangeError,
'32079': errors.ExchangeError,
'32080': errors.ExchangeError,
'32083': errors.ExchangeError,
// token and margin trading
'33001': errors.PermissionDenied,
'33002': errors.AccountSuspended,
'33003': errors.InsufficientFunds,
'33004': errors.ExchangeError,
'33005': errors.ExchangeError,
'33006': errors.ExchangeError,
'33007': errors.ExchangeError,
'33008': errors.InsufficientFunds,
'33009': errors.ExchangeError,
'33010': errors.ExchangeError,
'33011': errors.ExchangeError,
'33012': errors.ExchangeError,
'33013': errors.InvalidOrder,
'33014': errors.OrderNotFound,
'33015': errors.InvalidOrder,
'33016': errors.ExchangeError,
'33017': errors.InsufficientFunds,
'33018': errors.ExchangeError,
'33020': errors.ExchangeError,
'33021': errors.BadRequest,
'33022': errors.InvalidOrder,
'33023': errors.ExchangeError,
'33024': errors.InvalidOrder,
'33025': errors.InvalidOrder,
'33026': errors.ExchangeError,
'33027': errors.InvalidOrder,
'33028': errors.InvalidOrder,
'33029': errors.InvalidOrder,
'33034': errors.ExchangeError,
'33035': errors.ExchangeError,
'33036': errors.ExchangeError,
'33037': errors.ExchangeError,
'33038': errors.ExchangeError,
'33039': errors.ExchangeError,
'33040': errors.ExchangeError,
'33041': errors.ExchangeError,
'33042': errors.ExchangeError,
'33043': errors.ExchangeError,
'33044': errors.ExchangeError,
'33045': errors.ExchangeError,
'33046': errors.ExchangeError,
'33047': errors.ExchangeError,
'33048': errors.ExchangeError,
'33049': errors.ExchangeError,
'33050': errors.ExchangeError,
'33051': errors.ExchangeError,
'33059': errors.BadRequest,
'33060': errors.BadRequest,
'33061': errors.ExchangeError,
'33062': errors.ExchangeError,
'33063': errors.ExchangeError,
'33064': errors.ExchangeError,
'33065': errors.ExchangeError,
// account
'21009': errors.ExchangeError,
'34001': errors.PermissionDenied,
'34002': errors.InvalidAddress,
'34003': errors.ExchangeError,
'34004': errors.ExchangeError,
'34005': errors.ExchangeError,
'34006': errors.ExchangeError,
'34007': errors.ExchangeError,
'34008': errors.InsufficientFunds,
'34009': errors.ExchangeError,
'34010': errors.ExchangeError,
'34011': errors.ExchangeError,
'34012': errors.ExchangeError,
'34013': errors.ExchangeError,
'34014': errors.ExchangeError,
'34015': errors.ExchangeError,
'34016': errors.PermissionDenied,
'34017': errors.AccountSuspended,
'34018': errors.AuthenticationError,
'34019': errors.PermissionDenied,
'34020': errors.PermissionDenied,
'34021': errors.InvalidAddress,
'34022': errors.ExchangeError,
'34023': errors.PermissionDenied,
'34026': errors.ExchangeError,
'34036': errors.ExchangeError,
'34037': errors.ExchangeError,
'34038': errors.ExchangeError,
'34039': errors.ExchangeError,
// swap
'35001': errors.ExchangeError,
'35002': errors.ExchangeError,
'35003': errors.ExchangeError,
'35004': errors.ExchangeError,
'35005': errors.AuthenticationError,
'35008': errors.InvalidOrder,
'35010': errors.InvalidOrder,
'35012': errors.InvalidOrder,
'35014': errors.InvalidOrder,
'35015': errors.InvalidOrder,
'35017': errors.ExchangeError,
'35019': errors.InvalidOrder,
'35020': errors.InvalidOrder,
'35021': errors.InvalidOrder,
'35022': errors.ExchangeError,
'35024': errors.ExchangeError,
'35025': errors.InsufficientFunds,
'35026': errors.ExchangeError,
'35029': errors.OrderNotFound,
'35030': errors.InvalidOrder,
'35031': errors.InvalidOrder,
'35032': errors.ExchangeError,
'35037': errors.ExchangeError,
'35039': errors.ExchangeError,
'35040': errors.InvalidOrder,
'35044': errors.ExchangeError,
'35046': errors.InsufficientFunds,
'35047': errors.InsufficientFunds,
'35048': errors.ExchangeError,
'35049': errors.InvalidOrder,
'35050': errors.InvalidOrder,
'35052': errors.InsufficientFunds,
'35053': errors.ExchangeError,
'35055': errors.InsufficientFunds,
'35057': errors.ExchangeError,
'35058': errors.ExchangeError,
'35059': errors.BadRequest,
'35060': errors.BadRequest,
'35061': errors.BadRequest,
'35062': errors.InvalidOrder,
'35063': errors.InvalidOrder,
'35064': errors.InvalidOrder,
'35066': errors.InvalidOrder,
'35067': errors.InvalidOrder,
'35068': errors.InvalidOrder,
'35069': errors.InvalidOrder,
'35070': errors.InvalidOrder,
'35071': errors.InvalidOrder,
'35072': errors.InvalidOrder,
'35073': errors.InvalidOrder,
'35074': errors.InvalidOrder,
'35075': errors.InvalidOrder,
'35076': errors.InvalidOrder,
'35077': errors.InvalidOrder,
'35078': errors.InvalidOrder,
'35079': errors.InvalidOrder,
'35080': errors.InvalidOrder,
'35081': errors.InvalidOrder,
'35082': errors.InvalidOrder,
'35083': errors.InvalidOrder,
'35084': errors.InvalidOrder,
'35085': errors.InvalidOrder,
'35086': errors.InvalidOrder,
'35087': errors.InvalidOrder,
'35088': errors.InvalidOrder,
'35089': errors.InvalidOrder,
'35090': errors.ExchangeError,
'35091': errors.ExchangeError,
'35092': errors.ExchangeError,
'35093': errors.ExchangeError,
'35094': errors.ExchangeError,
'35095': errors.BadRequest,
'35096': errors.ExchangeError,
'35097': errors.ExchangeError,
'35098': errors.ExchangeError,
'35099': errors.ExchangeError,
// option
'36001': errors.BadRequest,
'36002': errors.BadRequest,
'36005': errors.ExchangeError,
'36101': errors.AuthenticationError,
'36102': errors.PermissionDenied,
'36103': errors.AccountSuspended,
'36104': errors.PermissionDenied,
'36105': errors.PermissionDenied,
'36106': errors.AccountSuspended,
'36107': errors.PermissionDenied,
'36108': errors.InsufficientFunds,
'36109': errors.PermissionDenied,
'36201': errors.PermissionDenied,
'36202': errors.PermissionDenied,
'36203': errors.InvalidOrder,
'36204': errors.ExchangeError,
'36205': errors.BadRequest,
'36206': errors.BadRequest,
'36207': errors.InvalidOrder,
'36208': errors.InvalidOrder,
'36209': errors.InvalidOrder,
'36210': errors.InvalidOrder,
'36211': errors.InvalidOrder,
'36212': errors.InvalidOrder,
'36213': errors.InvalidOrder,
'36214': errors.ExchangeError,
'36216': errors.OrderNotFound,
'36217': errors.InvalidOrder,
'36218': errors.InvalidOrder,
'36219': errors.InvalidOrder,
'36220': errors.InvalidOrder,
'36221': errors.InvalidOrder,
'36222': errors.InvalidOrder,
'36223': errors.InvalidOrder,
'36224': errors.InvalidOrder,
'36225': errors.InvalidOrder,
'36226': errors.InvalidOrder,
'36227': errors.InvalidOrder,
'36228': errors.InvalidOrder,
'36229': errors.InvalidOrder,
'36230': errors.InvalidOrder,
// --------------------------------------------------------
// swap
'400': errors.BadRequest,
'401': errors.AuthenticationError,
'403': errors.PermissionDenied,
'404': errors.BadRequest,
'405': errors.BadRequest,
'415': errors.BadRequest,
'429': errors.DDoSProtection,
'500': errors.ExchangeNotAvailable,
'1001': errors.RateLimitExceeded,
'1002': errors.ExchangeError,
'1003': errors.ExchangeError,
// '00000': ExchangeError, // success
'40001': errors.AuthenticationError,
'40002': errors.AuthenticationError,
'40003': errors.AuthenticationError,
'40004': errors.InvalidNonce,
'40005': errors.InvalidNonce,
'40006': errors.AuthenticationError,
'40007': errors.BadRequest,
'40008': errors.InvalidNonce,
'40009': errors.AuthenticationError,
'40010': errors.AuthenticationError,
'40011': errors.AuthenticationError,
'40012': errors.AuthenticationError,
'40013': errors.ExchangeError,
'40014': errors.PermissionDenied,
'40015': errors.ExchangeError,
'40016': errors.PermissionDenied,
'40017': errors.ExchangeError,
'40018': errors.PermissionDenied,
'40019': errors.BadRequest,
'40031': errors.AccountSuspended,
'40037': errors.AuthenticationError,
'40102': errors.BadRequest,
'40103': errors.BadRequest,
'40104': errors.ExchangeError,
'40105': errors.ExchangeError,
'40106': errors.ExchangeError,
'40107': errors.ExchangeError,
'40108': errors.InvalidOrder,
'40109': errors.OrderNotFound,
'40200': errors.OnMaintenance,
'40201': errors.InvalidOrder,
'40202': errors.ExchangeError,
'40203': errors.BadRequest,
'40204': errors.BadRequest,
'40205': errors.BadRequest,
'40206': errors.BadRequest,
'40207': errors.BadRequest,
'40208': errors.BadRequest,
'40209': errors.BadRequest,
'40300': errors.ExchangeError,
'40301': errors.PermissionDenied,
'40302': errors.BadRequest,
'40303': errors.BadRequest,
'40304': errors.BadRequest,
'40305': errors.BadRequest,
'40306': errors.ExchangeError,
'40308': errors.OnMaintenance,
'40309': errors.BadSymbol,
'40400': errors.ExchangeError,
'40401': errors.ExchangeError,
'40402': errors.BadRequest,
'40403': errors.BadRequest,
'40404': errors.BadRequest,
'40405': errors.BadRequest,
'40406': errors.BadRequest,
'40407': errors.ExchangeError,
'40408': errors.ExchangeError,
'40409': errors.ExchangeError,
'40500': errors.InvalidOrder,
'40501': errors.ExchangeError,
'40502': errors.ExchangeError,
'40503': errors.ExchangeError,
'40504': errors.ExchangeError,
'40505': errors.ExchangeError,
'40506': errors.AuthenticationError,
'40507': errors.AuthenticationError,
'40508': errors.ExchangeError,
'40509': errors.ExchangeError,
'40600': errors.ExchangeError,
'40601': errors.ExchangeError,
'40602': errors.ExchangeError,
'40603': errors.ExchangeError,
'40604': errors.ExchangeNotAvailable,
'40605': errors.ExchangeError,
'40606': errors.ExchangeError,
'40607': errors.ExchangeError,
'40608': errors.ExchangeError,
'40609': errors.ExchangeError,
'40700': errors.BadRequest,
'40701': errors.ExchangeError,
'40702': errors.ExchangeError,
'40703': errors.ExchangeError,
'40704': errors.ExchangeError,
'40705': errors.BadRequest,
'40706': errors.InvalidOrder,
'40707': errors.BadRequest,
'40708': errors.BadRequest,
'40709': errors.ExchangeError,
'40710': errors.ExchangeError,
'40711': errors.InsufficientFunds,
'40712': errors.InsufficientFunds,
'40713': errors.ExchangeError,
'40714': errors.ExchangeError,
'40762': errors.InsufficientFunds,
'40768': errors.OrderNotFound,
'40808': errors.InvalidOrder,
'41103': errors.InvalidOrder,
'41114': errors.OnMaintenance,
'43011': errors.InvalidOrder,
'43001': errors.OrderNotFound,
'43012': errors.InsufficientFunds,
'43025': errors.InvalidOrder,
'43115': errors.OnMaintenance,
'45110': errors.InvalidOrder,
// spot
'invalid sign': errors.AuthenticationError,
'invalid currency': errors.BadSymbol,
'invalid symbol': errors.BadSymbol,
'invalid period': errors.BadRequest,
'invalid user': errors.ExchangeError,
'invalid amount': errors.InvalidOrder,
'invalid type': errors.InvalidOrder,
'invalid orderId': errors.InvalidOrder,
'invalid record': errors.ExchangeError,
'invalid accountId': errors.BadRequest,
'invalid address': errors.BadRequest,
'accesskey not null': errors.AuthenticationError,
'illegal accesskey': errors.AuthenticationError,
'sign not null': errors.AuthenticationError,
'req_time is too much difference from server time': errors.InvalidNonce,
'permissions not right': errors.PermissionDenied,
'illegal sign invalid': errors.AuthenticationError,
'user locked': errors.AccountSuspended,
'Request Frequency Is Too High': errors.RateLimitExceeded,
'more than a daily rate of cash': errors.BadRequest,
'more than the maximum daily withdrawal amount': errors.BadRequest,
'need to bind email or mobile': errors.ExchangeError,
'user forbid': errors.PermissionDenied,
'User Prohibited Cash Withdrawal': errors.PermissionDenied,
'Cash Withdrawal Is Less Than The Minimum Value': errors.BadRequest,
'Cash Withdrawal Is More Than The Maximum Value': errors.BadRequest,
'the account with in 24 hours ban coin': errors.PermissionDenied,
'order cancel fail': errors.BadRequest,
'base symbol error': errors.BadSymbol,
'base date error': errors.ExchangeError,
'api signature not valid': errors.AuthenticationError,
'gateway internal error': errors.ExchangeError,
'audit failed': errors.ExchangeError,
'order queryorder invalid': errors.BadRequest,
'market no need price': errors.InvalidOrder,
'limit need price': errors.InvalidOrder,
'userid not equal to account_id': errors.ExchangeError,
'your balance is low': errors.InsufficientFunds,
'address invalid cointype': errors.ExchangeError,
'system exception': errors.ExchangeError,
'50003': errors.ExchangeError,
'50004': errors.BadSymbol,
'50006': errors.PermissionDenied,
'50007': errors.PermissionDenied,
'50008': errors.RequestTimeout,
'50009': errors.RateLimitExceeded,
'50010': errors.ExchangeError,
'50014': errors.InvalidOrder,
'50015': errors.InvalidOrder,
'50016': errors.InvalidOrder,
'50017': errors.InvalidOrder,
'50018': errors.InvalidOrder,
'50019': errors.InvalidOrder,
'50020': errors.InsufficientFunds,
'50021': errors.InvalidOrder,
'50026': errors.InvalidOrder,
'invalid order query time': errors.ExchangeError,
'invalid start time': errors.BadRequest,
'invalid end time': errors.BadRequest,
'20003': errors.ExchangeError,
'01001': errors.ExchangeError,
'43111': errors.PermissionDenied, // {"code":"43111","msg":"参数错误 address not in address book","requestTime":1665394201164,"data":null}
},
'broad': {
'invalid size, valid range': errors.ExchangeError,
},
},
'precisionMode': number.TICK_SIZE,
'commonCurrencies': {
'APX': 'AstroPepeX',
'DEGEN': 'DegenReborn',
'JADE': 'Jade Protocol',
'OMNI': 'omni',
'TONCOIN': 'TON',
},
'options': {
'uta': false,
'timeDifference': 0,
'adjustForTimeDifference': false,
'timeframes': {
'spot': {
'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': {
'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',
},
},
'fetchMarkets': {
'types': ['spot', 'swap'], // there is future markets but they use the same endpoints as swap
},
'defaultType': 'spot',
'defaultSubType': 'linear',
'createMarketBuyOrderRequiresPrice': true,
'broker': 'p4sve',
'withdraw': {
'fillResponseFromRequest': true,
},
'fetchOHLCV': {
// ### 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': {
'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': {
'maxLimitPerTimeframe': {
'1d': 300,
'3d': 100,
'1w': 100,
'1M': 100,
},
'method': 'publicSpotGetV2SpotMarketCandles', // publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
},
'swap': {
'maxLimitPerTimeframe': {
'4h': 540,
'6h': 360,
'12h': 180,
'1d': 90,
'3d': 30,
'1w': 13,
'1M': 4,
},
'method': 'publicMixGetV2MixMarketCandles', // publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
},
},
'fetchTrades': {
'spot': {
'method': 'publicSpotGetV2SpotMarketFillsHistory', // or publicSpotGetV2SpotMarketFills
},
'swap': {
'method': 'publicMixGetV2MixMarketFillsHistory', // or publicMixGetV2MixMarketFills
},
},
'fetchFundingRate': {
'method': 'publicMixGetV2MixMarketCurrentFundRate', // or publicMixGetV2MixMarketFundingTime
},
'accountsByType': {
'spot': 'spot',
'cross': 'crossed_margin',
'isolated': 'isolated_margin',
'swap': 'usdt_futures',
'usdc_swap': 'usdc_futures',
'future': 'coin_futures',
'p2p': 'p2p',
},
'accountsById': {
'spot': 'spot',
'crossed_margin': 'cross',
'isolated_margin': 'isolated',
'usdt_futures': 'swap',
'usdc_futures': 'usdc_swap',
'coin_futures': 'future',
'p2p': 'p2p',
},
'sandboxMode': false,
'networks': {
// 'TRX': 'TRX', // different code for mainnet
'TRC20': 'TRC20',
// 'ETH': 'ETH', // different code for mainnet
'ERC20': 'ERC20',
'BEP20': 'BSC',
// 'BEP20': 'BEP20', // different for BEP20
'BSC': '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',
'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': {},
'fetchPositions': {
'method': 'privateMixGetV2MixPositionAllPosition', // or privateMixGetV2MixPositionHistoryPosition
},
'defaultTimeInForce': 'GTC',
// fiat currencies on deposit page
'fiatCurrencies': ['EUR', 'VND', 'PLN', 'CZK', 'HUF', 'DKK', 'AUD', 'CAD', 'NOK', 'SEK', 'CHF', 'MXN', 'COP', 'ARS', 'GBP', 'BRL', 'UAH', 'ZAR'],
},
'features': {
'spot': {
'sandbox': true,
'createOrder': {
'marginMode': true,
'triggerPrice': true,
'triggerPriceType': {
'last': true,
'mark': true,
'index': false, // not on spot
},
'triggerDirection': false,
'stopLossPrice': true,
'takeProfitPrice': true,
'attachedStopLossTakeProfit': {
'triggerPriceType': {
'last': false,
'mark': false,
'index': false,
},
'price': true,
},
'timeInForce': {
'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': {
'max': 50,
},
'fetchMyTrades': {
'marginMode': true,
'limit': 100,
'daysBack': undefined,
'untilDays': 90,
'symbolRequired': true,
},
'fetchOrder': {
'marginMode': false,
'trigger': false,
'trailing': false,
'symbolRequired': true,
},
'fetchOpenOrders': {
'marginMode': true,
'limit': 100,
'trigger': true,
'trailing': false,
'symbolRequired': false,
},
'fetchOrders': undefined,
'fetchClosedOrders': {
'marginMode': true,
'limit': 100,
'daysBack': undefined,
'daysBackCanceled': undefined,
'untilDays': 90,
'trigger': true,
'trailing': false,
'symbolRequired': false,
},
'fetchOHLCV': {
'limit': 200, // variable timespans for recent endpoint, 200 for historical
},
},
'forPerps': {
'extends': 'spot',
'createOrder': {
'triggerPrice': true,
'triggerPriceType': {
'last': true,
'mark': true,
'index': false, // not on spot
},
'triggerDirection': false,
'stopLossPrice': true,
'takeProfitPrice': true,
'attachedStopLossTakeProfit': {
'triggerPriceType': {
'last': true,
'mark': true,
'index': true,
},
'price': false,
},
'timeInForce': {
'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': {
'untilDays': 7,
},
'fetchClosedOrders': {
'trailing': true,
},
},
'swap': {
'linear': {
'extends': 'forPerps',
},
'inverse': {
'extends': 'forPerps',
},
},
'future': {
'linear': {
'extends': 'forPerps',
},
'inverse': {
'extends': 'forPerps',
},
},
},
});
}
setSandboxMode(enabled) {
this.options['sandboxMode'] = enabled;
}
handleProductTypeAndParams(market = undefined, params = {}) {
let subType = undefined;
[subType, params] = this.handleSubTypeAndParams('handleProductTypeAndParams', undefined, params);
let defaultProductType = undefined;
if ((subType !== undefined) && (market === undefined)) {
// set default only if subType is defined and market is not defined, since there is also USDC productTypes which are also linear
// const sandboxMode = this.safeBool (this.options, 'sandboxMode', false);
// if (sandboxMode) {
// defaultProductType = (subType === 'linear') ? 'SUSDT-FUTURES' : 'SCOIN-FUTURES';
// } else {
defaultProductType = (subType === 'linear') ? 'USDT-FUTURES' : 'COIN-FUTURES';
// }
}
let productType = this.safeString(params, 'productType', defaultProductType);
if ((productType === undefined) && (market !== undefined)) {
const settle = market['settle'];
if (settle === 'USDT') {
productType = 'USDT-FUTURES';
}
else if (settle === 'USDC') {
productType = 'USDC-FUTURES';
}
else if (settle === 'SUSDT') {
productType = 'SUSDT-FUTURES';
}
else if (settle === 'SUSDC') {
productType = 'SUSDC-FUTURES';
}
else if ((settle === 'SBTC') || (settle === 'SETH') || (settle === 'SEOS')) {
productType = 'SCOIN-FUTURES';
}
else {
productType = 'COIN-FUTURES';
}
}
if (productType === undefined) {
throw new errors.ArgumentsRequired(this.id + ' requires a productType param, one of "USDT-FUTURES", "USDC-FUTURES", "COIN-FUTURES", "SUSDT-FUTURES", "SUSDC-FUTURES" or "SCOIN-FUTURES"');
}
params = this.omit(params, 'productType');
return [productType, params];
}
/**
* @method
* @name bitget#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://www.bitget.com/api-doc/common/public/Get-Server-Time
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
async fetchTime(params = {}) {
const response = await this.publicCommonGetV2PublicTime(params);
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700111073740,
// "data": {
// "serverTime": "1700111073740"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.safeInteger(data, 'serverTime');
}
/**
* @method
* @name bitget#fetchMarkets
* @description 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.bike/api-doc/uta/public/Instruments
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.uta] set to true to fetch markets for the unified trading account (uta), defaults to false
* @returns {object[]} an array of objects representing market data
*/
async fetchMarkets(params = {}) {
if (this.options['adjustForTimeDifference']) {
await this.loadTimeDifference();
}
let uta = undefined;
[uta, params] = this.handleOptionAndParams(params, 'fetchMarkets', 'uta', false);
if (uta) {
return await this.fetchUtaMarkets(params);
}
else {
return await this.fetchDefaultMarkets(params);
}
}
async fetchDefaultMarkets(params) {
let types = undefined;
const fetchMarketsOptions = this.safeDict(this.options, 'fetchMarkets');
const defaultMarkets = ['spot', 'swap'];
if (fetchMarketsOptions !== undefined) {
types = this.safeList(fetchMarketsOptions, 'types', defaultMarkets);
}
else {
// for backward-compatibility
types = this.safeList(this.options, 'fetchMarkets', defaultMarkets);
}
const promises = [];
let fetchMargins = false;
for (let i = 0; i < types.length; i++) {
const type = types[i];
if ((type === 'swap') || (type === 'future')) {
const subTypes = ['USDT-FUTURES', 'COIN-FUTURES', 'USDC-FUTURES', 'SUSDT-FUTURES', 'SCOIN-FUTURES', 'SUSDC-FUTURES'];
for (let j = 0; j < subTypes.length; j++) {
promises.push(this.publicMixGetV2MixMarketContracts(this.extend(params, {
'productType': subTypes[j],
})));
}
}
else if (type === 'spot') {
promises.push(this.publicSpotGetV2SpotPublicSymbols(params));
fetchMargins = true;
promises.push(this.publicMarginGetV2MarginCurrencies(params));
}
else {
throw new errors.NotSupported(this.id + ' does not support ' + type + ' market');
}
}
const results = await Promise.all(promises);
let markets = [];
this.options['crossMarginPairsData'] = [];
this.options['isolatedMarginPairsData'] = [];
for (let i = 0; i < results.length; i++) {
const res = this.safeDict(results, i);
const data = this.safeList(res, 'data', []);
const firstData = this.safeDict(data, 0, {});
const isBorrowable = this.safeString(firstData, 'isBorrowable');
if (fetchMargins && isBorrowable !== undefined) {
const keysList = Object.keys(this.indexBy(data, 'symbol'));
this.options['crossMarginPairsData'] = keysList;
this.options['isolatedMarginPairsData'] = keysList;
}
else {
markets = this.arrayConcat(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": ""
// }
//
const result = [];
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
const marketId = this.safeString(market, 'symbol');
const quoteId = this.safeString(market, 'quoteCoin');
const baseId = this.safeString(market, 'baseCoin');
const quote = this.safeCurrencyCode(quoteId);
const base = this.safeCurrencyCode(baseId);
const supportMarginCoins = this.safeValue(market, 'supportMarginCoins', []);
let settleId = undefined;
if (this.inArray(baseId, supportMarginCoins)) {
settleId = baseId;
}
else if (this.inArray(quoteId, supportMarginCoins)) {
settleId = quoteId;
}
else {
settleId = this.safeString(supportMarginCoins, 0);
}
const settle = this.safeCurrencyCode(settleId);
let symbol = base + '/' + quote;
let type = undefined;
let swap = false;
let spot = false;
let future = false;
let contract = false;
let pricePrecision = undefined;
let amountPrecision = undefined;
let linear = undefined;
let inverse = undefined;
let expiry = undefined;
let expiryDatetime = undefined;
const symbolType = this.safeString(market, 'symbolType');
let marginModes = undefined;
let isMarginTradingAllowed = false;
if (symbolType === undefined) {
type = 'spot';
spot = true;
pricePrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'pricePrecision')));
amountPrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityPrecision')));
const hasCrossMargin = this.inArray(marketId, this.options['crossMarginPairsData']);
const hasIsolatedMargin = this.inArray(marketId, this.options['isolatedMarginPairsData']);
marginModes = {
'cross': hasCrossMargin,
'isolated': hasIsolatedMargin,
};
isMarginTradingAllowed = hasCrossMargin || hasCrossMargin;
}
else {
if (symbolType === 'perpetual') {
type = 'swap';
swap = true;
symbol = symbol + ':' + settle;
}
else if (symbolType === 'delivery') {
expiry = this.safeInteger(market, 'deliveryTime');
expiryDatetime = this.iso8601(expiry);
const expiryParts = expiryDatetime.split('-');
const yearPart = this.safeString(expiryParts, 0);
const dayPart = this.safeString(expiryParts, 2);
const year = yearPart.slice(2, 4);
const month = this.safeString(expiryParts, 1);
const day = dayPart.slice(0, 2);
const expiryString = year + month + day;
type = 'future';
future = true;
symbol = symbol + ':' + settle + '-' + expiryString;
}
contract = true;
inverse = (base === settle);
linear = !inverse;
const priceDecimals = this.safeInteger(market, 'pricePlace');
const amountDecimals = this.safeInteger(market, 'volumePlace');
const priceStep = this.safeString(market, 'priceEndStep');
const amountStep = this.safeString(market, 'sizeMultiplier');
const precise = new Precise["default"](priceStep);
precise.decimals = Math.max(precise.decimals, priceDecimals);
precise.reduce();
const priceString = precise.toString();
pricePrecision = this.parseNumber(priceString);
const preciseAmount = new Precise["default"](amountStep);
preciseAmount.decimals = Math.max(preciseAmount.decimals, amountDecimals);
preciseAmount.reduce();
const amountString = preciseAmount.toString();
amountPrecision = this.parseNumber(amountString);
marginModes = {
'cross': true,
'isolated': true,
};
}
const status = this.safeString2(market, 'status', 'symbolStatus');
let active = undefined;
if (status !== undefined) {
active = ((status === 'online') || (status === 'normal'));
}
let minCost = undefined;
if (quote === 'USDT') {
minCost = this.safeNumber(market, 'minTradeUSDT');
}
const contractSize = contract ? 1 : undefined;
result.push(this.safeMarketStructure({
'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.safeNumber(market, 'takerFeeRate'),
'maker': this.safeNumber(market, 'makerFeeRate'),
'contractSize': contractSize,
'expiry': expiry,
'expiryDatetime': expiryDatetime,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': amountPrecision,
'price': pricePrecision,
},
'limits': {
'leverage': {
'min': this.safeNumber(market, 'minLever'),
'max': this.safeNumber(market, 'maxLever'),
},
'amount': {
'min': this.safeNumber2(market, 'minTradeNum', 'minTradeAmount'),
'max': this.safeNumber(market, 'maxTradeAmount'),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': minCost,
'max': undefined,
},
},
'created': this.safeInteger(market, 'launchTime'),
'info': market,
}));
}
return result;
}
async fetchUtaMarkets(params) {
const subTypes = ['SPOT', 'USDT-FUTURES', 'COIN-FUTURES', 'USDC-FUTURES'];
const promises = [];
for (let i = 0; i < subTypes.length; i++) {
const req = this.extend(params, {
'category': subTypes[i],
});
promises.push(this.publicUtaGetV3MarketInstruments(req));
}
const results = await Promise.all(promises);
let markets = [];
for (let i = 0; i < results.length; i++) {
const res = this.safeDict(results, i);
const data = this.safeList(res, 'data', []);
markets = this.arrayConcat(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": ""
// }
//
const result = [];
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
const category = this.safeString(market, 'category');
const marketId = this.safeString(market, 'symbol');
const quoteId = this.safeString(market, 'quoteCoin');
const baseId = this.safeString(market, 'baseCoin');
const quote = this.safeCurrencyCode(quoteId);
const base = this.safeCurrencyCode(baseId);
let settleId = undefined;
let settle = undefined;
if (category === 'USDT-FUTURES') {
settleId = 'USDT';
}
else if (category === 'USDC-FUTURES') {
settleId = 'USDC';
}
else if (category === 'COIN-FUTURES') {
settleId = base;
}
if (settleId !== undefined) {
settle = this.safeCurrencyCode(settleId);
}
let symbol = base + '/' + quote;
let type = undefined;
let swap = false;
let spot = false;
let future = false;
let contract = false;
let pricePrecision = undefined;
let amountPrecision = undefined;
let linear = undefined;
let inverse = undefined;
let expiry = undefined;
let expiryDatetime = undefined;
const symbolType = this.safeString(market, 'type');
let marginModes = undefined;
let isMarginTradingAllowed = false;
const isUtaMargin = (category === 'MARGIN');
if (isUtaMargin || (category === 'SPOT')) {
type = 'spot';
spot = true;
if (isUtaMargin) {
const isolatedBase = this.safeString(market, 'isIsolatedBaseBorrowable');
const isolatedQuote = this.safeString(market, 'isIsolatedQuotedBorrowable');
const isolated = (isolatedBase === 'YES') || (isolatedQuote === 'YES');
const maxCrossLeverage = this.safeString(market, 'maxCrossedLeverage');
const cross = (maxCrossLeverage !== '0');
marginModes = {
'cross': cross,
'isolated': isolated,
};
isMarginTradingAllowed = true;
}
}
else {
if (symbolType === 'perpetual') {
type = 'swap';
swap = true;
symbol = symbol + ':' + settle;
}
else if (symbolType === 'delivery') {
expiry = this.safeInteger(market, 'deliveryTime');
expiryDatetime = this.iso8601(expiry);
const expiryParts = expiryDatetime.split('-');
const yearPart = this.safeString(expiryParts, 0);
const dayPart = this.safeString(expiryParts, 2);
const year = yearPart.slice(2, 4);
const month = this.safeString(expiryParts, 1);
const day = dayPart.slice(0, 2);
const expiryString = year + month + day;
type = 'future';
future = true;
symbol = symbol + ':' + settle + '-' + expiryString;
}
contract = true;
inverse = (base === settle);
linear = !inverse;
marginModes = {
'cross': true,
'isolated': true,
};
}
pricePrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'pricePrecision')));
amountPrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityPrecision')));
const status = this.safeString(market, 'status');
let active = undefined;
if (status !== undefined) {
active = ((status === 'online') || (status === 'normal'));
}
const contractSize = contract ? 1 : undefined;
result.push(this.safeMarketStructure({
'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.safeNumber(market, 'takerFeeRate'),
'maker': this.safeNumber(market, 'makerFeeRate'),
'contractSize': contractSize,
'expiry': expiry,
'expiryDatetime': expiryDatetime,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': amountPrecision,
'price': pricePrecision,
},
'limits': {
'leverage': {
'min': this.safeNumber(market, 'minLeverage'),
'max': this.safeNumber(market, 'maxLeverage'),
},
'amount': {
'min': this.safeNumber(market, 'minOrderQty'),
'max': this.safeNumber(market, 'maxOrderQty'),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'created': this.safeInteger(market, 'launchTime'),
'info': market,
}));
}
return result;
}
/**
* @method
* @name bitget#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://www.bitget.com/api-doc/spot/market/Get-Coin-List
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an associative dictionary of currencies
*/
async fetchCurrencies(params = {}) {
const response = await this.publicSpotGetV2SpotPublicCoins(params);
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": "1746195617812",
// "data": [
// {
// "coinId": "1456",
// "coin": "NEIROETH",
// "transfer": "false",
// "chains": [
// {
// "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"
// },
// ...
//
const result = {};
const data = this.safeValue(response, 'data', []);
const fiatCurrencies = this.safeList(this.options, 'fiatCurrencies', []);
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const id = this.safeString(entry, 'coin'); // we don't use 'coinId' as it has no use. it is 'coin' field that needs to be used in currency related endpoints (deposit, withdraw, etc..)
const code = this.safeCurrencyCode(id);
const chains = this.safeValue(entry, 'chains', []);
const networks = {};
for (let j = 0; j < chains.length; j++) {
const chain = chains[j];
const networkId = this.safeString(chain, 'chain');
let network = this.networkIdToCode(networkId, code);
network = network.toUpperCase();
networks[network] = {
'info': chain,
'id': networkId,
'network': network,
'limits': {
'withdraw': {
'min': this.safeNumber(chain, 'minWithdrawAmount'),
'max': undefined,
},
'deposit': {
'min': this.safeNumber(chain, 'minDepositAmount'),
'max': undefined,
},
},
'active': undefined,
'withdraw': this.safeString(chain, 'withdrawable') === 'true',
'deposit': this.safeString(chain, 'rechargeable') === 'true',
'fee': this.safeNumber(chain, 'withdrawFee'),
'precision': this.parseNumber(this.parsePrecision(this.safeString(chain, 'withdrawMinScale'))),
};
}
const isFiat = this.inArray(code, fiatCurrencies);
result[code] = this.safeCurrencyStructure({
'info': entry,
'id': id,
'code': code,
'networks': networks,
'type': isFiat ? 'fiat' : 'crypto',
'name': undefined,
'active': undefined,
'deposit': undefined,
'withdraw': undefined,
'fee': undefined,
'precision': undefined,
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': undefined,
'max': undefined,
},
'deposit': {
'min': undefined,
'max': undefined,
},
},
'created': undefined,
});
}
return result;
}
/**
* @method
* @name bitget#fetchMarketLeverageTiers
* @description 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
* @param {string} symbol unified market symbol
* @param {object} [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 only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
* @returns {object} a [leverage tiers structure]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}
*/
async fetchMarketLeverageTiers(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {};
let response = undefined;
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchMarketLeverageTiers', params, 'isolated');
if ((market['swap']) || (market['future'])) {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
request['symbol'] = market['id'];
response = await this.publicMixGetV2MixMarketQueryPositionLever(this.extend(request, params));
}
else if (marginMode === 'isolated') {
request['symbol'] = market['id'];
response = await this.privateMarginGetV2MarginIsolatedTierData(this.extend(request, params));
}
else if (marginMode === 'cross') {
const code = this.safeString(params, 'code');
if (code === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchMarketLeverageTiers() requires a code argument');
}
params = this.omit(params, 'code');
const currency = this.currency(code);
request['coin'] = currency['id'];
response = await this.privateMarginGetV2MarginCrossedTierData(this.extend(request, params));
}
else {
throw new errors.BadRequest(this.id + ' fetchMarketLeverageTiers() symbol does not support market ' + market['symbol']);
}
//
// swap and future
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700290724614,
// "data": [
// {
// "symbol": "BTCUSDT",
// "level": "1",
// "startUnit": "0",
// "endUnit": "150000",
// "leverage": "125",
// "keepMarginRate": "0.004"
// },
// ]
// }
//
// isolated
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700291531894,
// "data": [
// {
// "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": [
// {
// "tier": "1",
// "leverage": "3",
// "coin": "BTC",
// "maxBorrowableAmount": "26",
// "maintainMarginRate": "0.1"
// }
// ]
// }
//
const result = this.safeValue(response, 'data', []);
return this.parseMarketLeverageTiers(result, market);
}
parseMarketLeverageTiers(info, market = undefined) {
//
// 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"
// }
//
const tiers = [];
let minNotional = 0;
for (let i = 0; i < info.length; i++) {
const item = info[i];
const minimumNotional = this.safeNumber(item, 'startUnit');
if (minimumNotional !== undefined) {
minNotional = minimumNotional;
}
const maxNotional = this.safeNumberN(item, ['endUnit', 'maxBorrowableAmount', 'baseMaxBorrowableAmount']);
const marginCurrency = this.safeString2(item, 'coin', 'baseCoin');
const currencyId = (marginCurrency !== undefined) ? marginCurrency : market['base'];
const marketId = this.safeString(item, 'symbol');
tiers.push({
'tier': this.safeInteger2(item, 'level', 'tier'),
'symbol': this.safeSymbol(marketId, market),
'currency': this.safeCurrencyCode(currencyId),
'minNotional': minNotional,
'maxNotional': maxNotional,
'maintenanceMarginRate': this.safeNumber2(item, 'keepMarginRate', 'maintainMarginRate'),
'maxLeverage': this.safeNumber(item, 'leverage'),
'info': item,
});
minNotional = maxNotional;
}
return tiers;
}
/**
* @method
* @name bitget#fetchDeposits
* @description 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 {object} [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)
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchDeposits', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchDeposits', undefined, since, limit, params, 'idLessThan', 'idLessThan', undefined, 100);
}
if (since === undefined) {
since = this.milliseconds() - 7776000000; // 90 days
}
let request = {
'startTime': since,
'endTime': this.milliseconds(),
};
let currency = undefined;
if (code !== undefined) {
currency = this.currency(code);
request['coin'] = currency['id'];
}
if (limit !== undefined) {
request['limit'] = limit;
}
[request, params] = this.handleUntilOption('endTime', request, params);
const response = await this.privateSpotGetV2SpotWalletDepositRecords(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700528340608,
// "data": [
// {
// "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"
// }
// ]
// }
//
const rawTransactions = this.safeList(response, 'data', []);
return this.parseTransactions(rawTransactions, undefined, since, limit);
}
/**
* @method
* @name bitget#withdraw
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.chain] the blockchain network the withdrawal is taking place on
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
async withdraw(code, amount, address, tag = undefined, params = {}) {
this.checkAddress(address);
let networkCode = undefined;
[networkCode, params] = this.handleNetworkCodeAndParams(params);
if (networkCode === undefined) {
throw new errors.ArgumentsRequired(this.id + ' withdraw() requires a "network" parameter');
}
await this.loadMarkets();
const currency = this.currency(code);
const networkId = this.networkCodeToId(networkCode);
const request = {
'coin': currency['id'],
'address': address,
'chain': networkId,
'size': this.currencyToPrecision(code, amount, networkCode),
'transferType': 'on_chain',
};
if (tag !== undefined) {
request['tag'] = tag;
}
const response = await this.privateSpotPostV2SpotWalletWithdrawal(this.extend(request, params));
//
// {
// "code":"00000",
// "msg":"success",
// "requestTime":1696784219602,
// "data": {
// "orderId":"1094957867615789056",
// "clientOid":"64f1e4ce842041d296b4517df1b5c2d7"
// }
// }
//
const data = this.safeValue(response, 'data', {});
const result = this.parseTransaction(data, currency);
result['type'] = 'withdrawal';
const withdrawOptions = this.safeValue(this.options, 'withdraw', {});
const fillResponseFromRequest = this.safeBool(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;
}
/**
* @method
* @name bitget#fetchWithdrawals
* @description 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 {object} [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)
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchWithdrawals', undefined, since, limit, params, 'idLessThan', 'idLessThan', undefined, 100);
}
let currency = undefined;
if (code !== undefined) {
currency = this.currency(code);
}
if (since === undefined) {
since = this.milliseconds() - 7776000000; // 90 days
}
let request = {
'startTime': since,
'endTime': this.milliseconds(),
};
if (currency !== undefined) {
request['coin'] = currency['id'];
}
[request, params] = this.handleUntilOption('endTime', request, params);
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.privateSpotGetV2SpotWalletWithdrawalRecords(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700528340608,
// "data": [
// {
// "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"
// }
// ]
// }
//
const rawTransactions = this.safeList(response, 'data', []);
return this.parseTransactions(rawTransactions, currency, since, limit);
}
parseTransaction(transaction, currency = undefined) {
//
// 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"
// }
//
const currencyId = this.safeString(transaction, 'coin');
const code = this.safeCurrencyCode(currencyId, currency);
const timestamp = this.safeInteger(transaction, 'cTime');
const networkId = this.safeString(transaction, 'chain');
const status = this.safeString(transaction, 'status');
const tag = this.safeString(transaction, 'tag');
const feeCostString = this.safeString(transaction, 'fee');
let feeCostAbsString = undefined;
if (feeCostString !== undefined) {
feeCostAbsString = Precise["default"].stringAbs(feeCostString);
}
let fee = undefined;
let amountString = this.safeString(transaction, 'size');
if (feeCostAbsString !== undefined) {
fee = { 'currency': code, 'cost': this.parseNumber(feeCostAbsString) };
amountString = Precise["default"].stringSub(amountString, feeCostAbsString);
}
return {
'id': this.safeString(transaction, 'orderId'),
'info': transaction,
'txid': this.safeString(transaction, 'tradeId'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'network': this.networkIdToCode(networkId),
'addressFrom': this.safeString(transaction, 'fromAddress'),
'address': this.safeString(transaction, 'toAddress'),
'addressTo': this.safeString(transaction, 'toAddress'),
'amount': this.parseNumber(amountString),
'type': this.safeString(transaction, 'type'),
'currency': code,
'status': this.parseTransactionStatus(status),
'updated': this.safeInteger(transaction, 'uTime'),
'tagFrom': undefined,
'tag': tag,
'tagTo': tag,
'comment': undefined,
'internal': undefined,
'fee': fee,
};
}
parseTransactionStatus(status) {
const statuses = {
'success': 'ok',
'Pending': 'pending',
'pending_review': 'pending',
'pending_review_fail': 'failed',
'reject': 'failed',
};
return this.safeString(statuses, status, status);
}
/**
* @method
* @name bitget#fetchDepositAddress
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
*/
async fetchDepositAddress(code, params = {}) {
await this.loadMarkets();
let networkCode = undefined;
[networkCode, params] = this.handleNetworkCodeAndParams(params);
const currency = this.currency(code);
const request = {
'coin': currency['id'],
};
if (networkCode !== undefined) {
request['chain'] = this.networkCodeToId(networkCode, code);
}
const response = 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/"
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseDepositAddress(data, currency);
}
parseDepositAddress(depositAddress, currency = undefined) {
//
// {
// "coin": "BTC",
// "address": "1BfZh7JESJGBUszCGeZnzxbVVvBycbJSbA",
// "chain": "",
// "tag": null,
// "url": "https://blockchair.com/bitcoin/transaction/"
// }
//
const currencyId = this.safeString(depositAddress, 'coin');
const networkId = this.safeString(depositAddress, 'chain');
const parsedCurrency = this.safeCurrencyCode(currencyId, currency);
let network = undefined;
if (networkId !== undefined) {
network = this.networkIdToCode(networkId, parsedCurrency);
}
return {
'info': depositAddress,
'currency': parsedCurrency,
'network': network,
'address': this.safeString(depositAddress, 'address'),
'tag': this.safeString(depositAddress, 'tag'),
};
}
/**
* @method
* @name bitget#fetchOrderBook
* @description 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
* @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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async fetchOrderBook(symbol, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
request['limit'] = limit;
}
let response = undefined;
if (market['spot']) {
response = await this.publicSpotGetV2SpotMarketOrderbook(this.extend(request, params));
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.publicMixGetV2MixMarketMergeDepth(this.extend(request, params));
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1645854610294,
// "data": {
// "asks": [ [ "39102", "11.026" ] ],
// "bids": [ [ '39100.5', "1.773" ] ],
// "ts": "1645854610294"
// }
// }
//
const data = this.safeValue(response, 'data', {});
const timestamp = this.safeInteger(data, 'ts');
return this.parseOrderBook(data, market['symbol'], timestamp);
}
parseTicker(ticker, market = undefined) {
//
// {
// "symbol": "BTCUSDT",
// "price": "26242",
// "indexPrice": "34867",
// "markPrice": "25555",
// "ts": "1695793390482"
// }
//
// spot: fetchTicker, fetchTickers
//
// {
// "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: fetchTicker
//
// {
// "symbol": "BTCUSDT",
// "lastPr": "37577.2",
// "askPr": "37577.3",
// "bidPr": "37577.2",
// "bidSz": "3.679",
// "askSz": "0.02",
// "high24h": "37765",
// "low24h": "36628.9",
// "ts": "1700533070359",
// "change24h": "0.00288",
// "baseVolume": "108606.181",
// "quoteVolume": "4051316303.9608",
// "usdtVolume": "4051316303.9608",
// "openUtc": "37451.5",
// "changeUtc24h": "0.00336",
// "indexPrice": "37574.489253",
// "fundingRate": "0.0001",
// "holdingAmount": "53464.529",
// "deliveryStartTime": null,
// "deliveryTime": null,
// "deliveryStatus": "",
// "open24h": "37235.7"
// }
//
// swap and future: fetchTickers
//
// {
// "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"
// }
//
const marketId = this.safeString(ticker, 'symbol');
const close = this.safeString(ticker, 'lastPr');
const timestamp = this.safeIntegerOmitZero(ticker, 'ts'); // exchange bitget provided 0
const change = this.safeString(ticker, 'change24h');
const open24 = this.safeString2(ticker, 'open24', 'open24h');
const open = this.safeString(ticker, 'open');
let symbol;
let openValue;
if (open === undefined) {
symbol = this.safeSymbol(marketId, market, undefined, 'contract');
openValue = open24;
}
else {
symbol = this.safeSymbol(marketId, market, undefined, 'spot');
openValue = open;
}
return this.safeTicker({
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString(ticker, 'high24h'),
'low': this.safeString(ticker, 'low24h'),
'bid': this.safeString(ticker, 'bidPr'),
'bidVolume': this.safeString(ticker, 'bidSz'),
'ask': this.safeString(ticker, 'askPr'),
'askVolume': this.safeString(ticker, 'askSz'),
'vwap': undefined,
'open': openValue,
'close': close,
'last': close,
'previousClose': undefined,
'change': change,
'percentage': Precise["default"].stringMul(change, '100'),
'average': undefined,
'baseVolume': this.safeString(ticker, 'baseVolume'),
'quoteVolume': this.safeString(ticker, 'quoteVolume'),
'indexPrice': this.safeString(ticker, 'indexPrice'),
'markPrice': this.safeString(ticker, 'markPrice'),
'info': ticker,
}, market);
}
/**
* @method
* @name bitget#fetchTicker
* @description 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
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async fetchTicker(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
let response = undefined;
if (market['spot']) {
response = await this.publicSpotGetV2SpotMarketTickers(this.extend(request, params));
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.publicMixGetV2MixMarketTicker(this.extend(request, params));
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700532903782,
// "data": [
// {
// "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": 1700533070357,
// "data": [
// {
// "symbol": "BTCUSDT",
// "lastPr": "37577.2",
// "askPr": "37577.3",
// "bidPr": "37577.2",
// "bidSz": "3.679",
// "askSz": "0.02",
// "high24h": "37765",
// "low24h": "36628.9",
// "ts": "1700533070359",
// "change24h": "0.00288",
// "baseVolume": "108606.181",
// "quoteVolume": "4051316303.9608",
// "usdtVolume": "4051316303.9608",
// "openUtc": "37451.5",
// "changeUtc24h": "0.00336",
// "indexPrice": "37574.489253",
// "fundingRate": "0.0001",
// "holdingAmount": "53464.529",
// "deliveryStartTime": null,
// "deliveryTime": null,
// "deliveryStatus": "",
// "open24h": "37235.7"
// }
// ]
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTicker(data[0], market);
}
/**
* @method
* @name bitget#fetchMarkPrice
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async fetchMarkPrice(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
let response = undefined;
if (market['spot']) {
throw new errors.NotSupported(this.id + ' fetchMarkPrice() is not supported for spot markets');
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.publicMixGetV2MixMarketSymbolPrice(this.extend(request, params));
}
const data = this.safeList(response, 'data', []);
return this.parseTicker(data[0], market);
}
/**
* @method
* @name bitget#fetchTickers
* @description 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
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} [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'
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async fetchTickers(symbols = undefined, params = {}) {
await this.loadMarkets();
let market = undefined;
if (symbols !== undefined) {
const symbol = this.safeValue(symbols, 0);
market = this.market(symbol);
}
let response = undefined;
const request = {};
let type = undefined;
[type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
// Calls like `.fetchTickers (undefined, {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
const passedSubType = this.safeString(params, 'subType');
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
// only if passedSubType && productType is undefined, then use spot
if (type === 'spot' && passedSubType === undefined) {
response = await this.publicSpotGetV2SpotMarketTickers(this.extend(request, params));
}
else {
request['productType'] = productType;
response = await this.publicMixGetV2MixMarketTickers(this.extend(request, params));
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700532903782,
// "data": [
// {
// "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": [
// {
// "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"
// },
// ]
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTickers(data, symbols);
}
parseTrade(trade, market = undefined) {
//
// 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": {
// "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": {
// "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": [
// {
// "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"
// }
//
const marketId = this.safeString(trade, 'symbol');
const symbol = this.safeSymbol(marketId, market);
const timestamp = this.safeInteger2(trade, 'cTime', 'ts');
let fee = undefined;
const feeDetail = this.safeValue(trade, 'feeDetail');
const posMode = this.safeString(trade, 'posMode');
const feeStructure = (posMode !== undefined) ? feeDetail[0] : feeDetail;
if (feeStructure !== undefined) {
const currencyCode = this.safeCurrencyCode(this.safeString(feeStructure, 'feeCoin'));
fee = {
'currency': currencyCode,
};
const feeCostString = this.safeString(feeStructure, 'totalFee');
const deduction = this.safeString(feeStructure, 'deduction') === 'yes' ? true : false;
if (deduction) {
fee['cost'] = feeCostString;
}
else {
fee['cost'] = Precise["default"].stringNeg(feeCostString);
}
}
return this.safeTrade({
'info': trade,
'id': this.safeString(trade, 'tradeId'),
'order': this.safeString(trade, 'orderId'),
'symbol': symbol,
'side': this.safeStringLower(trade, 'side'),
'type': this.safeString(trade, 'orderType'),
'takerOrMaker': this.safeString(trade, 'tradeScope'),
'price': this.safeString2(trade, 'priceAvg', 'price'),
'amount': this.safeString2(trade, 'baseVolume', 'size'),
'cost': this.safeString2(trade, 'quoteVolume', 'amount'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'fee': fee,
}, market);
}
/**
* @method
* @name bitget#fetchTrades
* @description 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
* @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 {object} [params] extra parameters specific to the exchange API endpoint
* @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
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchTrades', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchTrades', symbol, since, limit, params, 'idLessThan', 'idLessThan');
}
const market = this.market(symbol);
let request = {
'symbol': market['id'],
};
if (limit !== undefined) {
if (market['contract']) {
request['limit'] = Math.min(limit, 1000);
}
else {
request['limit'] = limit;
}
}
const options = this.safeValue(this.options, 'fetchTrades', {});
let response = undefined;
if (market['spot']) {
const spotOptions = this.safeValue(options, 'spot', {});
const defaultSpotMethod = this.safeString(spotOptions, 'method', 'publicSpotGetV2SpotMarketFillsHistory');
const spotMethod = this.safeString(params, 'method', defaultSpotMethod);
params = this.omit(params, 'method');
if (spotMethod === 'publicSpotGetV2SpotMarketFillsHistory') {
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
response = await this.publicSpotGetV2SpotMarketFillsHistory(this.extend(request, params));
}
else if (spotMethod === 'publicSpotGetV2SpotMarketFills') {
response = await this.publicSpotGetV2SpotMarketFills(this.extend(request, params));
}
}
else {
const swapOptions = this.safeValue(options, 'swap', {});
const defaultSwapMethod = this.safeString(swapOptions, 'method', 'publicMixGetV2MixMarketFillsHistory');
const swapMethod = this.safeString(params, 'method', defaultSwapMethod);
params = this.omit(params, 'method');
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (swapMethod === 'publicMixGetV2MixMarketFillsHistory') {
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
response = await this.publicMixGetV2MixMarketFillsHistory(this.extend(request, params));
}
else if (swapMethod === 'publicMixGetV2MixMarketFills') {
response = await this.publicMixGetV2MixMarketFills(this.extend(request, params));
}
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1692073693562,
// "data": [
// {
// "symbol": "BTCUSDT_SPBL",
// "tradeId": "1075200479040323585",
// "side": "Sell",
// "price": "29381.54",
// "size": "0.0056",
// "ts": "1692073691000"
// },
// ]
// }
//
// swap
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1692073522689,
// "data": [
// {
// "tradeId": "1075199767891652609",
// "price": "29376.5",
// "size": "6.035",
// "side": "Buy",
// "ts": "1692073521000",
// "symbol": "BTCUSDT_UMCBL"
// },
// ]
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTrades(data, market, since, limit);
}
/**
* @method
* @name bitget#fetchTradingFee
* @description 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 {object} [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
* @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
*/
async fetchTradingFee(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchTradingFee', params);
if (market['spot']) {
if (marginMode !== undefined) {
request['businessType'] = 'margin';
}
else {
request['businessType'] = 'spot';
}
}
else {
request['businessType'] = 'mix';
}
const response = await this.privateCommonGetV2CommonTradeRate(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700549524887,
// "data": {
// "makerFeeRate": "0.001",
// "takerFeeRate": "0.001"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.parseTradingFee(data, market);
}
/**
* @method
* @name bitget#fetchTradingFees
* @description 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 {object} [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
* @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
*/
async fetchTradingFees(params = {}) {
await this.loadMarkets();
let response = undefined;
let marginMode = undefined;
let marketType = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchTradingFees', params);
[marketType, params] = this.handleMarketTypeAndParams('fetchTradingFees', undefined, params);
if (marketType === 'spot') {
const margin = this.safeBool(params, 'margin', false);
params = this.omit(params, 'margin');
if ((marginMode !== undefined) || margin) {
response = await this.publicMarginGetV2MarginCurrencies(params);
}
else {
response = await this.publicSpotGetV2SpotPublicSymbols(params);
}
}
else if ((marketType === 'swap') || (marketType === 'future')) {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(undefined, params);
params['productType'] = productType;
response = await this.publicMixGetV2MixMarketContracts(params);
}
else {
throw new errors.NotSupported(this.id + ' does not support ' + marketType + ' market');
}
//
// spot and margin
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700102364653,
// "data": [
// {
// "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": [
// {
// "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": ""
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const result = {};
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const marketId = this.safeString(entry, 'symbol');
const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
const market = this.market(symbol);
const fee = this.parseTradingFee(entry, market);
result[symbol] = fee;
}
return result;
}
parseTradingFee(data, market = undefined) {
const marketId = this.safeString(data, 'symbol');
return {
'info': data,
'symbol': this.safeSymbol(marketId, market),
'maker': this.safeNumber(data, 'makerFeeRate'),
'taker': this.safeNumber(data, 'takerFeeRate'),
'percentage': undefined,
'tierBased': undefined,
};
}
parseOHLCV(ohlcv, market = undefined) {
//
// [
// "1645911960000",
// "39406",
// "39407",
// "39374.5",
// "39379",
// "35.526",
// "1399132.341"
// ]
//
return [
this.safeInteger(ohlcv, 0),
this.safeNumber(ohlcv, 1),
this.safeNumber(ohlcv, 2),
this.safeNumber(ohlcv, 3),
this.safeNumber(ohlcv, 4),
this.safeNumber(ohlcv, 5),
];
}
/**
* @method
* @name bitget#fetchOHLCV
* @description 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
* @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 {object} [params] extra parameters specific to the exchange API endpoint
* @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)
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const defaultLimit = 100; // default 100, max 1000
const maxLimitForRecentEndpoint = 1000;
const maxLimitForHistoryEndpoint = 200; // note, max 1000 bars are supported for "recent-candles" endpoint, but "historical-candles" support only max 200
const useHistoryEndpoint = this.safeBool(params, 'useHistoryEndpoint', false);
const useHistoryEndpointForPagination = this.safeBool(params, 'useHistoryEndpointForPagination', true);
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate');
if (paginate) {
const limitForPagination = useHistoryEndpointForPagination ? maxLimitForHistoryEndpoint : maxLimitForRecentEndpoint;
return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, limitForPagination);
}
const market = this.market(symbol);
const marketType = market['spot'] ? 'spot' : 'swap';
const timeframes = this.options['timeframes'][marketType];
const request = {
'symbol': market['id'],
'granularity': this.safeString(timeframes, timeframe, timeframe),
};
const msInDay = 86400000;
const now = this.milliseconds();
const duration = this.parseTimeframe(timeframe) * 1000;
const until = this.safeInteger(params, 'until');
const limitDefined = limit !== undefined;
const sinceDefined = since !== undefined;
const untilDefined = until !== undefined;
params = this.omit(params, ['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
const key = market['spot'] ? 'spot' : 'swap';
const ohlcOptions = this.safeDict(this.options['fetchOHLCV'], key, {});
const maxLimitPerTimeframe = this.safeDict(ohlcOptions, 'maxLimitPerTimeframe', {});
const maxLimitForThisTimeframe = this.safeInteger(maxLimitPerTimeframe, timeframe, limit);
const recentEndpointDaysMap = this.safeDict(this.options['fetchOHLCV'], 'maxRecentDaysPerTimeframe', {});
const recentEndpointAvailableDays = this.safeInteger(recentEndpointDaysMap, timeframe);
const recentEndpointBoundaryTs = now - (recentEndpointAvailableDays - 1) * msInDay;
if (limitDefined) {
limit = Math.min(limit, maxLimitForRecentEndpoint);
limit = Math.min(limit, maxLimitForThisTimeframe);
}
else {
limit = defaultLimit;
}
let limitMultipliedDuration = limit * duration;
// exchange aligns from endTime, so it's important, not startTime
// startTime is supported only on "recent" endpoint, not on "historical" endpoint
let calculatedStartTime = undefined;
let calculatedEndTime = undefined;
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
let historicalEndpointNeeded = false;
if ((calculatedStartTime !== undefined && calculatedStartTime <= recentEndpointBoundaryTs) || useHistoryEndpoint) {
historicalEndpointNeeded = true;
// only for "historical-candles" - ensure we use correct max limit
limit = Math.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']) {
const 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
let response = undefined;
if (market['spot']) {
// checks if we need history endpoint
if (historicalEndpointNeeded) {
response = await this.publicSpotGetV2SpotMarketHistoryCandles(this.extend(request, params));
}
else {
response = await this.publicSpotGetV2SpotMarketCandles(this.extend(request, params));
}
}
else {
let priceType = undefined;
[priceType, params] = this.handleParamString(params, 'price');
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
const extended = this.extend(request, params);
// todo: mark & index also have their "recent" endpoints, but not priority now.
if (priceType === 'mark') {
response = await this.publicMixGetV2MixMarketHistoryMarkCandles(extended);
}
else if (priceType === 'index') {
response = await this.publicMixGetV2MixMarketHistoryIndexCandles(extended);
}
else {
if (historicalEndpointNeeded) {
response = await this.publicMixGetV2MixMarketHistoryCandles(extended);
}
else {
response = await this.publicMixGetV2MixMarketCandles(extended);
}
}
}
if (response === '') {
return []; // happens when a new token is listed
}
// [ ["1645911960000","39406","39407","39374.5","39379","35.526","1399132.341"] ]
const data = this.safeList(response, 'data', response);
return this.parseOHLCVs(data, market, timeframe, since, limit);
}
/**
* @method
* @name bitget#fetchBalance
* @description 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
* @param {object} [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'
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
*/
async fetchBalance(params = {}) {
await this.loadMarkets();
const request = {};
let marketType = undefined;
let marginMode = undefined;
let response = undefined;
[marketType, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
[marginMode, params] = this.handleMarginModeAndParams('fetchBalance', params);
if ((marketType === 'swap') || (marketType === 'future')) {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(undefined, params);
request['productType'] = productType;
response = await this.privateMixGetV2MixAccountAccounts(this.extend(request, params));
}
else if (marginMode === 'isolated') {
response = await this.privateMarginGetMarginV1IsolatedAccountAssets(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetMarginV1CrossAccountAssets(this.extend(request, params));
}
else if (marketType === 'spot') {
response = await this.privateSpotGetV2SpotAccountAssets(this.extend(request, params));
}
else {
throw new errors.NotSupported(this.id + ' fetchBalance() does not support ' + marketType + ' accounts');
}
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700623852854,
// "data": [
// {
// "coin": "USDT",
// "available": "0.00000000",
// "limitAvailable": "0",
// "frozen": "0.00000000",
// "locked": "0.00000000",
// "uTime": "1699937566000"
// }
// ]
// }
//
// swap
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700625127294,
// "data": [
// {
// "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
// }
// ]
// }
//
// isolated margin
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1697501436571,
// "data": [
// {
// "symbol": "BTCUSDT",
// "coin": "BTC",
// "totalAmount": "0.00021654",
// "available": "0.00021654",
// "transferable": "0.00021654",
// "frozen": "0",
// "borrow": "0",
// "interest": "0",
// "net": "0.00021654",
// "ctime": "1697248128071"
// },
// ]
// }
//
// cross margin
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1697515463804,
// "data": [
// {
// "coin": "BTC",
// "totalAmount": "0.00024996",
// "available": "0.00024996",
// "transferable": "0.00004994",
// "frozen": "0",
// "borrow": "0.0001",
// "interest": "0.00000001",
// "net": "0.00014995",
// "ctime": "1697251265504"
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
return this.parseBalance(data);
}
parseBalance(balance) {
const result = { '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
// }
//
// isolated margin
//
// {
// "symbol": "BTCUSDT",
// "coin": "BTC",
// "totalAmount": "0.00021654",
// "available": "0.00021654",
// "transferable": "0.00021654",
// "frozen": "0",
// "borrow": "0",
// "interest": "0",
// "net": "0.00021654",
// "ctime": "1697248128071"
// }
//
// cross margin
//
// {
// "coin": "BTC",
// "totalAmount": "0.00024995",
// "available": "0.00024995",
// "transferable": "0.00004993",
// "frozen": "0",
// "borrow": "0.0001",
// "interest": "0.00000001",
// "net": "0.00014994",
// "ctime": "1697251265504"
// }
//
for (let i = 0; i < balance.length; i++) {
const entry = balance[i];
const account = this.account();
const currencyId = this.safeString2(entry, 'marginCoin', 'coin');
const code = this.safeCurrencyCode(currencyId);
const borrow = this.safeString(entry, 'borrow');
if (borrow !== undefined) {
const interest = this.safeString(entry, 'interest');
account['free'] = this.safeString(entry, 'transferable');
account['total'] = this.safeString(entry, 'totalAmount');
account['debt'] = Precise["default"].stringAdd(borrow, interest);
}
else {
// Use transferable instead of available for swap and margin https://github.com/ccxt/ccxt/pull/19127
const spotAccountFree = this.safeString(entry, 'available');
const contractAccountFree = this.safeString(entry, 'maxTransferOut');
if (contractAccountFree !== undefined) {
account['free'] = contractAccountFree;
account['total'] = this.safeString(entry, 'accountEquity');
}
else {
account['free'] = spotAccountFree;
const frozen = this.safeString(entry, 'frozen');
const locked = this.safeString(entry, 'locked');
account['used'] = Precise["default"].stringAdd(frozen, locked);
}
}
result[code] = account;
}
return this.safeBalance(result);
}
parseOrderStatus(status) {
const statuses = {
'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.safeString(statuses, status, status);
}
parseOrder(order, market = undefined) {
//
// createOrder, editOrder, closePosition
//
// {
// "clientOid": "abe95dbe-6081-4a6f-a2d3-ae49601cd479",
// "orderId": null
// }
//
// createOrders
//
// [
// {
// "orderId": "1111397214281175046",
// "clientOid": "766d3fc3-7321-4406-a689-15c9987a2e75"
// },
// {
// "orderId": "",
// "clientOid": "d1b75cb3-cc15-4ede-ad4c-3937396f75ab",
// "errorMsg": "less than the minimum amount 5 USDT",
// "errorCode": "45110"
// },
// ]
//
// spot, swap, future and spot margin: cancelOrder, cancelOrders
//
// {
// "orderId": "1098758604547850241",
// "clientOid": "1098758604585598977"
// }
//
// spot trigger: cancelOrder
//
// {
// "result": "success"
// }
//
// spot: fetchOrder
//
// {
// "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: fetchOrder
//
// {
// "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"
// }
//
// spot: fetchOpenOrders
//
// {
// "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: 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: fetchOpenOrders, fetchCanceledAndClosedOrders
//
// {
// "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"
// }
//
// swap stop: fetchOpenOrders
//
// {
// "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"
// }
//
// spot: fetchCanceledAndClosedOrders
//
// {
// "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"
// }
//
// swap stop: fetchCanceledAndClosedOrders
//
// {
// "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"
// }
//
const errorMessage = this.safeString(order, 'errorMsg');
if (errorMessage !== undefined) {
return this.safeOrder({
'info': order,
'id': this.safeString(order, 'orderId'),
'clientOrderId': this.safeString2(order, 'clientOrderId', 'clientOid'),
'status': 'rejected',
}, market);
}
const isContractOrder = ('posSide' in order);
let marketType = isContractOrder ? 'contract' : 'spot';
if (market !== undefined) {
marketType = market['type'];
}
const marketId = this.safeString(order, 'symbol');
market = this.safeMarket(marketId, market, undefined, marketType);
const timestamp = this.safeInteger2(order, 'cTime', 'ctime');
const updateTimestamp = this.safeInteger(order, 'uTime');
let rawStatus = this.safeString2(order, 'status', 'state');
rawStatus = this.safeString(order, 'planStatus', rawStatus);
let fee = undefined;
const feeCostString = this.safeString(order, 'fee');
if (feeCostString !== undefined) {
// swap
fee = {
'cost': this.parseNumber(Precise["default"].stringNeg(feeCostString)),
'currency': market['settle'],
};
}
const feeDetail = this.safeValue(order, 'feeDetail');
if (feeDetail !== undefined) {
const parsedFeeDetail = JSON.parse(feeDetail);
const feeValues = Object.values(parsedFeeDetail);
let feeObject = undefined;
for (let i = 0; i < feeValues.length; i++) {
const feeValue = feeValues[i];
if (this.safeValue(feeValue, 'feeCoinCode') !== undefined) {
feeObject = feeValue;
break;
}
}
fee = {
'cost': this.parseNumber(Precise["default"].stringNeg(this.safeString(feeObject, 'totalFee'))),
'currency': this.safeCurrencyCode(this.safeString(feeObject, 'feeCoinCode')),
};
}
let postOnly = undefined;
let timeInForce = this.safeStringUpper(order, 'force');
if (timeInForce === 'POST_ONLY') {
postOnly = true;
timeInForce = 'PO';
}
let reduceOnly = undefined;
const reduceOnlyRaw = this.safeString(order, 'reduceOnly');
if (reduceOnlyRaw !== undefined) {
reduceOnly = (reduceOnlyRaw === 'NO') ? false : true;
}
let price = undefined;
let average = undefined;
const basePrice = this.safeString(order, 'basePrice');
if (basePrice !== undefined) {
// for spot fetchOpenOrders, the price is priceAvg and the filled price is basePrice
price = this.safeString(order, 'priceAvg');
average = this.safeString(order, 'basePrice');
}
else {
price = this.safeString2(order, 'price', 'executePrice');
average = this.safeString(order, 'priceAvg');
}
let size = undefined;
let filled = undefined;
const baseSize = this.safeString(order, 'baseSize');
if (baseSize !== undefined) {
// for spot margin fetchOpenOrders, the order size is baseSize and the filled amount is size
size = baseSize;
filled = this.safeString(order, 'size');
}
else {
size = this.safeString(order, 'size');
filled = this.safeString(order, 'baseVolume');
}
let side = this.safeString(order, 'side');
const posMode = this.safeString(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
}
return this.safeOrder({
'info': order,
'id': this.safeString2(order, 'orderId', 'data'),
'clientOrderId': this.safeString2(order, 'clientOrderId', 'clientOid'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'lastTradeTimestamp': updateTimestamp,
'lastUpdateTimestamp': updateTimestamp,
'symbol': market['symbol'],
'type': this.safeString(order, 'orderType'),
'side': side,
'price': price,
'amount': size,
'cost': this.safeString2(order, 'quoteVolume', 'quoteSize'),
'average': average,
'filled': filled,
'remaining': undefined,
'timeInForce': timeInForce,
'postOnly': postOnly,
'reduceOnly': reduceOnly,
'triggerPrice': this.safeNumber(order, 'triggerPrice'),
'takeProfitPrice': this.safeNumber2(order, 'presetStopSurplusPrice', 'stopSurplusTriggerPrice'),
'stopLossPrice': this.safeNumber2(order, 'presetStopLossPrice', 'stopLossTriggerPrice'),
'status': this.parseOrderStatus(rawStatus),
'fee': fee,
'trades': undefined,
}, market);
}
/**
* @method
* @name bitget#createMarketBuyOrderWithCost
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
if (!market['spot']) {
throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
}
const req = {
'createMarketBuyOrderRequiresPrice': false,
};
return await this.createOrder(symbol, 'market', 'buy', cost, undefined, this.extend(req, params));
}
/**
* @method
* @name bitget#createOrder
* @description 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
* @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 {object} [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 {object} [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 {object} [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 as undefined 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
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const marginParams = this.handleMarginModeAndParams('createOrder', params);
const marginMode = marginParams[0];
const triggerPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
const stopLossTriggerPrice = this.safeValue(params, 'stopLossPrice');
const takeProfitTriggerPrice = this.safeValue(params, 'takeProfitPrice');
const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRatio');
const isTrailingPercentOrder = trailingPercent !== undefined;
const isTriggerOrder = triggerPrice !== undefined;
const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
const isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
const request = this.createOrderRequest(symbol, type, side, amount, price, params);
let response = undefined;
if (market['spot']) {
if (isTriggerOrder) {
response = await this.privateSpotPostV2SpotTradePlacePlanOrder(request);
}
else if (marginMode === 'isolated') {
response = await this.privateMarginPostV2MarginIsolatedPlaceOrder(request);
}
else if (marginMode === 'cross') {
response = await this.privateMarginPostV2MarginCrossedPlaceOrder(request);
}
else {
response = await this.privateSpotPostV2SpotTradePlaceOrder(request);
}
}
else {
if (isTriggerOrder || isTrailingPercentOrder) {
response = await this.privateMixPostV2MixOrderPlacePlanOrder(request);
}
else if (isStopLossOrTakeProfitTrigger) {
response = await this.privateMixPostV2MixOrderPlaceTpslOrder(request);
}
else {
response = await this.privateMixPostV2MixOrderPlaceOrder(request);
}
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1645932209602,
// "data": {
// "orderId": "881669078313766912",
// "clientOid": "iauIBf#a45b595f96474d888d0ada"
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseOrder(data, market);
}
createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
const market = this.market(symbol);
let marketType = undefined;
let marginMode = undefined;
[marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
[marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
const request = {
'symbol': market['id'],
'orderType': type,
};
const isMarketOrder = type === 'market';
const triggerPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
const stopLossTriggerPrice = this.safeValue(params, 'stopLossPrice');
const takeProfitTriggerPrice = this.safeValue(params, 'takeProfitPrice');
const stopLoss = this.safeValue(params, 'stopLoss');
const takeProfit = this.safeValue(params, 'takeProfit');
const isTriggerOrder = triggerPrice !== undefined;
const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
const isStopLoss = stopLoss !== undefined;
const isTakeProfit = takeProfit !== undefined;
const isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
const isStopLossOrTakeProfit = isStopLoss || isTakeProfit;
const trailingTriggerPrice = this.safeString(params, 'trailingTriggerPrice', this.numberToString(price));
const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRatio');
const isTrailingPercentOrder = trailingPercent !== undefined;
if (this.sum(isTriggerOrder, isStopLossTriggerOrder, isTakeProfitTriggerOrder, isTrailingPercentOrder) > 1) {
throw new errors.ExchangeError(this.id + ' createOrder() params can only contain one of triggerPrice, stopLossPrice, takeProfitPrice, trailingPercent');
}
if (type === 'limit') {
request['price'] = this.priceToPrecision(symbol, price);
}
const triggerPriceType = this.safeString2(params, 'triggerPriceType', 'triggerType', 'mark_price');
const reduceOnly = this.safeBool(params, 'reduceOnly', false);
const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
const exchangeSpecificTifParam = this.safeString2(params, 'force', 'timeInForce');
let postOnly = undefined;
[postOnly, params] = this.handlePostOnly(isMarketOrder, exchangeSpecificTifParam === 'post_only', params);
const defaultTimeInForce = this.safeStringUpper(this.options, 'defaultTimeInForce');
const timeInForce = this.safeStringUpper(params, 'timeInForce', defaultTimeInForce);
if (postOnly) {
request['force'] = 'post_only';
}
else if (timeInForce === 'GTC') {
request['force'] = 'GTC';
}
else if (timeInForce === 'FOK') {
request['force'] = 'FOK';
}
else if (timeInForce === 'IOC') {
request['force'] = 'IOC';
}
params = this.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'postOnly', 'reduceOnly', 'clientOrderId', 'trailingPercent', 'trailingTriggerPrice']);
if ((marketType === 'swap') || (marketType === 'future')) {
request['marginCoin'] = market['settleId'];
request['size'] = this.amountToPrecision(symbol, amount);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (clientOrderId !== undefined) {
request['clientOid'] = clientOrderId;
}
if (isTriggerOrder || isStopLossOrTakeProfitTrigger || isTrailingPercentOrder) {
request['triggerType'] = triggerPriceType;
}
if (isTrailingPercentOrder) {
if (!isMarketOrder) {
throw new errors.BadRequest(this.id + ' createOrder() bitget trailing orders must be market orders');
}
if (trailingTriggerPrice === undefined) {
throw new errors.ArgumentsRequired(this.id + ' createOrder() bitget trailing orders must have a trailingTriggerPrice param');
}
request['planType'] = 'track_plan';
request['triggerPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
request['callbackRatio'] = trailingPercent;
}
else if (isTriggerOrder) {
request['planType'] = 'normal_plan';
request['triggerPrice'] = this.priceToPrecision(symbol, triggerPrice);
if (price !== undefined) {
request['executePrice'] = this.priceToPrecision(symbol, price);
}
if (isStopLoss) {
const slTriggerPrice = this.safeNumber2(stopLoss, 'triggerPrice', 'stopPrice');
request['stopLossTriggerPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
const slPrice = this.safeNumber(stopLoss, 'price');
request['stopLossExecutePrice'] = this.priceToPrecision(symbol, slPrice);
const slType = this.safeString(stopLoss, 'type', 'mark_price');
request['stopLossTriggerType'] = slType;
}
if (isTakeProfit) {
const tpTriggerPrice = this.safeNumber2(takeProfit, 'triggerPrice', 'stopPrice');
request['stopSurplusTriggerPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
const tpPrice = this.safeNumber(takeProfit, 'price');
request['stopSurplusExecutePrice'] = this.priceToPrecision(symbol, tpPrice);
const tpType = this.safeString(takeProfit, 'type', 'mark_price');
request['stopSurplusTriggerType'] = tpType;
}
}
else if (isStopLossOrTakeProfitTrigger) {
if (!isMarketOrder) {
throw new errors.ExchangeError(this.id + ' createOrder() bitget stopLoss or takeProfit orders must be market orders');
}
request['holdSide'] = (side === 'buy') ? 'long' : 'short';
if (isStopLossTriggerOrder) {
request['triggerPrice'] = this.priceToPrecision(symbol, stopLossTriggerPrice);
request['planType'] = 'pos_loss';
}
else if (isTakeProfitTriggerOrder) {
request['triggerPrice'] = this.priceToPrecision(symbol, takeProfitTriggerPrice);
request['planType'] = 'pos_profit';
}
}
else {
if (isStopLoss) {
const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice');
request['presetStopLossPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
}
if (isTakeProfit) {
const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
request['presetStopSurplusPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
}
}
if (!isStopLossOrTakeProfitTrigger) {
if (marginMode === undefined) {
marginMode = 'cross';
}
const marginModeRequest = (marginMode === 'cross') ? 'crossed' : 'isolated';
request['marginMode'] = marginModeRequest;
let hedged = undefined;
[hedged, params] = this.handleParamBool(params, 'hedged', false);
// backward compatibility for `oneWayMode`
let oneWayMode = undefined;
[oneWayMode, params] = this.handleParamBool(params, 'oneWayMode');
if (oneWayMode !== undefined) {
hedged = !oneWayMode;
}
let 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;
}
}
else if (marketType === 'spot') {
if (isStopLossOrTakeProfitTrigger || isStopLossOrTakeProfit) {
throw new errors.InvalidOrder(this.id + ' createOrder() does not support stop loss/take profit orders on spot markets, only swap markets');
}
request['side'] = side;
let quantity = undefined;
let planType = undefined;
let createMarketBuyOrderRequiresPrice = true;
[createMarketBuyOrderRequiresPrice, params] = this.handleOptionAndParams(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
if (isMarketOrder && (side === 'buy')) {
planType = 'total';
const cost = this.safeNumber(params, 'cost');
params = this.omit(params, 'cost');
if (cost !== undefined) {
quantity = this.costToPrecision(symbol, cost);
}
else if (createMarketBuyOrderRequiresPrice) {
if (price === undefined) {
throw new errors.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 {
const amountString = this.numberToString(amount);
const priceString = this.numberToString(price);
const quoteAmount = Precise["default"].stringMul(amountString, priceString);
quantity = this.costToPrecision(symbol, quoteAmount);
}
}
else {
quantity = this.costToPrecision(symbol, amount);
}
}
else {
planType = 'amount';
quantity = this.amountToPrecision(symbol, amount);
}
if (clientOrderId !== undefined) {
request['clientOid'] = clientOrderId;
}
if (marginMode !== undefined) {
request['loanType'] = 'normal';
if (isMarketOrder && (side === 'buy')) {
request['quoteSize'] = quantity;
}
else {
request['baseSize'] = quantity;
}
}
else {
if (quantity !== undefined) {
request['size'] = quantity;
}
if (triggerPrice !== undefined) {
request['planType'] = planType;
request['triggerType'] = triggerPriceType;
request['triggerPrice'] = this.priceToPrecision(symbol, triggerPrice);
if (price !== undefined) {
request['executePrice'] = this.priceToPrecision(symbol, price);
}
}
}
}
else {
throw new errors.NotSupported(this.id + ' createOrder() does not support ' + marketType + ' orders');
}
return this.extend(request, params);
}
/**
* @method
* @name bitget#createOrders
* @description 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
* @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 {object} [params] extra parameters specific to the api endpoint
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async createOrders(orders, params = {}) {
await this.loadMarkets();
const ordersRequests = [];
let symbol = undefined;
let marginMode = undefined;
for (let i = 0; i < orders.length; i++) {
const rawOrder = orders[i];
const marketId = this.safeString(rawOrder, 'symbol');
if (symbol === undefined) {
symbol = marketId;
}
else {
if (symbol !== marketId) {
throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
}
}
const type = this.safeString(rawOrder, 'type');
const side = this.safeString(rawOrder, 'side');
const amount = this.safeValue(rawOrder, 'amount');
const price = this.safeValue(rawOrder, 'price');
const orderParams = this.safeValue(rawOrder, 'params', {});
const marginResult = this.handleMarginModeAndParams('createOrders', orderParams);
const currentMarginMode = marginResult[0];
if (currentMarginMode !== undefined) {
if (marginMode === undefined) {
marginMode = currentMarginMode;
}
else {
if (marginMode !== currentMarginMode) {
throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same margin mode (isolated or cross)');
}
}
}
const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
ordersRequests.push(orderRequest);
}
const market = this.market(symbol);
const request = {
'symbol': market['id'],
'orderList': ordersRequests,
};
let response = undefined;
if ((market['swap']) || (market['future'])) {
if (marginMode === undefined) {
marginMode = 'cross';
}
const marginModeRequest = (marginMode === 'cross') ? 'crossed' : 'isolated';
request['marginMode'] = marginModeRequest;
request['marginCoin'] = market['settleId'];
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.privateMixPostV2MixOrderBatchPlaceOrder(request);
}
else if (marginMode === 'isolated') {
response = await this.privateMarginPostV2MarginIsolatedBatchPlaceOrder(request);
}
else if (marginMode === 'cross') {
response = await this.privateMarginPostV2MarginCrossedBatchPlaceOrder(request);
}
else {
response = await this.privateSpotPostV2SpotTradeBatchOrders(request);
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700703539416,
// "data": {
// "successList": [
// {
// "orderId": "1111397214281175046",
// "clientOid": "766d3fc3-7321-4406-a689-15c9987a2e75"
// },
// ],
// "failureList": [
// {
// "orderId": "",
// "clientOid": "d1b75cb3-cc15-4ede-ad4c-3937396f75ab",
// "errorMsg": "less than the minimum amount 5 USDT",
// "errorCode": "45110"
// },
// ]
// }
// }
//
const data = this.safeValue(response, 'data', {});
const failure = this.safeValue(data, 'failureList', []);
const orderInfo = this.safeValue(data, 'successList', []);
const both = this.arrayConcat(orderInfo, failure);
return this.parseOrders(both, market);
}
/**
* @method
* @name bitget#editOrder
* @description 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
* @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 {object} [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 {object} [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 {object} [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'
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'orderId': id,
};
const isMarketOrder = type === 'market';
const triggerPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
const isTriggerOrder = triggerPrice !== undefined;
const stopLossPrice = this.safeValue(params, 'stopLossPrice');
const isStopLossOrder = stopLossPrice !== undefined;
const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
const isTakeProfitOrder = takeProfitPrice !== undefined;
const stopLoss = this.safeValue(params, 'stopLoss');
const takeProfit = this.safeValue(params, 'takeProfit');
const isStopLoss = stopLoss !== undefined;
const isTakeProfit = takeProfit !== undefined;
const trailingTriggerPrice = this.safeString(params, 'trailingTriggerPrice', this.numberToString(price));
const trailingPercent = this.safeString2(params, 'trailingPercent', 'newCallbackRatio');
const isTrailingPercentOrder = trailingPercent !== undefined;
if (this.sum(isTriggerOrder, isStopLossOrder, isTakeProfitOrder, isTrailingPercentOrder) > 1) {
throw new errors.ExchangeError(this.id + ' editOrder() params can only contain one of triggerPrice, stopLossPrice, takeProfitPrice, trailingPercent');
}
const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
if (clientOrderId !== undefined) {
request['clientOid'] = clientOrderId;
}
params = this.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent']);
let response = undefined;
if (market['spot']) {
if (triggerPrice === undefined) {
throw new errors.NotSupported(this.id + ' editOrder() only supports plan/trigger spot orders');
}
const editMarketBuyOrderRequiresPrice = this.safeBool(this.options, 'editMarketBuyOrderRequiresPrice', true);
if (editMarketBuyOrderRequiresPrice && isMarketOrder && (side === 'buy')) {
if (price === undefined) {
throw new errors.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 {
const amountString = this.numberToString(amount);
const priceString = this.numberToString(price);
const cost = this.parseNumber(Precise["default"].stringMul(amountString, priceString));
request['size'] = this.priceToPrecision(symbol, cost);
}
}
else {
request['size'] = this.amountToPrecision(symbol, amount);
}
request['orderType'] = type;
request['triggerPrice'] = this.priceToPrecision(symbol, triggerPrice);
request['executePrice'] = this.priceToPrecision(symbol, price);
response = await this.privateSpotPostV2SpotTradeModifyPlanOrder(this.extend(request, params));
}
else {
if ((!market['swap']) && (!market['future'])) {
throw new errors.NotSupported(this.id + ' editOrder() does not support ' + market['type'] + ' orders');
}
request['symbol'] = market['id'];
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (!isTakeProfitOrder && !isStopLossOrder) {
request['newSize'] = this.amountToPrecision(symbol, amount);
if ((price !== undefined) && !isTrailingPercentOrder) {
request['newPrice'] = this.priceToPrecision(symbol, price);
}
}
if (isTrailingPercentOrder) {
if (!isMarketOrder) {
throw new errors.BadRequest(this.id + ' editOrder() bitget trailing orders must be market orders');
}
if (trailingTriggerPrice !== undefined) {
request['newTriggerPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
}
request['newCallbackRatio'] = trailingPercent;
response = await this.privateMixPostV2MixOrderModifyPlanOrder(this.extend(request, params));
}
else if (isTakeProfitOrder || isStopLossOrder) {
request['marginCoin'] = market['settleId'];
request['size'] = this.amountToPrecision(symbol, amount);
if (price !== undefined) {
request['executePrice'] = this.priceToPrecision(symbol, price);
}
if (isStopLossOrder) {
request['triggerPrice'] = this.priceToPrecision(symbol, stopLossPrice);
}
else if (isTakeProfitOrder) {
request['triggerPrice'] = this.priceToPrecision(symbol, takeProfitPrice);
}
response = await this.privateMixPostV2MixOrderModifyTpslOrder(this.extend(request, params));
}
else if (isTriggerOrder) {
request['newTriggerPrice'] = this.priceToPrecision(symbol, triggerPrice);
if (isStopLoss) {
const slTriggerPrice = this.safeNumber2(stopLoss, 'triggerPrice', 'stopPrice');
request['newStopLossTriggerPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
const slPrice = this.safeNumber(stopLoss, 'price');
request['newStopLossExecutePrice'] = this.priceToPrecision(symbol, slPrice);
const slType = this.safeString(stopLoss, 'type', 'mark_price');
request['newStopLossTriggerType'] = slType;
}
if (isTakeProfit) {
const tpTriggerPrice = this.safeNumber2(takeProfit, 'triggerPrice', 'stopPrice');
request['newSurplusTriggerPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
const tpPrice = this.safeNumber(takeProfit, 'price');
request['newStopSurplusExecutePrice'] = this.priceToPrecision(symbol, tpPrice);
const tpType = this.safeString(takeProfit, 'type', 'mark_price');
request['newStopSurplusTriggerType'] = tpType;
}
response = await this.privateMixPostV2MixOrderModifyPlanOrder(this.extend(request, params));
}
else {
const defaultNewClientOrderId = this.uuid();
const newClientOrderId = this.safeString2(params, 'newClientOid', 'newClientOrderId', defaultNewClientOrderId);
params = this.omit(params, 'newClientOrderId');
request['newClientOid'] = newClientOrderId;
if (isStopLoss) {
const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice');
request['newPresetStopLossPrice'] = this.priceToPrecision(symbol, slTriggerPrice);
}
if (isTakeProfit) {
const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
request['newPresetStopSurplusPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
}
response = await this.privateMixPostV2MixOrderModifyOrder(this.extend(request, params));
}
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700708275737,
// "data": {
// "clientOid": "abe95dbe-6081-4a6f-a2d3-ae49601cd459",
// "orderId": null
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseOrder(data, market);
}
/**
* @method
* @name bitget#cancelOrder
* @description 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
* @param {string} id order id
* @param {string} symbol unified symbol of the market the order was made in
* @param {object} [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
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async cancelOrder(id, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let marginMode = undefined;
let response = undefined;
[marginMode, params] = this.handleMarginModeAndParams('cancelOrder', params);
const request = {};
const trailing = this.safeValue(params, 'trailing');
const trigger = this.safeValue2(params, 'stop', 'trigger');
params = this.omit(params, ['stop', 'trigger', 'trailing']);
if (!(market['spot'] && trigger)) {
request['symbol'] = market['id'];
}
if (!((market['swap'] || market['future']) && trigger)) {
request['orderId'] = id;
}
if ((market['swap']) || (market['future'])) {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (trigger || trailing) {
const orderIdList = [];
const orderId = {
'orderId': id,
};
orderIdList.push(orderId);
request['orderIdList'] = orderIdList;
}
if (trailing) {
const planType = this.safeString(params, 'planType', 'track_plan');
request['planType'] = planType;
response = await this.privateMixPostV2MixOrderCancelPlanOrder(this.extend(request, params));
}
else if (trigger) {
response = await this.privateMixPostV2MixOrderCancelPlanOrder(this.extend(request, params));
}
else {
response = await this.privateMixPostV2MixOrderCancelOrder(this.extend(request, params));
}
}
else if (market['spot']) {
if (marginMode !== undefined) {
if (marginMode === 'isolated') {
response = await this.privateMarginPostV2MarginIsolatedCancelOrder(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginPostV2MarginCrossedCancelOrder(this.extend(request, params));
}
}
else {
if (trigger) {
response = await this.privateSpotPostV2SpotTradeCancelPlanOrder(this.extend(request, params));
}
else {
response = await this.privateSpotPostV2SpotTradeCancelOrder(this.extend(request, params));
}
}
}
else {
throw new errors.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": [
// {
// "clientOid": "1111428059067125760",
// "orderId": "1111428059067125761"
// }
// ],
// "failureList": []
// }
// }
//
// spot trigger
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700711728063,
// "data": {
// "result": "success"
// }
// }
//
const data = this.safeValue(response, 'data', {});
let order = undefined;
if ((market['swap'] || market['future']) && trigger) {
const orderInfo = this.safeValue(data, 'successList', []);
order = orderInfo[0];
}
else {
order = data;
}
return this.parseOrder(order, market);
}
/**
* @method
* @name bitget#cancelOrders
* @description 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
* @param {string[]} ids order ids
* @param {string} symbol unified market symbol, default is undefined
* @param {object} [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
* @returns {object} an array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async cancelOrders(ids, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('cancelOrders', params);
const trigger = this.safeValue2(params, 'stop', 'trigger');
params = this.omit(params, ['stop', 'trigger']);
const orderIdList = [];
for (let i = 0; i < ids.length; i++) {
const individualId = ids[i];
const orderId = {
'orderId': individualId,
};
orderIdList.push(orderId);
}
const request = {
'symbol': market['id'],
};
if (market['spot'] && (marginMode === undefined)) {
request['orderList'] = orderIdList;
}
else {
request['orderIdList'] = orderIdList;
}
let response = undefined;
if (market['spot']) {
if (marginMode !== undefined) {
if (marginMode === 'cross') {
response = await this.privateMarginPostV2MarginCrossedBatchCancelOrder(this.extend(request, params));
}
else {
response = await this.privateMarginPostV2MarginIsolatedBatchCancelOrder(this.extend(request, params));
}
}
else {
response = await this.privateSpotPostV2SpotTradeBatchCancelOrder(this.extend(request, params));
}
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (trigger) {
response = await this.privateMixPostV2MixOrderCancelPlanOrder(this.extend(request, params));
}
else {
response = await this.privateMixPostV2MixOrderBatchCancelOrders(this.extend(request, params));
}
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": "1680008815965",
// "data": {
// "successList": [
// {
// "orderId": "1024598257429823488",
// "clientOid": "876493ce-c287-4bfc-9f4a-8b1905881313"
// },
// ],
// "failureList": []
// }
// }
//
const data = this.safeValue(response, 'data', {});
const orders = this.safeList(data, 'successList', []);
return this.parseOrders(orders, market);
}
/**
* @method
* @name bitget#cancelAllOrders
* @description 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
* @param {string} symbol unified market symbol
* @param {object} [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
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async cancelAllOrders(symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' cancelAllOrders() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('cancelAllOrders', params);
const request = {
'symbol': market['id'],
};
const trigger = this.safeBool2(params, 'stop', 'trigger');
params = this.omit(params, ['stop', 'trigger']);
let response = undefined;
if (market['spot']) {
if (marginMode !== undefined) {
if (marginMode === 'cross') {
response = await this.privateMarginPostMarginV1CrossOrderBatchCancelOrder(this.extend(request, params));
}
else {
response = await this.privateMarginPostMarginV1IsolatedOrderBatchCancelOrder(this.extend(request, params));
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700717155622,
// "data": {
// "resultList": [
// {
// "orderId": "1111453253721796609",
// "clientOid": "2ae7fc8a4ff949b6b60d770ca3950e2d"
// },
// ],
// "failure": []
// }
// }
//
}
else {
if (trigger) {
const stopRequest = {
'symbolList': [market['id']],
};
response = await this.privateSpotPostV2SpotTradeBatchCancelPlanOrder(this.extend(stopRequest, params));
}
else {
response = await this.privateSpotPostV2SpotTradeCancelSymbolOrder(this.extend(request, params));
}
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700716953996,
// "data": {
// "symbol": "BTCUSDT"
// }
// }
//
const timestamp = this.safeInteger(response, 'requestTime');
const responseData = this.safeDict(response, 'data');
const marketId = this.safeString(responseData, 'symbol');
return [
this.safeOrder({
'info': response,
'symbol': this.safeSymbol(marketId, undefined, undefined, 'spot'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
}),
];
}
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
if (trigger) {
response = await this.privateMixPostV2MixOrderCancelPlanOrder(this.extend(request, params));
}
else {
response = await this.privateMixPostV2MixOrderBatchCancelOrders(this.extend(request, params));
}
// {
// "code": "00000",
// "msg": "success",
// "requestTime": "1680008815965",
// "data": {
// "successList": [
// {
// "orderId": "1024598257429823488",
// "clientOid": "876493ce-c287-4bfc-9f4a-8b1905881313"
// },
// ],
// "failureList": []
// }
// }
}
const data = this.safeDict(response, 'data');
const resultList = this.safeList2(data, 'resultList', 'successList');
const failureList = this.safeList2(data, 'failure', 'failureList');
const responseList = this.arrayConcat(resultList, failureList);
return this.parseOrders(responseList);
}
/**
* @method
* @name bitget#fetchOrder
* @description 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
* @param {string} id the order id
* @param {string} symbol unified symbol of the market the order was made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchOrder(id, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'orderId': id,
};
let response = undefined;
if (market['spot']) {
response = await this.privateSpotGetV2SpotTradeOrderInfo(this.extend(request, params));
}
else if (market['swap'] || market['future']) {
request['symbol'] = market['id'];
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.privateMixGetV2MixOrderDetail(this.extend(request, params));
}
else {
throw new errors.NotSupported(this.id + ' fetchOrder() does not support ' + market['type'] + ' orders');
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700719076263,
// "data": [
// {
// "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"
// }
// }
//
if (typeof response === 'string') {
response = JSON.parse(response);
}
const data = this.safeDict(response, 'data');
if ((data !== undefined)) {
if (!Array.isArray(data)) {
return this.parseOrder(data, market);
}
}
const dataList = this.safeList(response, 'data', []);
const first = this.safeDict(dataList, 0, {});
return this.parseOrder(first, market);
// const first = this.safeDict (data, 0, data);
// return this.parseOrder (first, market);
}
/**
* @method
* @name bitget#fetchOpenOrders
* @description 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
* @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 {object} [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
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let market = undefined;
let type = undefined;
let request = {};
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchOpenOrders', params);
if (symbol !== undefined) {
market = this.market(symbol);
request['symbol'] = market['id'];
const defaultType = this.safeString2(this.options, 'fetchOpenOrders', 'defaultType', 'spot');
const marketType = ('type' in market) ? market['type'] : defaultType;
type = this.safeString(params, 'type', marketType);
}
else {
const defaultType = this.safeString2(this.options, 'fetchOpenOrders', 'defaultType', 'spot');
type = this.safeString(params, 'type', defaultType);
}
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchOpenOrders', 'paginate');
if (paginate) {
let cursorReceived = undefined;
if (type === 'spot') {
if (marginMode !== undefined) {
cursorReceived = 'minId';
}
}
else {
cursorReceived = 'endId';
}
return await this.fetchPaginatedCallCursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, 'idLessThan');
}
let response = undefined;
const trailing = this.safeBool(params, 'trailing');
const trigger = this.safeBool2(params, 'stop', 'trigger');
const planTypeDefined = this.safeString(params, 'planType') !== undefined;
const isTrigger = (trigger || planTypeDefined);
params = this.omit(params, ['stop', 'trigger', 'trailing']);
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
if ((type === 'swap') || (type === 'future') || (marginMode !== undefined)) {
const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
params = this.omit(params, 'clientOrderId');
if (clientOrderId !== undefined) {
request['clientOid'] = clientOrderId;
}
}
let query = undefined;
query = this.omit(params, ['type']);
if (type === 'spot') {
if (marginMode !== undefined) {
if (since === undefined) {
since = this.milliseconds() - 7776000000;
request['startTime'] = since;
}
if (marginMode === 'isolated') {
response = await this.privateMarginGetV2MarginIsolatedOpenOrders(this.extend(request, query));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetV2MarginCrossedOpenOrders(this.extend(request, query));
}
}
else {
if (trigger) {
response = await this.privateSpotGetV2SpotTradeCurrentPlanOrder(this.extend(request, query));
}
else {
response = await this.privateSpotGetV2SpotTradeUnfilledOrders(this.extend(request, query));
}
}
}
else {
let productType = undefined;
[productType, query] = this.handleProductTypeAndParams(market, query);
request['productType'] = productType;
if (trailing) {
const planType = this.safeString(params, 'planType', 'track_plan');
request['planType'] = planType;
response = await this.privateMixGetV2MixOrderOrdersPlanPending(this.extend(request, query));
}
else if (isTrigger) {
const planType = this.safeString(query, 'planType', 'normal_plan');
request['planType'] = planType;
response = await this.privateMixGetV2MixOrderOrdersPlanPending(this.extend(request, query));
}
else {
response = await this.privateMixGetV2MixOrderOrdersPending(this.extend(request, query));
}
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700728123994,
// "data": [
// {
// "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": [
// {
// "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": [
// {
// "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": [
// {
// "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": [
// {
// "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"
// }
// }
//
const data = this.safeValue(response, 'data');
if (type === 'spot') {
if ((marginMode !== undefined) || trigger) {
const resultList = this.safeList(data, 'orderList', []);
return this.parseOrders(resultList, market, since, limit);
}
}
else {
const result = this.safeList(data, 'entrustedList', []);
return this.parseOrders(result, market, since, limit);
}
return this.parseOrders(data, market, since, limit);
}
/**
* @method
* @name bitget#fetchClosedOrders
* @description 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
* @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 {object} [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
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const orders = await this.fetchCanceledAndClosedOrders(symbol, since, limit, params);
return this.filterBy(orders, 'status', 'closed');
}
/**
* @method
* @name bitget#fetchCanceledOrders
* @description 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
* @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 {object} [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
* @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const orders = await this.fetchCanceledAndClosedOrders(symbol, since, limit, params);
return this.filterBy(orders, 'status', 'canceled');
}
/**
* @method
* @name bitget#fetchCanceledAndClosedOrders
* @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
* @description 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 {object} [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
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchCanceledAndClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let market = undefined;
let request = {};
if (symbol !== undefined) {
market = this.market(symbol);
request['symbol'] = market['id'];
}
let marketType = undefined;
[marketType, params] = this.handleMarketTypeAndParams('fetchCanceledAndClosedOrders', market, params);
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchCanceledAndClosedOrders', params);
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchCanceledAndClosedOrders', 'paginate');
if (paginate) {
let cursorReceived = undefined;
if (marketType === 'spot') {
if (marginMode !== undefined) {
cursorReceived = 'minId';
}
}
else {
cursorReceived = 'endId';
}
return await this.fetchPaginatedCallCursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, cursorReceived, 'idLessThan');
}
let response = undefined;
const trailing = this.safeBool(params, 'trailing');
const trigger = this.safeBool2(params, 'stop', 'trigger');
params = this.omit(params, ['stop', 'trigger', 'trailing']);
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
if ((marketType === 'swap') || (marketType === 'future') || (marginMode !== undefined)) {
const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
params = this.omit(params, 'clientOrderId');
if (clientOrderId !== undefined) {
request['clientOid'] = clientOrderId;
}
}
const now = this.milliseconds();
if (marketType === 'spot') {
if (marginMode !== undefined) {
if (since === undefined) {
since = now - 7776000000;
request['startTime'] = since;
}
if (marginMode === 'isolated') {
response = await this.privateMarginGetV2MarginIsolatedHistoryOrders(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetV2MarginCrossedHistoryOrders(this.extend(request, params));
}
}
else if (trigger) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchCanceledAndClosedOrders() requires a symbol argument');
}
const endTime = this.safeIntegerN(params, ['endTime', 'until']);
params = this.omit(params, ['until']);
if (since === undefined) {
since = now - 7776000000;
request['startTime'] = since;
}
if (endTime === undefined) {
request['endTime'] = now;
}
response = await this.privateSpotGetV2SpotTradeHistoryPlanOrder(this.extend(request, params));
}
else {
response = await this.privateSpotGetV2SpotTradeHistoryOrders(this.extend(request, params));
}
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
const planTypeDefined = this.safeString(params, 'planType') !== undefined;
if (trailing) {
const planType = this.safeString(params, 'planType', 'track_plan');
request['planType'] = planType;
response = await this.privateMixGetV2MixOrderOrdersPlanHistory(this.extend(request, params));
}
else if (trigger || planTypeDefined) {
const planType = this.safeString(params, 'planType', 'normal_plan');
request['planType'] = planType;
response = await this.privateMixGetV2MixOrderOrdersPlanHistory(this.extend(request, params));
}
else {
response = await this.privateMixGetV2MixOrderOrdersHistory(this.extend(request, params));
}
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700791085380,
// "data": [
// {
// "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": [
// {
// "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": [
// {
// "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": [
// {
// "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": [
// {
// "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"
// }
// }
//
const data = this.safeValue(response, 'data', {});
if (marketType === 'spot') {
if ((marginMode !== undefined) || trigger) {
return this.parseOrders(this.safeValue(data, 'orderList', []), market, since, limit);
}
}
else {
return this.parseOrders(this.safeValue(data, 'entrustedList', []), market, since, limit);
}
if (typeof response === 'string') {
response = JSON.parse(response);
}
const orders = this.safeList(response, 'data', []);
return this.parseOrders(orders, market, since, limit);
}
/**
* @method
* @name bitget#fetchLedger
* @description 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 undefined
* @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
* @param {int} [limit] max number of ledger entries to return, default is undefined
* @param {object} [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)
* @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
*/
async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const symbol = this.safeString(params, 'symbol');
params = this.omit(params, 'symbol');
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
}
let marketType = undefined;
[marketType, params] = this.handleMarketTypeAndParams('fetchLedger', market, params);
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchLedger', 'paginate');
if (paginate) {
let cursorReceived = undefined;
if (marketType !== 'spot') {
cursorReceived = 'endId';
}
return await this.fetchPaginatedCallCursor('fetchLedger', symbol, since, limit, params, cursorReceived, 'idLessThan');
}
let currency = undefined;
let request = {};
if (code !== undefined) {
currency = this.currency(code);
request['coin'] = currency['id'];
}
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
let response = undefined;
if (marketType === 'spot') {
response = await this.privateSpotGetV2SpotAccountBills(this.extend(request, params));
}
else {
if (symbol !== undefined) {
request['symbol'] = market['id'];
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.privateMixGetV2MixAccountBill(this.extend(request, params));
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700795836415,
// "data": [
// {
// "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": [
// {
// "billId": "1111499428100472833",
// "symbol": "",
// "amount": "-11.64958799",
// "fee": "0",
// "feeByCoupon": "",
// "businessType": "trans_to_exchange",
// "coin": "USDT",
// "cTime": "1700728034996"
// },
// ],
// "endId": "1098396773329305606"
// }
// }
//
const data = this.safeValue(response, 'data');
if ((marketType === 'swap') || (marketType === 'future')) {
const bills = this.safeValue(data, 'bills', []);
return this.parseLedger(bills, currency, since, limit);
}
return this.parseLedger(data, currency, since, limit);
}
parseLedgerEntry(item, currency = undefined) {
//
// 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"
// }
//
const currencyId = this.safeString(item, 'coin');
const code = this.safeCurrencyCode(currencyId, currency);
currency = this.safeCurrency(currencyId, currency);
const timestamp = this.safeInteger(item, 'cTime');
const after = this.safeNumber(item, 'balance');
const fee = this.safeNumber2(item, 'fees', 'fee');
const amountRaw = this.safeString2(item, 'size', 'amount');
const amount = this.parseNumber(Precise["default"].stringAbs(amountRaw));
let direction = 'in';
if (amountRaw.indexOf('-') >= 0) {
direction = 'out';
}
return this.safeLedgerEntry({
'info': item,
'id': this.safeString(item, 'billId'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'direction': direction,
'account': undefined,
'referenceId': undefined,
'referenceAccount': undefined,
'type': this.parseLedgerType(this.safeString(item, 'businessType')),
'currency': code,
'amount': amount,
'before': undefined,
'after': after,
'status': undefined,
'fee': {
'currency': code,
'cost': fee,
},
}, currency);
}
parseLedgerType(type) {
const types = {
'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.safeString(types, type, type);
}
/**
* @method
* @name bitget#fetchMyTrades
* @description 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
* @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 {object} [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.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)
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchMyTrades', params);
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate');
if (paginate) {
let cursorReceived = undefined;
if (market['spot']) {
if (marginMode !== undefined) {
cursorReceived = 'minId';
}
}
else {
cursorReceived = 'endId';
}
return await this.fetchPaginatedCallCursor('fetchMyTrades', symbol, since, limit, params, cursorReceived, 'idLessThan');
}
let response = undefined;
let request = {
'symbol': market['id'],
};
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
if (market['spot']) {
if (marginMode !== undefined) {
if (since === undefined) {
request['startTime'] = this.milliseconds() - 7776000000;
}
if (marginMode === 'isolated') {
response = await this.privateMarginGetV2MarginIsolatedFills(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetV2MarginCrossedFills(this.extend(request, params));
}
}
else {
response = await this.privateSpotGetV2SpotTradeFills(this.extend(request, params));
}
}
else {
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
response = await this.privateMixGetV2MixOrderFills(this.extend(request, params));
}
//
// spot
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700802995406,
// "data": [
// {
// "userId": "7264631750",
// "symbol": "BTCUSDT",
// "orderId": "1098394344925597696",
// "tradeId": "1098394344974925824",
// "orderType": "market",
// "side": "sell",
// "priceAvg": "28467.68",
// "size": "0.0002",
// "amount": "5.693536",
// "feeDetail": {
// "deduction": "no",
// "feeCoin": "USDT",
// "totalDeductionFee": "",
// "totalFee": "-0.005693536"
// },
// "tradeScope": "taker",
// "cTime": "1697603539699",
// "uTime": "1697603539754"
// }
// ]
// }
//
// spot margin
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700803176399,
// "data": {
// "fills": [
// {
// "orderId": "1099353730455318528",
// "tradeId": "1099353730627092481",
// "orderType": "market",
// "side": "sell",
// "priceAvg": "29543.7",
// "size": "0.0001",
// "amount": "2.95437",
// "tradeScope": "taker",
// "feeDetail": {
// "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": [
// {
// "tradeId": "1111468664328269825",
// "symbol": "BTCUSDT",
// "orderId": "1111468664264753162",
// "price": "37271.4",
// "baseVolume": "0.001",
// "feeDetail": [
// {
// "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"
// }
// }
//
const data = this.safeValue(response, 'data');
if ((market['swap']) || (market['future'])) {
const fillList = this.safeList(data, 'fillList', []);
return this.parseTrades(fillList, market, since, limit);
}
else if (marginMode !== undefined) {
const fills = this.safeList(data, 'fills', []);
return this.parseTrades(fills, market, since, limit);
}
return this.parseTrades(data, market, since, limit);
}
/**
* @method
* @name bitget#fetchPosition
* @description fetch data on a single open contract trade position
* @see https://www.bitget.com/api-doc/contract/position/get-single-position
* @param {string} symbol unified market symbol of the market the position is held in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
async fetchPosition(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'productType': productType,
};
const response = await this.privateMixGetV2MixPositionSinglePosition(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700807531673,
// "data": [
// {
// "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"
// }
// ]
// }
//
const data = this.safeList(response, 'data', []);
const first = this.safeDict(data, 0, {});
return this.parsePosition(first, market);
}
/**
* @method
* @name bitget#fetchPositions
* @description 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
* @param {string[]} [symbols] list of unified market symbols
* @param {object} [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' or 'privateMixGetV2MixPositionHistoryPosition'
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
async fetchPositions(symbols = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchPositions', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchPositions', undefined, undefined, undefined, params, 'endId', 'idLessThan');
}
let method = undefined;
const useHistoryEndpoint = this.safeBool(params, 'useHistoryEndpoint', false);
if (useHistoryEndpoint) {
method = 'privateMixGetV2MixPositionHistoryPosition';
}
else {
[method, params] = this.handleOptionAndParams(params, 'fetchPositions', 'method', 'privateMixGetV2MixPositionAllPosition');
}
let market = undefined;
if (symbols !== undefined) {
const first = this.safeString(symbols, 0);
market = this.market(first);
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'productType': productType,
};
let response = undefined;
let isHistory = false;
if (method === 'privateMixGetV2MixPositionAllPosition') {
let marginCoin = this.safeString(params, 'marginCoin', 'USDT');
if (symbols !== undefined) {
marginCoin = market['settleId'];
}
else if (productType === 'USDT-FUTURES') {
marginCoin = 'USDT';
}
else if (productType === 'USDC-FUTURES') {
marginCoin = 'USDC';
}
else if (productType === 'SUSDT-FUTURES') {
marginCoin = 'SUSDT';
}
else if (productType === 'SUSDC-FUTURES') {
marginCoin = 'SUSDC';
}
else if ((productType === 'SCOIN-FUTURES') || (productType === 'COIN-FUTURES')) {
if (marginCoin === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchPositions() requires a marginCoin parameter that matches the productType');
}
}
request['marginCoin'] = marginCoin;
response = await this.privateMixGetV2MixPositionAllPosition(this.extend(request, params));
}
else {
isHistory = true;
if (market !== undefined) {
request['symbol'] = market['id'];
}
response = await this.privateMixGetV2MixPositionHistoryPosition(this.extend(request, params));
}
//
// privateMixGetV2MixPositionAllPosition
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700807810221,
// "data": [
// {
// "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": [
// {
// "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"
// }
// }
//
let position = [];
if (!isHistory) {
position = this.safeList(response, 'data', []);
}
else {
const data = this.safeDict(response, 'data', {});
position = this.safeList(data, 'list', []);
}
const result = [];
for (let i = 0; i < position.length; i++) {
result.push(this.parsePosition(position[i], market));
}
symbols = this.marketSymbols(symbols);
return this.filterByArrayPositions(result, 'symbol', symbols, false);
}
parsePosition(position, market = undefined) {
//
// 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"
// }
//
// 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"
// }
//
const marketId = this.safeString(position, 'symbol');
market = this.safeMarket(marketId, market, undefined, 'contract');
const symbol = market['symbol'];
const timestamp = this.safeInteger2(position, 'cTime', 'ctime');
let marginMode = this.safeString(position, 'marginMode');
let collateral = undefined;
let initialMargin = undefined;
const unrealizedPnl = this.safeString(position, 'unrealizedPL');
const rawCollateral = this.safeString(position, 'marginSize');
if (marginMode === 'isolated') {
collateral = Precise["default"].stringAdd(rawCollateral, unrealizedPnl);
}
else if (marginMode === 'crossed') {
marginMode = 'cross';
initialMargin = rawCollateral;
}
const holdMode = this.safeString(position, 'posMode');
let hedged = undefined;
if (holdMode === 'hedge_mode') {
hedged = true;
}
else if (holdMode === 'one_way_mode') {
hedged = false;
}
const side = this.safeString(position, 'holdSide');
const leverage = this.safeString(position, 'leverage');
const contractSizeNumber = this.safeValue(market, 'contractSize');
const contractSize = this.numberToString(contractSizeNumber);
const baseAmount = this.safeString(position, 'total');
const entryPrice = this.safeString2(position, 'openPriceAvg', 'openAvgPrice');
const maintenanceMarginPercentage = this.safeString(position, 'keepMarginRate');
const openNotional = Precise["default"].stringMul(entryPrice, baseAmount);
if (initialMargin === undefined) {
initialMargin = Precise["default"].stringDiv(openNotional, leverage);
}
let contracts = this.parseNumber(Precise["default"].stringDiv(baseAmount, contractSize));
if (contracts === undefined) {
contracts = this.safeNumber(position, 'closeTotalPos');
}
const markPrice = this.safeString(position, 'markPrice');
const notional = Precise["default"].stringMul(baseAmount, markPrice);
const initialMarginPercentage = Precise["default"].stringDiv(initialMargin, notional);
let liquidationPrice = this.parseNumber(this.omitZero(this.safeString(position, 'liquidationPrice')));
const calcTakerFeeRate = '0.0006';
const calcTakerFeeMult = '0.9994';
if ((liquidationPrice === undefined) && (marginMode === 'isolated') && Precise["default"].stringGt(baseAmount, '0')) {
let signedMargin = Precise["default"].stringDiv(rawCollateral, baseAmount);
let signedMmp = maintenanceMarginPercentage;
if (side === 'short') {
signedMargin = Precise["default"].stringNeg(signedMargin);
signedMmp = Precise["default"].stringNeg(signedMmp);
}
let mmrMinusOne = Precise["default"].stringSub('1', signedMmp);
let numerator = Precise["default"].stringSub(entryPrice, signedMargin);
if (side === 'long') {
mmrMinusOne = Precise["default"].stringMul(mmrMinusOne, calcTakerFeeMult);
}
else {
numerator = Precise["default"].stringMul(numerator, calcTakerFeeMult);
}
liquidationPrice = this.parseNumber(Precise["default"].stringDiv(numerator, mmrMinusOne));
}
const feeToClose = Precise["default"].stringMul(notional, calcTakerFeeRate);
const maintenanceMargin = Precise["default"].stringAdd(Precise["default"].stringMul(maintenanceMarginPercentage, notional), feeToClose);
const percentage = Precise["default"].stringMul(Precise["default"].stringDiv(unrealizedPnl, initialMargin, 4), '100');
return this.safePosition({
'info': position,
'id': this.safeString(position, 'orderId'),
'symbol': symbol,
'notional': this.parseNumber(notional),
'marginMode': marginMode,
'liquidationPrice': liquidationPrice,
'entryPrice': this.parseNumber(entryPrice),
'unrealizedPnl': this.parseNumber(unrealizedPnl),
'realizedPnl': this.safeNumber(position, 'pnl'),
'percentage': this.parseNumber(percentage),
'contracts': contracts,
'contractSize': contractSizeNumber,
'markPrice': this.parseNumber(markPrice),
'lastPrice': this.safeNumber(position, 'closeAvgPrice'),
'side': side,
'hedged': hedged,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'lastUpdateTimestamp': this.safeInteger(position, 'utime'),
'maintenanceMargin': this.parseNumber(maintenanceMargin),
'maintenanceMarginPercentage': this.parseNumber(maintenanceMarginPercentage),
'collateral': this.parseNumber(collateral),
'initialMargin': this.parseNumber(initialMargin),
'initialMarginPercentage': this.parseNumber(initialMarginPercentage),
'leverage': this.parseNumber(leverage),
'marginRatio': this.safeNumber(position, 'marginRatio'),
'stopLossPrice': undefined,
'takeProfitPrice': undefined,
});
}
/**
* @method
* @name bitget#fetchFundingRateHistory
* @description fetches historical funding rate prices
* @see https://www.bitget.com/api-doc/contract/market/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 {object} [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 [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
*/
async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
}
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallIncremental('fetchFundingRateHistory', symbol, since, limit, params, 'pageNo', 100);
}
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'productType': productType,
// 'pageSize': limit, // default 20
// 'pageNo': 1,
};
if (limit !== undefined) {
request['pageSize'] = limit;
}
const response = await this.publicMixGetV2MixMarketHistoryFundRate(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1652406728393,
// "data": [
// {
// "symbol": "BTCUSDT",
// "fundingRate": "-0.0003",
// "fundingTime": "1652396400000"
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const rates = [];
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const marketId = this.safeString(entry, 'symbol');
const symbolInner = this.safeSymbol(marketId, market);
const timestamp = this.safeInteger(entry, 'fundingTime');
rates.push({
'info': entry,
'symbol': symbolInner,
'fundingRate': this.safeNumber(entry, 'fundingRate'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
});
}
const sorted = this.sortBy(rates, 'timestamp');
return this.filterBySymbolSinceLimit(sorted, market['symbol'], since, limit);
}
/**
* @method
* @name bitget#fetchFundingRate
* @description 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
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.method] either (default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
*/
async fetchFundingRate(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
if (!market['swap']) {
throw new errors.BadSymbol(this.id + ' fetchFundingRate() supports swap contracts only');
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'productType': productType,
};
let method = undefined;
[method, params] = this.handleOptionAndParams(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate');
let response = undefined;
if (method === 'publicMixGetV2MixMarketCurrentFundRate') {
response = await this.publicMixGetV2MixMarketCurrentFundRate(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1745500709429,
// "data": [
// {
// "symbol": "BTCUSDT",
// "fundingRate": "-0.000013",
// "fundingRateInterval": "8",
// "nextUpdate": "1745510400000",
// "minFundingRate": "-0.003",
// "maxFundingRate": "0.003"
// }
// ]
// }
//
}
else if (method === 'publicMixGetV2MixMarketFundingTime') {
response = await this.publicMixGetV2MixMarketFundingTime(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1745402092428,
// "data": [
// {
// "symbol": "BTCUSDT",
// "nextFundingTime": "1745424000000",
// "ratePeriod": "8"
// }
// ]
// }
//
}
const data = this.safeList(response, 'data', []);
return this.parseFundingRate(data[0], market);
}
/**
* @method
* @name bitget#fetchFundingRates
* @description 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 {object} [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'
* @returns {object} a dictionary of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rates-structure}, indexed by market symbols
*/
async fetchFundingRates(symbols = undefined, params = {}) {
await this.loadMarkets();
let market = undefined;
if (symbols !== undefined) {
const symbol = this.safeValue(symbols, 0);
market = this.market(symbol);
}
const request = {};
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
request['productType'] = productType;
const response = await this.publicMixGetV2MixMarketTickers(this.extend(request, params));
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700533773477,
// "data": [
// {
// "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.marketSymbols(symbols);
const data = this.safeList(response, 'data', []);
return this.parseFundingRates(data, symbols);
}
parseFundingRate(contract, market = undefined) {
//
// fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate
//
// {
// "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"
// }
//
const marketId = this.safeString(contract, 'symbol');
const symbol = this.safeSymbol(marketId, market, undefined, 'swap');
const fundingTimestamp = this.safeInteger2(contract, 'nextFundingTime', 'nextUpdate');
const interval = this.safeString2(contract, 'ratePeriod', 'fundingRateInterval');
const timestamp = this.safeInteger(contract, 'ts');
const markPrice = this.safeNumber(contract, 'markPrice');
const indexPrice = this.safeNumber(contract, 'indexPrice');
let intervalString = undefined;
if (interval !== undefined) {
intervalString = interval + 'h';
}
return {
'info': contract,
'symbol': symbol,
'markPrice': markPrice,
'indexPrice': indexPrice,
'interestRate': undefined,
'estimatedSettlePrice': undefined,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'fundingRate': this.safeNumber(contract, 'fundingRate'),
'fundingTimestamp': fundingTimestamp,
'fundingDatetime': this.iso8601(fundingTimestamp),
'nextFundingRate': undefined,
'nextFundingTimestamp': undefined,
'nextFundingDatetime': undefined,
'previousFundingRate': undefined,
'previousFundingTimestamp': undefined,
'previousFundingDatetime': undefined,
'interval': intervalString,
};
}
/**
* @method
* @name bitget#fetchFundingHistory
* @description 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 {object} [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)
* @returns {object[]} a list of [funding history structures]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
*/
async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchFundingHistory() requires a symbol argument');
}
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchFundingHistory', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchFundingHistory', symbol, since, limit, params, 'endId', 'idLessThan');
}
const market = this.market(symbol);
if (!market['swap']) {
throw new errors.BadSymbol(this.id + ' fetchFundingHistory() supports swap contracts only');
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
let request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'businessType': 'contract_settle_fee',
'productType': productType,
};
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.privateMixGetV2MixAccountBill(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700795977890,
// "data": {
// "bills": [
// {
// "billId": "1111499428100472833",
// "symbol": "BTCUSDT",
// "amount": "-0.004992",
// "fee": "0",
// "feeByCoupon": "",
// "businessType": "contract_settle_fee",
// "coin": "USDT",
// "cTime": "1700728034996"
// },
// ],
// "endId": "1098396773329305606"
// }
// }
//
const data = this.safeValue(response, 'data', {});
const result = this.safeValue(data, 'bills', []);
return this.parseFundingHistories(result, market, since, limit);
}
parseFundingHistory(contract, market = undefined) {
//
// {
// "billId": "1111499428100472833",
// "symbol": "BTCUSDT",
// "amount": "-0.004992",
// "fee": "0",
// "feeByCoupon": "",
// "businessType": "contract_settle_fee",
// "coin": "USDT",
// "cTime": "1700728034996"
// }
//
const marketId = this.safeString(contract, 'symbol');
const currencyId = this.safeString(contract, 'coin');
const timestamp = this.safeInteger(contract, 'cTime');
return {
'info': contract,
'symbol': this.safeSymbol(marketId, market, undefined, 'swap'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'code': this.safeCurrencyCode(currencyId),
'amount': this.safeNumber(contract, 'amount'),
'id': this.safeString(contract, 'billId'),
};
}
parseFundingHistories(contracts, market = undefined, since = undefined, limit = undefined) {
const result = [];
for (let i = 0; i < contracts.length; i++) {
const contract = contracts[i];
const business = this.safeString(contract, 'businessType');
if (business !== 'contract_settle_fee') {
continue;
}
result.push(this.parseFundingHistory(contract, market));
}
const sorted = this.sortBy(result, 'timestamp');
let symbol = undefined;
if (market !== undefined) {
symbol = market['symbol'];
}
return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
}
async modifyMarginHelper(symbol, amount, type, params = {}) {
await this.loadMarkets();
const holdSide = this.safeString(params, 'holdSide');
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'amount': this.amountToPrecision(symbol, amount),
'holdSide': holdSide,
'productType': productType,
};
params = this.omit(params, 'holdSide');
const response = await this.privateMixPostV2MixAccountSetMargin(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700813444618,
// "data": ""
// }
//
return this.extend(this.parseMarginModification(response, market), {
'amount': this.parseNumber(amount),
'type': type,
});
}
parseMarginModification(data, market = undefined) {
//
// addMargin/reduceMargin
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700813444618,
// "data": ""
// }
//
const errorCode = this.safeString(data, 'code');
const status = (errorCode === '00000') ? 'ok' : 'failed';
return {
'info': data,
'symbol': market['symbol'],
'type': undefined,
'marginMode': 'isolated',
'amount': undefined,
'total': undefined,
'code': market['settle'],
'status': status,
'timestamp': undefined,
'datetime': undefined,
};
}
/**
* @method
* @name bitget#reduceMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
*/
async reduceMargin(symbol, amount, params = {}) {
if (amount > 0) {
throw new errors.BadRequest(this.id + ' reduceMargin() amount parameter must be a negative value');
}
const holdSide = this.safeString(params, 'holdSide');
if (holdSide === undefined) {
throw new errors.ArgumentsRequired(this.id + ' reduceMargin() requires a holdSide parameter, either long or short');
}
return await this.modifyMarginHelper(symbol, amount, 'reduce', params);
}
/**
* @method
* @name bitget#addMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
*/
async addMargin(symbol, amount, params = {}) {
const holdSide = this.safeString(params, 'holdSide');
if (holdSide === undefined) {
throw new errors.ArgumentsRequired(this.id + ' addMargin() requires a holdSide parameter, either long or short');
}
return await this.modifyMarginHelper(symbol, amount, 'add', params);
}
/**
* @method
* @name bitget#fetchLeverage
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
*/
async fetchLeverage(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'productType': productType,
};
const response = 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": ""
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseLeverage(data, market);
}
parseLeverage(leverage, market = undefined) {
const isCrossMarginMode = this.safeString(leverage, 'marginMode') === 'crossed';
const longLevKey = isCrossMarginMode ? 'crossedMarginLeverage' : 'isolatedLongLever';
const shortLevKey = isCrossMarginMode ? 'crossedMarginLeverage' : 'isolatedShortLever';
return {
'info': leverage,
'symbol': market['symbol'],
'marginMode': isCrossMarginMode ? 'cross' : 'isolated',
'longLeverage': this.safeInteger(leverage, longLevKey),
'shortLeverage': this.safeInteger(leverage, shortLevKey),
};
}
/**
* @method
* @name bitget#setLeverage
* @description set the level of leverage for a market
* @see https://www.bitget.com/api-doc/contract/account/Change-Leverage
* @param {int} leverage the rate of leverage
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.holdSide] *isolated only* position direction, 'long' or 'short'
* @returns {object} response from the exchange
*/
async setLeverage(leverage, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'leverage': this.numberToString(leverage),
'productType': productType,
// 'holdSide': 'long',
};
const response = 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;
}
/**
* @method
* @name bitget#setMarginMode
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} response from the exchange
*/
async setMarginMode(marginMode, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
}
marginMode = marginMode.toLowerCase();
if (marginMode === 'cross') {
marginMode = 'crossed';
}
if ((marginMode !== 'isolated') && (marginMode !== 'crossed')) {
throw new errors.ArgumentsRequired(this.id + ' setMarginMode() marginMode must be either isolated or crossed (cross)');
}
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'marginMode': marginMode,
'productType': productType,
};
const response = 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;
}
/**
* @method
* @name bitget#setPositionMode
* @description set hedged to true or false for a market
* @see https://www.bitget.com/api-doc/contract/account/Change-Hold-Mode
* @param {bool} hedged set to true to use dualSidePosition
* @param {string} symbol not used by bitget setPositionMode ()
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.productType] required if symbol is undefined: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
* @returns {object} response from the exchange
*/
async setPositionMode(hedged, symbol = undefined, params = {}) {
await this.loadMarkets();
const posMode = hedged ? 'hedge_mode' : 'one_way_mode';
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'posMode': posMode,
'productType': productType,
};
const response = await this.privateMixPostV2MixAccountSetPositionMode(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700865608009,
// "data": {
// "posMode": "hedge_mode"
// }
// }
//
return response;
}
/**
* @method
* @name bitget#fetchOpenInterest
* @description retrieves the open interest of a contract trading pair
* @see https://www.bitget.com/api-doc/contract/market/Get-Open-Interest
* @param {string} symbol unified CCXT market symbol
* @param {object} [params] exchange specific parameters
* @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
*/
async fetchOpenInterest(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
if (!market['contract']) {
throw new errors.BadRequest(this.id + ' fetchOpenInterest() supports contract markets only');
}
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'productType': productType,
};
const response = await this.publicMixGetV2MixMarketOpenInterest(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700866041022,
// "data": {
// "openInterestList": [
// {
// "symbol": "BTCUSDT",
// "size": "52234.134"
// }
// ],
// "ts": "1700866041023"
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseOpenInterest(data, market);
}
parseOpenInterest(interest, market = undefined) {
//
// {
// "openInterestList": [
// {
// "symbol": "BTCUSDT",
// "size": "52234.134"
// }
// ],
// "ts": "1700866041023"
// }
//
const data = this.safeValue(interest, 'openInterestList', []);
const timestamp = this.safeInteger(interest, 'ts');
const marketId = this.safeString(data[0], 'symbol');
return this.safeOpenInterest({
'symbol': this.safeSymbol(marketId, market, undefined, 'contract'),
'openInterestAmount': this.safeNumber(data[0], 'size'),
'openInterestValue': undefined,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'info': interest,
}, market);
}
/**
* @method
* @name bitget#fetchTransfers
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch entries for
* @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
if (code === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchTransfers() requires a code argument');
}
await this.loadMarkets();
let type = undefined;
[type, params] = this.handleMarketTypeAndParams('fetchTransfers', undefined, params);
const fromAccount = this.safeString(params, 'fromAccount', type);
params = this.omit(params, 'fromAccount');
const accountsByType = this.safeValue(this.options, 'accountsByType', {});
type = this.safeString(accountsByType, fromAccount);
const currency = this.currency(code);
let request = {
'coin': currency['id'],
'fromType': type,
};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
[request, params] = this.handleUntilOption('endTime', request, params);
const response = await this.privateSpotGetV2SpotAccountTransferRecords(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700873854651,
// "data": [
// {
// "coin": "USDT",
// "status": "Successful",
// "toType": "crossed_margin",
// "toSymbol": "",
// "fromType": "spot",
// "fromSymbol": "",
// "size": "11.64958799",
// "ts": "1700729673028",
// "clientOid": "1111506298504744960",
// "transferId": "24930940"
// },
// ]
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTransfers(data, currency, since, limit);
}
/**
* @method
* @name bitget#transfer
* @description 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 {object} [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
* @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
async transfer(code, amount, fromAccount, toAccount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const accountsByType = this.safeValue(this.options, 'accountsByType', {});
const fromType = this.safeString(accountsByType, fromAccount);
const toType = this.safeString(accountsByType, toAccount);
const request = {
'fromType': fromType,
'toType': toType,
'amount': amount,
'coin': currency['id'],
};
const symbol = this.safeString(params, 'symbol');
params = this.omit(params, 'symbol');
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
request['symbol'] = market['id'];
}
const response = await this.privateSpotPostV2SpotWalletTransfer(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700874302021,
// "data": {
// "transferId": "1112112916581847040",
// "clientOrderId": null
// }
// }
//
const data = this.safeValue(response, 'data', {});
data['ts'] = this.safeInteger(response, 'requestTime');
return this.parseTransfer(data, currency);
}
parseTransfer(transfer, currency = undefined) {
//
// 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"
// }
//
const timestamp = this.safeInteger(transfer, 'ts');
const status = this.safeStringLower(transfer, 'status');
const currencyId = this.safeString(transfer, 'coin');
const fromAccountRaw = this.safeString(transfer, 'fromType');
const accountsById = this.safeValue(this.options, 'accountsById', {});
const fromAccount = this.safeString(accountsById, fromAccountRaw, fromAccountRaw);
const toAccountRaw = this.safeString(transfer, 'toType');
const toAccount = this.safeString(accountsById, toAccountRaw, toAccountRaw);
return {
'info': transfer,
'id': this.safeString(transfer, 'transferId'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'currency': this.safeCurrencyCode(currencyId, currency),
'amount': this.safeNumber(transfer, 'size'),
'fromAccount': fromAccount,
'toAccount': toAccount,
'status': this.parseTransferStatus(status),
};
}
parseTransferStatus(status) {
const statuses = {
'successful': 'ok',
};
return this.safeString(statuses, status, status);
}
parseDepositWithdrawFee(fee, currency = undefined) {
//
// {
// "chains": [
// {
// "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""
// }
//
const chains = this.safeValue(fee, 'chains', []);
const chainsLength = chains.length;
const result = {
'info': fee,
'withdraw': {
'fee': undefined,
'percentage': undefined,
},
'deposit': {
'fee': undefined,
'percentage': undefined,
},
'networks': {},
};
for (let i = 0; i < chainsLength; i++) {
const chain = chains[i];
const networkId = this.safeString(chain, 'chain');
const currencyCode = this.safeString(currency, 'code');
const networkCode = this.networkIdToCode(networkId, currencyCode);
result['networks'][networkCode] = {
'deposit': { 'fee': undefined, 'percentage': undefined },
'withdraw': { 'fee': this.safeNumber(chain, 'withdrawFee'), 'percentage': false },
};
if (chainsLength === 1) {
result['withdraw']['fee'] = this.safeNumber(chain, 'withdrawFee');
result['withdraw']['percentage'] = false;
}
}
return result;
}
/**
* @method
* @name bitget#fetchDepositWithdrawFees
* @description fetch deposit and withdraw fees
* @see https://www.bitget.com/api-doc/spot/market/Get-Coin-List
* @param {string[]|undefined} codes list of unified currency codes
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure}
*/
async fetchDepositWithdrawFees(codes = undefined, params = {}) {
await this.loadMarkets();
const response = await this.publicSpotGetV2SpotPublicCoins(params);
//
// {
// "code": "00000",
// "data": [
// {
// "chains": [
// {
// "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"
// }
//
const data = this.safeList(response, 'data', []);
return this.parseDepositWithdrawFees(data, codes, 'coin');
}
/**
* @method
* @name bitget#borrowCrossMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
*/
async borrowCrossMargin(code, amount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'coin': currency['id'],
'borrowAmount': this.currencyToPrecision(code, amount),
};
const response = await this.privateMarginPostV2MarginCrossedAccountBorrow(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700876470931,
// "data": {
// "loanId": "1112122013642272769",
// "coin": "USDT",
// "borrowAmount": "4"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.parseMarginLoan(data, currency);
}
/**
* @method
* @name bitget#borrowIsolatedMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
*/
async borrowIsolatedMargin(symbol, code, amount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const market = this.market(symbol);
const request = {
'coin': currency['id'],
'borrowAmount': this.currencyToPrecision(code, amount),
'symbol': market['id'],
};
const response = await this.privateMarginPostV2MarginIsolatedAccountBorrow(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700877255605,
// "data": {
// "loanId": "1112125304879067137",
// "symbol": "BTCUSDT",
// "coin": "USDT",
// "borrowAmount": "4"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.parseMarginLoan(data, currency, market);
}
/**
* @method
* @name bitget#repayIsolatedMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
*/
async repayIsolatedMargin(symbol, code, amount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const market = this.market(symbol);
const request = {
'coin': currency['id'],
'repayAmount': this.currencyToPrecision(code, amount),
'symbol': market['id'],
};
const response = 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"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.parseMarginLoan(data, currency, market);
}
/**
* @method
* @name bitget#repayCrossMargin
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
*/
async repayCrossMargin(code, amount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'coin': currency['id'],
'repayAmount': this.currencyToPrecision(code, amount),
};
const response = await this.privateMarginPostV2MarginCrossedAccountRepay(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700876704885,
// "data": {
// "remainDebtAmount": "0",
// "repayId": "1112122994945830912",
// "coin": "USDT",
// "repayAmount": "4.00006834"
// }
// }
//
const data = this.safeValue(response, 'data', {});
return this.parseMarginLoan(data, currency);
}
parseMarginLoan(info, currency = undefined, market = undefined) {
//
// 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"
// }
//
const currencyId = this.safeString(info, 'coin');
const marketId = this.safeString(info, 'symbol');
let symbol = undefined;
if (marketId !== undefined) {
symbol = this.safeSymbol(marketId, market, undefined, 'spot');
}
return {
'id': this.safeString2(info, 'loanId', 'repayId'),
'currency': this.safeCurrencyCode(currencyId, currency),
'amount': this.safeNumber2(info, 'borrowAmount', 'repayAmount'),
'symbol': symbol,
'timestamp': undefined,
'datetime': undefined,
'info': info,
};
}
/**
* @method
* @name bitget#fetchMyLiquidations
* @description 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 {object} [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)
* @returns {object} an array of [liquidation structures]{@link https://docs.ccxt.com/#/?id=liquidation-structure}
*/
async fetchMyLiquidations(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchMyLiquidations', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchMyLiquidations', symbol, since, limit, params, 'minId', 'idLessThan');
}
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
}
let type = undefined;
[type, params] = this.handleMarketTypeAndParams('fetchMyLiquidations', market, params);
if (type !== 'spot') {
throw new errors.NotSupported(this.id + ' fetchMyLiquidations() supports spot margin markets only');
}
let request = {};
[request, params] = this.handleUntilOption('endTime', request, params);
if (since !== undefined) {
request['startTime'] = since;
}
else {
request['startTime'] = this.milliseconds() - 7776000000;
}
if (limit !== undefined) {
request['limit'] = limit;
}
let response = undefined;
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchMyLiquidations', params, 'cross');
if (marginMode === 'isolated') {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchMyLiquidations() requires a symbol argument');
}
request['symbol'] = market['id'];
response = await this.privateMarginGetV2MarginIsolatedLiquidationHistory(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetV2MarginCrossedLiquidationHistory(this.extend(request, params));
}
//
// isolated
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1698114119193,
// "data": {
// "resultList": [
// {
// "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": [
// {
// "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"
// }
// }
//
const data = this.safeValue(response, 'data', {});
const liquidations = this.safeList(data, 'resultList', []);
return this.parseLiquidations(liquidations, market, since, limit);
}
parseLiquidation(liquidation, market = undefined) {
//
// 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"
// }
//
const marketId = this.safeString(liquidation, 'symbol');
const timestamp = this.safeInteger(liquidation, 'liqEndTime');
const liquidationFee = this.safeString2(liquidation, 'LiqFee', 'liqFee');
const totalDebt = this.safeString(liquidation, 'totalDebt');
const quoteValueString = Precise["default"].stringAdd(liquidationFee, totalDebt);
return this.safeLiquidation({
'info': liquidation,
'symbol': this.safeSymbol(marketId, market),
'contracts': undefined,
'contractSize': undefined,
'price': undefined,
'baseValue': undefined,
'quoteValue': this.parseNumber(quoteValueString),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
});
}
/**
* @method
* @name bitget#fetchIsolatedBorrowRate
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [isolated borrow rate structure]{@link https://docs.ccxt.com/#/?id=isolated-borrow-rate-structure}
*/
async fetchIsolatedBorrowRate(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const response = await this.privateMarginGetV2MarginIsolatedInterestRateAndLimit(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700878692567,
// "data": [
// {
// "symbol": "BTCUSDT",
// "leverage": "10",
// "baseCoin": "BTC",
// "baseTransferable": true,
// "baseBorrowable": true,
// "baseDailyInterestRate": "0.00007",
// "baseAnnuallyInterestRate": "0.02555",
// "baseMaxBorrowableAmount": "27",
// "baseVipList": [
// {"level":"0","dailyInterestRate":"0.00007","limit":"27","annuallyInterestRate":"0.02555","discountRate":"1"},
// {"level":"1","dailyInterestRate":"0.0000679","limit":"27.81","annuallyInterestRate":"0.0247835","discountRate":"0.97"},
// {"level":"2","dailyInterestRate":"0.0000644","limit":"29.16","annuallyInterestRate":"0.023506","discountRate":"0.92"},
// {"level":"3","dailyInterestRate":"0.0000602","limit":"31.32","annuallyInterestRate":"0.021973","discountRate":"0.86"},
// {"level":"4","dailyInterestRate":"0.0000525","limit":"35.91","annuallyInterestRate":"0.0191625","discountRate":"0.75"},
// {"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": [
// {"level":"0","dailyInterestRate":"0.00041095","limit":"300000","annuallyInterestRate":"0.14999675","discountRate":"1"},
// {"level":"1","dailyInterestRate":"0.00039863","limit":"309000","annuallyInterestRate":"0.14549995","discountRate":"0.97"},
// {"level":"2","dailyInterestRate":"0.00037808","limit":"324000","annuallyInterestRate":"0.1379992","discountRate":"0.92"},
// {"level":"3","dailyInterestRate":"0.00035342","limit":"348000","annuallyInterestRate":"0.1289983","discountRate":"0.86"},
// {"level":"4","dailyInterestRate":"0.00030822","limit":"399000","annuallyInterestRate":"0.1125003","discountRate":"0.75"},
// {"level":"5","dailyInterestRate":"0.00024657","limit":"498000","annuallyInterestRate":"0.08999805","discountRate":"0.6"}
// ]
// }
// ]
// }
//
const timestamp = this.safeInteger(response, 'requestTime');
const data = this.safeValue(response, 'data', []);
const first = this.safeValue(data, 0, {});
first['timestamp'] = timestamp;
return this.parseIsolatedBorrowRate(first, market);
}
parseIsolatedBorrowRate(info, market = undefined) {
//
// {
// "symbol": "BTCUSDT",
// "leverage": "10",
// "baseCoin": "BTC",
// "baseTransferable": true,
// "baseBorrowable": true,
// "baseDailyInterestRate": "0.00007",
// "baseAnnuallyInterestRate": "0.02555",
// "baseMaxBorrowableAmount": "27",
// "baseVipList": [
// {"level":"0","dailyInterestRate":"0.00007","limit":"27","annuallyInterestRate":"0.02555","discountRate":"1"},
// {"level":"1","dailyInterestRate":"0.0000679","limit":"27.81","annuallyInterestRate":"0.0247835","discountRate":"0.97"},
// {"level":"2","dailyInterestRate":"0.0000644","limit":"29.16","annuallyInterestRate":"0.023506","discountRate":"0.92"},
// {"level":"3","dailyInterestRate":"0.0000602","limit":"31.32","annuallyInterestRate":"0.021973","discountRate":"0.86"},
// {"level":"4","dailyInterestRate":"0.0000525","limit":"35.91","annuallyInterestRate":"0.0191625","discountRate":"0.75"},
// {"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": [
// {"level":"0","dailyInterestRate":"0.00041095","limit":"300000","annuallyInterestRate":"0.14999675","discountRate":"1"},
// {"level":"1","dailyInterestRate":"0.00039863","limit":"309000","annuallyInterestRate":"0.14549995","discountRate":"0.97"},
// {"level":"2","dailyInterestRate":"0.00037808","limit":"324000","annuallyInterestRate":"0.1379992","discountRate":"0.92"},
// {"level":"3","dailyInterestRate":"0.00035342","limit":"348000","annuallyInterestRate":"0.1289983","discountRate":"0.86"},
// {"level":"4","dailyInterestRate":"0.00030822","limit":"399000","annuallyInterestRate":"0.1125003","discountRate":"0.75"},
// {"level":"5","dailyInterestRate":"0.00024657","limit":"498000","annuallyInterestRate":"0.08999805","discountRate":"0.6"}
// ]
// }
//
const marketId = this.safeString(info, 'symbol');
const symbol = this.safeSymbol(marketId, market, undefined, 'spot');
const baseId = this.safeString(info, 'baseCoin');
const quoteId = this.safeString(info, 'quoteCoin');
const timestamp = this.safeInteger(info, 'timestamp');
return {
'symbol': symbol,
'base': this.safeCurrencyCode(baseId),
'baseRate': this.safeNumber(info, 'baseDailyInterestRate'),
'quote': this.safeCurrencyCode(quoteId),
'quoteRate': this.safeNumber(info, 'quoteDailyInterestRate'),
'period': 86400000,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'info': info,
};
}
/**
* @method
* @name bitget#fetchCrossBorrowRate
* @description 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
* @param {string} code unified currency code
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.symbol] required for isolated margin
* @returns {object} a [borrow rate structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#borrow-rate-structure}
*/
async fetchCrossBorrowRate(code, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'coin': currency['id'],
};
const response = await this.privateMarginGetV2MarginCrossedInterestRateAndLimit(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700879047861,
// "data": [
// {
// "coin": "BTC",
// "leverage": "3",
// "transferable": true,
// "borrowable": true,
// "dailyInterestRate": "0.00007",
// "annualInterestRate": "0.02555",
// "maxBorrowableAmount": "26",
// "vipList": [
// {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
// {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
// {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
// {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
// {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
// {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
// ]
// }
// ]
// }
//
const timestamp = this.safeInteger(response, 'requestTime');
const data = this.safeValue(response, 'data', []);
const first = this.safeValue(data, 0, {});
first['timestamp'] = timestamp;
return this.parseBorrowRate(first, currency);
}
parseBorrowRate(info, currency = undefined) {
//
// {
// "coin": "BTC",
// "leverage": "3",
// "transferable": true,
// "borrowable": true,
// "dailyInterestRate": "0.00007",
// "annualInterestRate": "0.02555",
// "maxBorrowableAmount": "26",
// "vipList": [
// {"level":"0","limit":"26","dailyInterestRate":"0.00007","annualInterestRate":"0.02555","discountRate":"1"},
// {"level":"1","limit":"26.78","dailyInterestRate":"0.0000679","annualInterestRate":"0.0247835","discountRate":"0.97"},
// {"level":"2","limit":"28.08","dailyInterestRate":"0.0000644","annualInterestRate":"0.023506","discountRate":"0.92"},
// {"level":"3","limit":"30.16","dailyInterestRate":"0.0000602","annualInterestRate":"0.021973","discountRate":"0.86"},
// {"level":"4","limit":"34.58","dailyInterestRate":"0.0000525","annualInterestRate":"0.0191625","discountRate":"0.75"},
// {"level":"5","limit":"43.16","dailyInterestRate":"0.000042","annualInterestRate":"0.01533","discountRate":"0.6"}
// ]
// }
//
const currencyId = this.safeString(info, 'coin');
const timestamp = this.safeInteger(info, 'timestamp');
return {
'currency': this.safeCurrencyCode(currencyId, currency),
'rate': this.safeNumber(info, 'dailyInterestRate'),
'period': 86400000,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'info': info,
};
}
/**
* @method
* @name bitget#fetchBorrowInterest
* @description 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 {object} [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)
* @returns {object[]} a list of [borrow interest structures]{@link https://docs.ccxt.com/#/?id=borrow-interest-structure}
*/
async fetchBorrowInterest(code = undefined, symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchBorrowInterest', 'paginate');
if (paginate) {
return await this.fetchPaginatedCallCursor('fetchBorrowInterest', symbol, since, limit, params, 'minId', 'idLessThan');
}
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
}
const request = {};
let currency = undefined;
if (code !== undefined) {
currency = this.currency(code);
request['coin'] = currency['id'];
}
if (since !== undefined) {
request['startTime'] = since;
}
else {
request['startTime'] = this.milliseconds() - 7776000000;
}
if (limit !== undefined) {
request['limit'] = limit;
}
let response = undefined;
let marginMode = undefined;
[marginMode, params] = this.handleMarginModeAndParams('fetchBorrowInterest', params, 'cross');
if (marginMode === 'isolated') {
if (symbol === undefined) {
throw new errors.ArgumentsRequired(this.id + ' fetchBorrowInterest() requires a symbol argument');
}
request['symbol'] = market['id'];
response = await this.privateMarginGetV2MarginIsolatedInterestHistory(this.extend(request, params));
}
else if (marginMode === 'cross') {
response = await this.privateMarginGetV2MarginCrossedInterestHistory(this.extend(request, params));
}
//
// isolated
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1700879935189,
// "data": {
// "resultList": [
// {
// "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": [
// {
// "interestId": "1112122013642272769",
// "interestCoin": "USDT",
// "dailyInterestRate": "0.00041",
// "loanCoin": "USDT",
// "interestAmount": "0.00006834",
// "interstType": "first",
// "cTime": "1700876470957",
// "uTime": "1700876470957"
// },
// ],
// "maxId": "1112122013642272769",
// "minId": "1096917004629716993"
// }
// }
//
const data = this.safeValue(response, 'data', {});
const rows = this.safeValue(data, 'resultList', []);
const interest = this.parseBorrowInterests(rows, market);
return this.filterByCurrencySinceLimit(interest, code, since, limit);
}
parseBorrowInterest(info, market = undefined) {
//
// 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"
// }
//
const marketId = this.safeString(info, 'symbol');
market = this.safeMarket(marketId, market);
const marginMode = (marketId !== undefined) ? 'isolated' : 'cross';
const timestamp = this.safeInteger(info, 'cTime');
return {
'info': info,
'symbol': this.safeString(market, 'symbol'),
'currency': this.safeCurrencyCode(this.safeString(info, 'interestCoin')),
'interest': this.safeNumber(info, 'interestAmount'),
'interestRate': this.safeNumber(info, 'dailyInterestRate'),
'amountBorrowed': undefined,
'marginMode': marginMode,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
};
}
/**
* @method
* @name bitget#closePosition
* @description closes an open position for a market
* @see https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
* @param {string} symbol unified CCXT market symbol
* @param {string} [side] one-way mode: 'buy' or 'sell', hedge-mode: 'long' or 'short'
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async closePosition(symbol, side = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'productType': productType,
};
if (side !== undefined) {
request['holdSide'] = side;
}
const response = await this.privateMixPostV2MixOrderClosePositions(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1702975017017,
// "data": {
// "successList": [
// {
// "orderId": "1120923953904893955",
// "clientOid": "1120923953904893956"
// }
// ],
// "failureList": [],
// "result": false
// }
// }
//
const data = this.safeValue(response, 'data', {});
const order = this.safeList(data, 'successList', []);
return this.parseOrder(order[0], market);
}
/**
* @method
* @name bitget#closeAllPositions
* @description closes all open positions for a market type
* @see https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
* @param {object} [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'
* @returns {object[]} A list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
async closeAllPositions(params = {}) {
await this.loadMarkets();
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(undefined, params);
const request = {
'productType': productType,
};
const response = await this.privateMixPostV2MixOrderClosePositions(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1702975017017,
// "data": {
// "successList": [
// {
// "orderId": "1120923953904893955",
// "clientOid": "1120923953904893956"
// }
// ],
// "failureList": [],
// "result": false
// }
// }
//
const data = this.safeValue(response, 'data', {});
const orderInfo = this.safeList(data, 'successList', []);
return this.parsePositions(orderInfo, undefined, params);
}
/**
* @method
* @name bitget#fetchMarginMode
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin mode structure]{@link https://docs.ccxt.com/#/?id=margin-mode-structure}
*/
async fetchMarginMode(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'marginCoin': market['settleId'],
'productType': productType,
};
const response = 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": ""
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.parseMarginMode(data, market);
}
parseMarginMode(marginMode, market = undefined) {
let marginType = this.safeString(marginMode, 'marginMode');
marginType = (marginType === 'crossed') ? 'cross' : marginType;
return {
'info': marginMode,
'symbol': market['symbol'],
'marginMode': marginType,
};
}
/**
* @method
* @name bitget#fetchPositionsHistory
* @description fetches historical positions
* @see https://www.bitget.com/api-doc/contract/position/Get-History-Position
* @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 {object} 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
*
* EXCHANGE SPECIFIC PARAMETERS
* @param {string} [params.productType] USDT-FUTURES (default), COIN-FUTURES, USDC-FUTURES, SUSDT-FUTURES, SCOIN-FUTURES, or SUSDC-FUTURES
* @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
async fetchPositionsHistory(symbols = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const until = this.safeInteger(params, 'until');
params = this.omit(params, 'until');
const request = {};
if (symbols !== undefined) {
const symbolsLength = symbols.length;
if (symbolsLength > 0) {
const market = this.market(symbols[0]);
request['symbol'] = market['id'];
}
}
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
if (until !== undefined) {
request['endTime'] = until;
}
const response = await this.privateMixGetV2MixPositionHistoryPosition(this.extend(request, params));
//
// {
// code: '00000',
// msg: 'success',
// requestTime: '1712794148791',
// data: {
// list: [
// {
// 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'
// },
// ...
// ]
// }
// }
//
const data = this.safeDict(response, 'data');
const responseList = this.safeList(data, 'list');
const positions = this.parsePositions(responseList, symbols, params);
return this.filterBySinceLimit(positions, since, limit);
}
/**
* @method
* @name bitget#fetchConvertQuote
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
await this.loadMarkets();
const request = {
'fromCoin': fromCode,
'toCoin': toCode,
'fromCoinSize': this.numberToString(amount),
};
const response = 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"
// }
// }
//
const data = this.safeDict(response, 'data', {});
const fromCurrencyId = this.safeString(data, 'fromCoin', fromCode);
const fromCurrency = this.currency(fromCurrencyId);
const toCurrencyId = this.safeString(data, 'toCoin', toCode);
const toCurrency = this.currency(toCurrencyId);
return this.parseConversion(data, fromCurrency, toCurrency);
}
/**
* @method
* @name bitget#createConvertTrade
* @description 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 {object} [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()
* @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
async createConvertTrade(id, fromCode, toCode, amount = undefined, params = {}) {
await this.loadMarkets();
const price = this.safeString2(params, 'price', 'cnvtPrice');
if (price === undefined) {
throw new errors.ArgumentsRequired(this.id + ' createConvertTrade() requires a price parameter');
}
const toAmount = this.safeString2(params, 'toAmount', 'toCoinSize');
if (toAmount === undefined) {
throw new errors.ArgumentsRequired(this.id + ' createConvertTrade() requires a toAmount parameter');
}
params = this.omit(params, ['price', 'toAmount']);
const request = {
'traceId': id,
'fromCoin': fromCode,
'toCoin': toCode,
'fromCoinSize': this.numberToString(amount),
'toCoinSize': toAmount,
'cnvtPrice': price,
};
const response = await this.privateConvertPostV2ConvertTrade(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1712123746203,
// "data": {
// "cnvtPrice": "0.99940076",
// "toCoin": "USDC",
// "toCoinSize": "4.99700379",
// "ts": "1712123746217"
// }
// }
//
const data = this.safeDict(response, 'data', {});
const toCurrencyId = this.safeString(data, 'toCoin', toCode);
const toCurrency = this.currency(toCurrencyId);
return this.parseConversion(data, undefined, toCurrency);
}
/**
* @method
* @name bitget#fetchConvertTradeHistory
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [conversion structures]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
async fetchConvertTradeHistory(code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const request = {};
const msInDay = 86400000;
const now = this.milliseconds();
if (since !== undefined) {
request['startTime'] = since;
}
else {
request['startTime'] = now - msInDay;
}
const endTime = this.safeString2(params, 'endTime', 'until');
if (endTime !== undefined) {
request['endTime'] = endTime;
}
else {
request['endTime'] = now;
}
if (limit !== undefined) {
request['limit'] = limit;
}
params = this.omit(params, 'until');
const response = await this.privateConvertGetV2ConvertConvertRecord(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1712124371799,
// "data": {
// "dataList": [
// {
// "id": "1159296505255219205",
// "fromCoin": "USDT",
// "fromCoinSize": "5",
// "cnvtPrice": "0.99940076",
// "toCoin": "USDC",
// "toCoinSize": "4.99700379",
// "ts": "1712123746217",
// "fee": "0"
// }
// ],
// "endId": "1159296505255219205"
// }
// }
//
const data = this.safeDict(response, 'data', {});
const dataList = this.safeList(data, 'dataList', []);
return this.parseConversions(dataList, code, 'fromCoin', 'toCoin', since, limit);
}
parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
//
// 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"
// }
//
const timestamp = this.safeInteger(conversion, 'ts');
const fromCoin = this.safeString(conversion, 'fromCoin');
const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
const to = this.safeString(conversion, 'toCoin');
const toCode = this.safeCurrencyCode(to, toCurrency);
return {
'info': conversion,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'id': this.safeString2(conversion, 'id', 'traceId'),
'fromCurrency': fromCode,
'fromAmount': this.safeNumber(conversion, 'fromCoinSize'),
'toCurrency': toCode,
'toAmount': this.safeNumber(conversion, 'toCoinSize'),
'price': this.safeNumber(conversion, 'cnvtPrice'),
'fee': this.safeNumber(conversion, 'fee'),
};
}
/**
* @method
* @name bitget#fetchConvertCurrencies
* @description fetches all available currencies that can be converted
* @see https://www.bitget.com/api-doc/common/convert/Get-Convert-Currencies
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an associative dictionary of currencies
*/
async fetchConvertCurrencies(params = {}) {
await this.loadMarkets();
const response = await this.privateConvertGetV2ConvertCurrencies(params);
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1712121755897,
// "data": [
// {
// "coin": "BTC",
// "available": "0.00009850",
// "maxAmount": "0.756266",
// "minAmount": "0.00001"
// },
// ]
// }
//
const result = {};
const data = this.safeList(response, 'data', []);
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const id = this.safeString(entry, 'coin');
const code = this.safeCurrencyCode(id);
result[code] = {
'info': entry,
'id': id,
'code': code,
'networks': undefined,
'type': undefined,
'name': undefined,
'active': undefined,
'deposit': undefined,
'withdraw': this.safeNumber(entry, 'available'),
'fee': undefined,
'precision': undefined,
'limits': {
'amount': {
'min': this.safeNumber(entry, 'minAmount'),
'max': this.safeNumber(entry, 'maxAmount'),
},
'withdraw': {
'min': undefined,
'max': undefined,
},
'deposit': {
'min': undefined,
'max': undefined,
},
},
'created': undefined,
};
}
return result;
}
/**
* @method
* @name bitget#fetchFundingInterval
* @description fetch the current funding rate interval
* @see https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
*/
async fetchFundingInterval(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
let productType = undefined;
[productType, params] = this.handleProductTypeAndParams(market, params);
const request = {
'symbol': market['id'],
'productType': productType,
};
const response = await this.publicMixGetV2MixMarketFundingTime(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1727930153888,
// "data": [
// {
// "symbol": "BTCUSDT",
// "nextFundingTime": "1727942400000",
// "ratePeriod": "8"
// }
// ]
// }
//
const data = this.safeList(response, 'data', []);
const first = this.safeDict(data, 0, {});
return this.parseFundingRate(first, market);
}
/**
* @method
* @name bitget#fetchLongShortRatioHistory
* @description 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 {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of [long short ratio structures]{@link https://docs.ccxt.com/#/?id=long-short-ratio-structure}
*/
async fetchLongShortRatioHistory(symbol = undefined, timeframe = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (timeframe !== undefined) {
request['period'] = timeframe;
}
let response = undefined;
if (market['swap'] || market['future']) {
response = await this.publicMixGetV2MixMarketAccountLongShort(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1729321233281,
// "data": [
// {
// "longAccountRatio": "0.58",
// "shortAccountRatio": "0.42",
// "longShortAccountRatio": "0.0138",
// "ts": "1729312200000"
// },
// ]
// }
//
}
else {
response = await this.publicMarginGetV2MarginMarketLongShortRatio(this.extend(request, params));
//
// {
// "code": "00000",
// "msg": "success",
// "requestTime": 1729306974712,
// "data": [
// {
// "longShortRatio": "40.66",
// "ts": "1729306800000"
// },
// ]
// }
//
}
const data = this.safeList(response, 'data', []);
return this.parseLongShortRatioHistory(data, market);
}
parseLongShortRatio(info, market = undefined) {
const marketId = this.safeString(info, 'symbol');
const timestamp = this.safeIntegerOmitZero(info, 'ts');
return {
'info': info,
'symbol': this.safeSymbol(marketId, market, undefined, 'contract'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'timeframe': undefined,
'longShortRatio': this.safeNumber2(info, 'longShortRatio', 'longShortAccountRatio'),
};
}
handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
if (!response) {
return undefined; // fallback to default error handler
}
//
// spot
//
// {"code":"00000","msg":"success","requestTime":1713294492511,"data":[...]}"
//
// {"status":"fail","err_code":"01001","err_msg":"系统异常,请稍后重试"}
// {"status":"error","ts":1595594160149,"err_code":"invalid-parameter","err_msg":"invalid size, valid range: [1,2000]"}
// {"status":"error","ts":1595684716042,"err_code":"invalid-parameter","err_msg":"illegal sign invalid"}
// {"status":"error","ts":1595700216275,"err_code":"bad-request","err_msg":"your balance is low!"}
// {"status":"error","ts":1595700344504,"err_code":"invalid-parameter","err_msg":"invalid type"}
// {"status":"error","ts":1595703343035,"err_code":"bad-request","err_msg":"order cancel fail"}
// {"status":"error","ts":1595704360508,"err_code":"invalid-parameter","err_msg":"accesskey not null"}
// {"status":"error","ts":1595704490084,"err_code":"invalid-parameter","err_msg":"permissions not right"}
// {"status":"error","ts":1595711862763,"err_code":"system exception","err_msg":"system exception"}
// {"status":"error","ts":1595730308979,"err_code":"bad-request","err_msg":"20003"}
//
// swap
//
// {"code":"40015","msg":"","requestTime":1595698564931,"data":null}
// {"code":"40017","msg":"Order id must not be blank","requestTime":1595702477835,"data":null}
// {"code":"40017","msg":"Order Type must not be blank","requestTime":1595698516162,"data":null}
// {"code":"40301","msg":"","requestTime":1595667662503,"data":null}
// {"code":"40017","msg":"Contract code must not be blank","requestTime":1595703151651,"data":null}
// {"code":"40108","msg":"","requestTime":1595885064600,"data":null}
// {"order_id":"513468410013679613","client_oid":null,"symbol":"ethusd","result":false,"err_code":"order_no_exist_error","err_msg":"订单不存在!"}
//
const message = this.safeString2(response, 'err_msg', 'msg');
const feedback = this.id + ' ' + body;
const nonEmptyMessage = ((message !== undefined) && (message !== '') && (message !== 'success'));
if (nonEmptyMessage) {
this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
}
const errorCode = this.safeString2(response, 'code', 'err_code');
const nonZeroErrorCode = (errorCode !== undefined) && (errorCode !== '00000');
if (nonZeroErrorCode) {
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
}
if (nonZeroErrorCode || nonEmptyMessage) {
throw new errors.ExchangeError(feedback); // unknown message
}
return undefined;
}
nonce() {
return this.milliseconds() - this.options['timeDifference'];
}
sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
const signed = api[0] === 'private';
const endpoint = api[1];
const pathPart = '/api';
const request = '/' + this.implodeParams(path, params);
const payload = pathPart + request;
let url = this.implodeHostname(this.urls['api'][endpoint]) + payload;
const query = this.omit(params, this.extractParams(path));
if (!signed && (method === 'GET')) {
const keys = Object.keys(query);
const keysLength = keys.length;
if (keysLength > 0) {
url = url + '?' + this.urlencode(query);
}
}
if (signed) {
this.checkRequiredCredentials();
const timestamp = this.nonce().toString();
let auth = timestamp + method + payload;
if (method === 'POST') {
body = this.json(params);
auth += body;
}
else {
if (Object.keys(params).length) {
let queryInner = '?' + this.urlencode(this.keysort(params));
// check #21169 pr
if (queryInner.indexOf('%24') > -1) {
queryInner = queryInner.replace('%24', '$');
}
url += queryInner;
auth += queryInner;
}
}
const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha256.sha256, 'base64');
const broker = this.safeString(this.options, 'broker');
headers = {
'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';
}
}
const sandboxMode = this.safeBool2(this.options, 'sandboxMode', 'sandbox', false);
if (sandboxMode && (path !== 'v2/public/time')) {
// https://github.com/ccxt/ccxt/issues/25252#issuecomment-2662742336
if (headers === undefined) {
headers = {};
}
const productType = this.safeString(params, 'productType');
if ((productType !== 'SCOIN-FUTURES') && (productType !== 'SUSDT-FUTURES') && (productType !== 'SUSDC-FUTURES')) {
headers['PAPTRADING'] = '1';
}
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
}
module.exports = bitget;