UNPKG

@jalmonter/ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges

1,234 lines (1,231 loc) 148 kB
'use strict'; var bingx$1 = require('./abstract/bingx.js'); var errors = require('./base/errors.js'); var Precise = require('./base/Precise.js'); var sha256 = require('./static_dependencies/noble-hashes/sha256.js'); var number = require('./base/functions/number.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- class bingx extends bingx$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'bingx', 'name': 'BingX', 'countries': ['US'], // cheapest is 60 requests a minute = 1 requests per second on average => ( 1000ms / 1) = 1000 ms between requests on average 'rateLimit': 1000, 'version': 'v1', 'certified': true, 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': false, 'cancelAllOrders': true, 'cancelOrder': true, 'cancelOrders': true, 'closeAllPositions': true, 'closePosition': false, 'createMarketBuyOrderWithCost': true, 'createMarketOrderWithCost': true, 'createMarketSellOrderWithCost': true, 'createOrder': true, 'createOrders': true, 'fetchBalance': true, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchLeverage': true, 'fetchLiquidations': false, 'fetchMarkets': true, 'fetchMyLiquidations': true, 'fetchOHLCV': true, 'fetchOpenInterest': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchPositions': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTransfers': true, 'fetchWithdrawals': true, 'setLeverage': true, 'setMargin': true, 'setMarginMode': true, 'transfer': true, }, 'hostname': 'bingx.com', 'urls': { 'logo': 'https://github-production-user-asset-6210df.s3.amazonaws.com/1294454/253675376-6983b72e-4999-4549-b177-33b374c195e3.jpg', 'api': { 'spot': 'https://open-api.{hostname}/openApi', 'swap': 'https://open-api.{hostname}/openApi', 'contract': 'https://open-api.{hostname}/openApi', 'wallets': 'https://open-api.{hostname}/openApi', 'user': 'https://open-api.{hostname}/openApi', 'subAccount': 'https://open-api.{hostname}/openApi', 'account': 'https://open-api.{hostname}/openApi', 'copyTrading': 'https://open-api.{hostname}/openApi', }, 'www': 'https://bingx.com/', 'doc': 'https://bingx-api.github.io/docs/', 'referral': 'https://bingx.com/invite/OHETOM', }, 'fees': { 'tierBased': true, 'spot': { 'feeSide': 'get', 'maker': this.parseNumber('0.001'), 'taker': this.parseNumber('0.001'), }, 'swap': { 'feeSide': 'quote', 'maker': this.parseNumber('0.0002'), 'taker': this.parseNumber('0.0005'), }, }, 'requiredCredentials': { 'apiKey': true, 'secret': true, }, 'api': { 'spot': { 'v1': { 'public': { 'get': { 'common/symbols': 3, 'market/trades': 3, 'market/depth': 3, 'market/kline': 3, 'ticker/24hr': 1, }, }, 'private': { 'get': { 'trade/query': 3, 'trade/openOrders': 3, 'trade/historyOrders': 3, 'account/balance': 3, }, 'post': { 'trade/order': 3, 'trade/cancel': 3, 'trade/batchOrders': 3, 'trade/cancelOrders': 3, }, }, }, 'v3': { 'private': { 'get': { 'get/asset/transfer': 3, 'asset/transfer': 3, 'capital/deposit/hisrec': 3, 'capital/withdraw/history': 3, }, 'post': { 'post/asset/transfer': 3, }, }, }, }, 'swap': { 'v2': { 'public': { 'get': { 'server/time': 3, 'quote/contracts': 1, 'quote/price': 1, 'quote/depth': 1, 'quote/trades': 1, 'quote/premiumIndex': 1, 'quote/fundingRate': 1, 'quote/klines': 1, 'quote/openInterest': 1, 'quote/ticker': 1, 'quote/bookTicker': 1, }, }, 'private': { 'get': { 'user/balance': 3, 'user/positions': 3, 'user/income': 3, 'trade/openOrders': 3, 'trade/order': 3, 'trade/marginType': 3, 'trade/leverage': 3, 'trade/forceOrders': 3, 'trade/allOrders': 3, 'trade/allFillOrders': 3, 'user/income/export': 3, 'user/commissionRate': 3, 'quote/bookTicker': 3, }, 'post': { 'trade/order': 3, 'trade/batchOrders': 3, 'trade/closeAllPositions': 3, 'trade/marginType': 3, 'trade/leverage': 3, 'trade/positionMargin': 3, 'trade/order/test': 3, }, 'delete': { 'trade/order': 3, 'trade/batchOrders': 3, 'trade/allOpenOrders': 3, }, }, }, 'v3': { 'public': { 'get': { 'quote/klines': 1, }, }, }, }, 'contract': { 'v1': { 'private': { 'get': { 'allPosition': 3, 'allOrders': 3, 'balance': 3, }, }, }, }, 'wallets': { 'v1': { 'private': { 'get': { 'capital/config/getall': 3, 'capital/deposit/address': 1, 'capital/innerTransfer/records': 1, 'capital/subAccount/deposit/address': 1, 'capital/deposit/subHisrec': 1, 'capital/subAccount/innerTransfer/records': 1, }, 'post': { 'capital/withdraw/apply': 3, 'capital/innerTransfer/apply': 3, 'capital/subAccountInnerTransfer/apply': 3, 'capital/deposit/createSubAddress': 1, }, }, }, }, 'subAccount': { 'v1': { 'private': { 'get': { 'list': 3, 'assets': 3, 'apiKey/query': 1, }, 'post': { 'create': 3, 'apiKey/create': 3, 'apiKey/edit': 3, 'apiKey/del': 3, 'updateStatus': 3, }, }, }, }, 'account': { 'v1': { 'private': { 'get': { 'uid': 1, }, 'post': { 'innerTransfer/authorizeSubAccount': 3, }, }, }, }, 'user': { 'auth': { 'private': { 'post': { 'userDataStream': 1, }, }, }, }, 'copyTrading': { 'v1': { 'private': { 'get': { 'swap/trace/currentTrack': 1, }, 'post': { 'swap/trace/closeTrackOrder': 1, 'swap/trace/setTPSL': 1, }, }, }, }, 'api': { 'v3': { 'private': { 'get': { 'asset/transfer': 1, 'capital/deposit/hisrec': 1, 'capital/withdraw/history': 1, }, 'post': { 'post/asset/transfer': 1, }, }, }, }, }, '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', }, 'precisionMode': number.DECIMAL_PLACES, 'exceptions': { 'exact': { '400': errors.BadRequest, '401': errors.AuthenticationError, '403': errors.PermissionDenied, '404': errors.BadRequest, '429': errors.DDoSProtection, '418': errors.PermissionDenied, '500': errors.ExchangeError, '504': errors.ExchangeError, '100001': errors.AuthenticationError, '100412': errors.AuthenticationError, '100202': errors.InsufficientFunds, '100204': errors.BadRequest, '100400': errors.BadRequest, '100440': errors.ExchangeError, '100500': errors.ExchangeError, '100503': errors.ExchangeError, '80001': errors.BadRequest, '80012': errors.ExchangeNotAvailable, '80014': errors.BadRequest, '80016': errors.OrderNotFound, '80017': errors.OrderNotFound, '100437': errors.BadRequest, // {"code":100437,"msg":"The withdrawal amount is lower than the minimum limit, please re-enter.","timestamp":1689258588845} }, 'broad': {}, }, 'commonCurrencies': {}, 'options': { 'defaultType': 'spot', 'accountsByType': { 'spot': 'FUND', 'swap': 'PFUTURES', 'future': 'SFUTURES', }, 'accountsById': { 'FUND': 'spot', 'PFUTURES': 'swap', 'SFUTURES': 'future', }, 'recvWindow': 5 * 1000, 'broker': 'CCXT', }, }); } async fetchTime(params = {}) { /** * @method * @name bingx#fetchTime * @description fetches the current integer timestamp in milliseconds from the bingx server * @see https://bingx-api.github.io/docs/#/swapV2/base-info.html#Get%20Server%20Time * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int} the current integer timestamp in milliseconds from the bingx server */ const response = await this.swapV2PublicGetServerTime(params); // // { // "code": 0, // "msg": "", // "data": { // "serverTime": 1675319535362 // } // } // const data = this.safeValue(response, 'data'); return this.safeInteger(data, 'serverTime'); } async fetchCurrencies(params = {}) { /** * @method * @name bingx#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://bingx-api.github.io/docs/#/common/account-api.html#All%20Coins * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ if (!this.checkRequiredCredentials(false)) { return undefined; } const response = await this.walletsV1PrivateGetCapitalConfigGetall(params); // // { // "code": 0, // "timestamp": 1688045966616, // "data": [ // { // "coin": "BTC", // "name": "BTC", // "networkList": [ // { // "name": "BTC", // "network": "BTC", // "isDefault": true, // "minConfirm": "2", // "withdrawEnable": true, // "withdrawFee": "0.00035", // "withdrawMax": "1.62842", // "withdrawMin": "0.0005" // }, // { // "name": "BTC", // "network": "BEP20", // "isDefault": false, // "minConfirm": "15", // "withdrawEnable": true, // "withdrawFee": "0.00001", // "withdrawMax": "1.62734", // "withdrawMin": "0.0001" // } // ] // }, // ... // ], // } // const data = this.safeValue(response, 'data', []); const result = {}; for (let i = 0; i < data.length; i++) { const entry = data[i]; const currencyId = this.safeString(entry, 'coin'); const code = this.safeCurrencyCode(currencyId); const name = this.safeString(entry, 'name'); const networkList = this.safeValue(entry, 'networkList'); const networks = {}; let fee = undefined; let active = undefined; let withdrawEnabled = undefined; let defaultLimits = {}; for (let j = 0; j < networkList.length; j++) { const rawNetwork = networkList[j]; const network = this.safeString(rawNetwork, 'network'); const networkCode = this.networkIdToCode(network); const isDefault = this.safeValue(rawNetwork, 'isDefault'); withdrawEnabled = this.safeValue(rawNetwork, 'withdrawEnable'); const limits = { 'amounts': { 'min': this.safeNumber(rawNetwork, 'withdrawMin'), 'max': this.safeNumber(rawNetwork, 'withdrawMax') }, }; if (isDefault) { fee = this.safeNumber(rawNetwork, 'withdrawFee'); active = withdrawEnabled; defaultLimits = limits; } networks[networkCode] = { 'info': rawNetwork, 'id': network, 'network': networkCode, 'fee': fee, 'active': active, 'deposit': undefined, 'withdraw': withdrawEnabled, 'precision': undefined, 'limits': limits, }; } result[code] = { 'info': entry, 'code': code, 'id': currencyId, 'precision': undefined, 'name': name, 'active': active, 'deposit': undefined, 'withdraw': withdrawEnabled, 'networks': networks, 'fee': fee, 'limits': defaultLimits, }; } return result; } async fetchSpotMarkets(params) { const response = await this.spotV1PublicGetCommonSymbols(params); // // { // "code": 0, // "msg": "", // "debugMsg": "", // "data": { // "symbols": [ // { // "symbol": "GEAR-USDT", // "minQty": 735, // "maxQty": 2941177, // "minNotional": 5, // "maxNotional": 20000, // "status": 1, // "tickSize": 0.000001, // "stepSize": 1 // }, // ... // ] // } // } // const data = this.safeValue(response, 'data'); const markets = this.safeValue(data, 'symbols', []); return this.parseMarkets(markets); } async fetchSwapMarkets(params) { const response = await this.swapV2PublicGetQuoteContracts(params); // // { // "code": 0, // "msg": "", // "data": [ // { // "contractId": "100", // "symbol": "BTC-USDT", // "size": "0.0001", // "quantityPrecision": 4, // "pricePrecision": 1, // "feeRate": 0.0005, // "tradeMinLimit": 1, // "maxLongLeverage": 150, // "maxShortLeverage": 150, // "currency": "USDT", // "asset": "BTC", // "status": 1 // }, // ... // ] // } // const markets = this.safeValue(response, 'data', []); return this.parseMarkets(markets); } parseMarket(market) { const id = this.safeString(market, 'symbol'); const symbolParts = id.split('-'); const baseId = symbolParts[0]; const quoteId = symbolParts[1]; const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const currency = this.safeString(market, 'currency'); const settle = this.safeCurrencyCode(currency); let pricePrecision = this.safeInteger(market, 'pricePrecision'); if (pricePrecision === undefined) { pricePrecision = this.precisionFromString(this.safeString(market, 'tickSize')); } let quantityPrecision = this.safeInteger(market, 'quantityPrecision'); if (quantityPrecision === undefined) { quantityPrecision = this.precisionFromString(this.safeString(market, 'stepSize')); } const type = (settle !== undefined) ? 'swap' : 'spot'; const spot = type === 'spot'; const swap = type === 'swap'; let symbol = base + '/' + quote; if (settle !== undefined) { symbol += ':' + settle; } const fees = this.safeValue(this.fees, type, {}); const contractSize = this.safeNumber(market, 'size'); const isActive = this.safeString(market, 'status') === '1'; const isInverse = (spot) ? undefined : false; const isLinear = (spot) ? undefined : swap; return this.safeMarketStructure({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': currency, 'type': type, 'spot': spot, 'margin': false, 'swap': swap, 'future': false, 'option': false, 'active': isActive, 'contract': swap, 'linear': isLinear, 'inverse': isInverse, 'taker': this.safeNumber(fees, 'taker'), 'maker': this.safeNumber(fees, 'maker'), 'feeSide': this.safeString(fees, 'feeSide'), 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': quantityPrecision, 'price': pricePrecision, }, 'limits': { 'leverage': { 'min': undefined, 'max': this.safeInteger(market, 'maxLongLeverage'), }, 'amount': { 'min': this.safeNumber(market, 'minQty'), 'max': this.safeNumber(market, 'maxQty'), }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.safeNumber(market, 'minNotional'), 'max': this.safeNumber(market, 'maxNotional'), }, }, 'created': undefined, 'info': market, }); } async fetchMarkets(params = {}) { /** * @method * @name bingx#fetchMarkets * @description retrieves data on all markets for bingx * @see https://bingx-api.github.io/docs/#/spot/market-api.html#Query%20Symbols * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Contract%20Information * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ const requests = [this.fetchSpotMarkets(params), this.fetchSwapMarkets(params)]; const promises = await Promise.all(requests); const spotMarkets = this.safeValue(promises, 0, []); const swapMarkets = this.safeValue(promises, 1, []); return this.arrayConcat(spotMarkets, swapMarkets); } async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name bingx#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#K-Line%20Data * @see https://bingx-api.github.io/docs/#/spot/market-api.html#Candlestick%20chart%20data * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#%20K-Line%20Data * @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.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 {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ await this.loadMarkets(); let paginate = false; [paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate', false); if (paginate) { return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1440); } const market = this.market(symbol); const request = { 'symbol': market['id'], }; request['interval'] = this.safeString(this.timeframes, timeframe, timeframe); if (since !== undefined) { request['startTime'] = since; } if (limit !== undefined) { request['limit'] = limit; } const until = this.safeInteger2(params, 'until', 'endTime'); if (until !== undefined) { params = this.omit(params, ['until']); request['endTime'] = until; } let response = undefined; if (market['spot']) { response = await this.spotV1PublicGetMarketKline(this.extend(request, params)); } else { response = await this.swapV3PublicGetQuoteKlines(this.extend(request, params)); } // // { // "code": 0, // "msg": "", // "data": [ // { // "open": "19396.8", // "close": "19394.4", // "high": "19397.5", // "low": "19385.7", // "volume": "110.05", // "time": 1666583700000 // }, // ... // ] // } // let ohlcvs = this.safeValue(response, 'data', []); if (!Array.isArray(ohlcvs)) { ohlcvs = [ohlcvs]; } return this.parseOHLCVs(ohlcvs, market, timeframe, since, limit); } parseOHLCV(ohlcv, market = undefined) { // // { // "open": "19394.4", // "close": "19379.0", // "high": "19394.4", // "low": "19368.3", // "volume": "167.44", // "time": 1666584000000 // } // spot // [ // 1691402580000, // 29093.61, // 29093.93, // 29087.73, // 29093.24, // 0.59, // 1691402639999, // 17221.07 // ] // if (Array.isArray(ohlcv)) { 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), ]; } return [ this.safeInteger(ohlcv, 'time'), this.safeNumber(ohlcv, 'open'), this.safeNumber(ohlcv, 'high'), this.safeNumber(ohlcv, 'low'), this.safeNumber(ohlcv, 'close'), this.safeNumber(ohlcv, 'volume'), ]; } async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name bingx#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://bingx-api.github.io/docs/#/spot/market-api.html#Query%20transaction%20records * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#The%20latest%20Trade%20of%20a%20Trading%20Pair * @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 * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades} */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; if (limit !== undefined) { request['limit'] = Math.min(limit, 100); // avoid API exception "limit should less than 100" } let response = undefined; let marketType = undefined; [marketType, params] = this.handleMarketTypeAndParams('fetchTrades', market, params); if (marketType === 'spot') { response = await this.spotV1PublicGetMarketTrades(this.extend(request, params)); } else { response = await this.swapV2PublicGetQuoteTrades(this.extend(request, params)); } // // spot // // { // "code": 0, // "data": [ // { // "id": 43148253, // "price": 25714.71, // "qty": 1.674571, // "time": 1655085975589, // "buyerMaker": false // } // ] // } // // swap // // { // "code":0, // "msg":"", // "data":[ // { // "time": 1672025549368, // "isBuyerMaker": true, // "price": "16885.0", // "qty": "3.3002", // "quoteQty": "55723.87" // }, // ... // ] // } // const trades = this.safeValue(response, 'data', []); return this.parseTrades(trades, market, since, limit); } parseTrade(trade, market = undefined) { // // spot // fetchTrades // // { // "id": 43148253, // "price": 25714.71, // "qty": 1.674571, // "time": 1655085975589, // "buyerMaker": false // } // // swap // fetchTrades // // { // "time": 1672025549368, // "isBuyerMaker": true, // "price": "16885.0", // "qty": "3.3002", // "quoteQty": "55723.87" // } // // swap // fetchMyTrades // // { // "volume": "0.1", // "price": "106.75", // "amount": "10.6750", // "commission": "-0.0053", // "currency": "USDT", // "orderId": "1676213270274379776", // "liquidatedPrice": "0.00", // "liquidatedMarginRatio": "0.00", // "filledTime": "2023-07-04T20:56:01.000+0800" // } // // // ws // // spot // // { // "E": 1690214529432, // "T": 1690214529386, // "e": "trade", // "m": true, // "p": "29110.19", // "q": "0.1868", // "s": "BTC-USDT", // "t": "57903921" // } // // swap // // { // "q": "0.0421", // "p": "29023.5", // "T": 1690221401344, // "m": false, // "s": "BTC-USDT" // } // let time = this.safeIntegerN(trade, ['time', 'filledTm', 'T']); const datetimeId = this.safeString(trade, 'filledTm'); if (datetimeId !== undefined) { time = this.parse8601(datetimeId); } if (time === 0) { time = undefined; } const cost = this.safeString(trade, 'quoteQty'); const type = (cost === undefined) ? 'spot' : 'swap'; const currencyId = this.safeString2(trade, 'currency', 'N'); const currencyCode = this.safeCurrencyCode(currencyId); const m = this.safeValue(trade, 'm', false); const marketId = this.safeString(trade, 's'); const isBuyerMaker = this.safeValue2(trade, 'buyerMaker', 'isBuyerMaker'); let takeOrMaker = (isBuyerMaker || m) ? 'maker' : 'taker'; let side = this.safeStringLower2(trade, 'side', 'S'); if (side === undefined) { side = (isBuyerMaker || m) ? 'sell' : 'buy'; takeOrMaker = 'taker'; } return this.safeTrade({ 'id': this.safeStringN(trade, ['id', 't']), 'info': trade, 'timestamp': time, 'datetime': this.iso8601(time), 'symbol': this.safeSymbol(marketId, market, '-', type), 'order': this.safeString2(trade, 'orderId', 'i'), 'type': this.safeStringLower(trade, 'o'), 'side': this.parseOrderSide(side), 'takerOrMaker': takeOrMaker, 'price': this.safeString2(trade, 'price', 'p'), 'amount': this.safeStringN(trade, ['qty', 'amount', 'q']), 'cost': cost, 'fee': { 'cost': this.parseNumber(Precise["default"].stringAbs(this.safeString2(trade, 'commission', 'n'))), 'currency': currencyCode, 'rate': undefined, }, }, market); } async fetchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name bingx#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://bingx-api.github.io/docs/#/spot/market-api.html#Query%20depth%20information * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Get%20Market%20Depth * @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 */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; if (limit !== undefined) { request['limit'] = limit; } let response = undefined; let marketType = undefined; [marketType, params] = this.handleMarketTypeAndParams('fetchOrderBook', market, params); if (marketType === 'spot') { response = await this.spotV1PublicGetMarketDepth(this.extend(request, params)); } else { response = await this.swapV2PublicGetQuoteDepth(this.extend(request, params)); } // // spot // // { // "code": 0, // "data": { // "bids": [ // [ // "26324.73", // "0.37655" // ], // [ // "26324.71", // "0.31888" // ], // ], // "asks": [ // [ // "26340.30", // "6.45221" // ], // [ // "26340.15", // "6.73261" // ], // ]} // } // // swap // // { // "code": 0, // "msg": "", // "data": { // "T": 1683914263304, // "bids": [ // [ // "26300.90000000", // "30408.00000000" // ], // [ // "26300.80000000", // "50906.00000000" // ], // ], // "asks": [ // [ // "26301.00000000", // "43616.00000000" // ], // [ // "26301.10000000", // "49402.00000000" // ], // ]} // } // const orderbook = this.safeValue(response, 'data', {}); const timestamp = this.safeInteger2(orderbook, 'T', 'ts'); return this.parseOrderBook(orderbook, market['symbol'], timestamp, 'bids', 'asks', 0, 1); } async fetchFundingRate(symbol, params = {}) { /** * @method * @name bingx#fetchFundingRate * @description fetch the current funding rate * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Current%20Funding%20Rate * @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} */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; const response = await this.swapV2PublicGetQuotePremiumIndex(this.extend(request, params)); // // { // "code":0, // "msg":"", // "data":[ // { // "symbol": "BTC-USDT", // "markPrice": "16884.5", // "indexPrice": "16886.9", // "lastFundingRate": "0.0001", // "nextFundingTime": 1672041600000 // }, // ... // ] // } // const data = this.safeValue(response, 'data', {}); return this.parseFundingRate(data, market); } parseFundingRate(contract, market = undefined) { // // { // "symbol": "BTC-USDT", // "markPrice": "16884.5", // "indexPrice": "16886.9", // "lastFundingRate": "0.0001", // "nextFundingTime": 1672041600000 // } // const marketId = this.safeString(contract, 'symbol'); const nextFundingTimestamp = this.safeInteger(contract, 'nextFundingTime'); return { 'info': contract, 'symbol': this.safeSymbol(marketId, market, '-', 'swap'), 'markPrice': this.safeNumber(contract, 'markPrice'), 'indexPrice': this.safeNumber(contract, 'indexPrice'), 'interestRate': undefined, 'estimatedSettlePrice': undefined, 'timestamp': undefined, 'datetime': undefined, 'fundingRate': this.safeNumber(contract, 'lastFundingRate'), 'fundingTimestamp': undefined, 'fundingDatetime': undefined, 'nextFundingRate': undefined, 'nextFundingTimestamp': nextFundingTimestamp, 'nextFundingDatetime': this.iso8601(nextFundingTimestamp), 'previousFundingRate': undefined, 'previousFundingTimestamp': undefined, 'previousFundingDatetime': undefined, }; } async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name bingx#fetchFundingRateHistory * @description fetches historical funding rate prices * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Funding%20Rate%20History * @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]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {int} [params.until] timestamp in ms of the latest funding rate to fetch * @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} */ 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.fetchPaginatedCallDeterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params); } const market = this.market(symbol); const request = { 'symbol': market['id'], }; if (since !== undefined) { request['startTime'] = since; } if (limit !== undefined) { request['limit'] = limit; } const until = this.safeInteger2(params, 'until', 'startTime'); if (until !== undefined) { params = this.omit(params, ['until']); request['startTime'] = until; } const response = await this.swapV2PublicGetQuoteFundingRate(this.extend(request, params)); // // { // "code":0, // "msg":"", // "data":[ // { // "symbol": "BTC-USDT", // "fundingRate": "0.0001", // "fundingTime": 1585684800000 // }, // ... // ] // } // 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, '-', 'swap'); 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); } async fetchOpenInterest(symbol, params = {}) { /** * @method * @name bingx#fetchOpenInterest * @description Retrieves the open interest of a currency * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Get%20Swap%20Open%20Positions * @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} */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; const response = await this.swapV2PublicGetQuoteOpenInterest(this.extend(request, params)); // // { // "code": 0, // "msg": "", // "data": { // "openInterest": "3289641547.10", // "symbol": "BTC-USDT", // "time": 1672026617364 // } // } // const data = this.safeValue(response, 'data', {}); return this.parseOpenInterest(data, market); } parseOpenInterest(interest, market = undefined) { // // { // "openInterest": "3289641547.10", // "symbol": "BTC-USDT", // "time": 1672026617364 // } // const timestamp = this.safeInteger(interest, 'time'); const id = this.safeString(interest, 'symbol'); const symbol = this.safeSymbol(id, market, '-', 'swap'); const openInterest = this.safeNumber(interest, 'openInterest'); return this.safeOpenInterest({ 'symbol': symbol, 'baseVolume': undefined, 'quoteVolume': undefined, 'openInterestAmount': undefined, 'openInterestValue': openInterest, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'info': interest, }, market); } async fetchTicker(symbol, params = {}) { /** * @method * @name bingx#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://bingx-api.github.io/docs/#/swapV2/market-api.html#Get%20Ticker * @see https://bingx-api.github.io/docs/#/spot/market-api.html#24%E5%B0%8F%E6%97%B6%E4%BB%B7%E6%A0%BC%E5%8F%98%E5%8A%A8%E6%83%85%E5%86%B5 * @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} */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; let response = undefined; if (market['spot']) { response = await this.spotV1PublicGetTicker24hr(this.extend(request, params)); } else { response = await this.swapV2PublicGetQuoteTicker(this.extend(request, params)); } const data = this.safeValue(response, 'data'); const ticker = this.safeValue(data, 0, data); return this.parseTicker(ticker, market); } async fetchTickers(symbols = undefined, params = {}) { /** * @method * @name bingx#fetchTickers