UNPKG

guyo13-ccxt

Version:

A ccxt fork with some corrections

277 lines (262 loc) 12.7 kB
'use strict'; // --------------------------------------------------------------------------- const binance = require ('./binance.js'); const { BadRequest } = require ('./base/errors'); // --------------------------------------------------------------------------- module.exports = class binanceusdm extends binance { describe () { return this.deepExtend (super.describe (), { 'id': 'binanceusdm', 'name': 'Binance USDⓈ-M', 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/117738721-668c8d80-b205-11eb-8c49-3fad84c4a07f.jpg', }, 'has': { 'fetchPositions': true, 'fetchIsolatedPositions': true, 'fetchFundingRate': true, 'fetchFundingHistory': true, 'setLeverage': true, 'setMode': true, }, 'options': { 'defaultType': 'future', // https://www.binance.com/en/support/faq/360033162192 // tier amount, maintenance margin, initial margin 'leverageBrackets': undefined, 'marginTypes': {}, }, // https://www.binance.com/en/fee/futureFee 'fees': { 'trading': { 'tierBased': true, 'percentage': true, 'taker': this.parseNumber ('0.000400'), 'maker': this.parseNumber ('0.000200'), 'tiers': { 'taker': [ [ this.parseNumber ('0'), this.parseNumber ('0.000400') ], [ this.parseNumber ('250'), this.parseNumber ('0.000400') ], [ this.parseNumber ('2500'), this.parseNumber ('0.000350') ], [ this.parseNumber ('7500'), this.parseNumber ('0.000320') ], [ this.parseNumber ('22500'), this.parseNumber ('0.000300') ], [ this.parseNumber ('50000'), this.parseNumber ('0.000270') ], [ this.parseNumber ('100000'), this.parseNumber ('0.000250') ], [ this.parseNumber ('200000'), this.parseNumber ('0.000220') ], [ this.parseNumber ('400000'), this.parseNumber ('0.000200') ], [ this.parseNumber ('750000'), this.parseNumber ('0.000170') ], ], 'maker': [ [ this.parseNumber ('0'), this.parseNumber ('0.000200') ], [ this.parseNumber ('250'), this.parseNumber ('0.000160') ], [ this.parseNumber ('2500'), this.parseNumber ('0.000140') ], [ this.parseNumber ('7500'), this.parseNumber ('0.000120') ], [ this.parseNumber ('22500'), this.parseNumber ('0.000100') ], [ this.parseNumber ('50000'), this.parseNumber ('0.000080') ], [ this.parseNumber ('100000'), this.parseNumber ('0.000060') ], [ this.parseNumber ('200000'), this.parseNumber ('0.000040') ], [ this.parseNumber ('400000'), this.parseNumber ('0.000020') ], [ this.parseNumber ('750000'), this.parseNumber ('0') ], ], }, }, }, }); } async fetchTradingFees (params = {}) { await this.loadMarkets (); const marketSymbols = Object.keys (this.markets); const fees = {}; const accountInfo = await this.fapiPrivateGetAccount (params); // { // "feeTier": 0, // account commisssion tier // "canTrade": true, // if can trade // "canDeposit": true, // if can transfer in asset // "canWithdraw": true, // if can transfer out asset // "updateTime": 0, // "totalInitialMargin": "0.00000000", // total initial margin required with current mark price (useless with isolated positions), only for USDT asset // "totalMaintMargin": "0.00000000", // total maintenance margin required, only for USDT asset // "totalWalletBalance": "23.72469206", // total wallet balance, only for USDT asset // "totalUnrealizedProfit": "0.00000000", // total unrealized profit, only for USDT asset // "totalMarginBalance": "23.72469206", // total margin balance, only for USDT asset // "totalPositionInitialMargin": "0.00000000", // initial margin required for positions with current mark price, only for USDT asset // "totalOpenOrderInitialMargin": "0.00000000", // initial margin required for open orders with current mark price, only for USDT asset // "totalCrossWalletBalance": "23.72469206", // crossed wallet balance, only for USDT asset // "totalCrossUnPnl": "0.00000000", // unrealized profit of crossed positions, only for USDT asset // "availableBalance": "23.72469206", // available balance, only for USDT asset // "maxWithdrawAmount": "23.72469206" // maximum amount for transfer out, only for USDT asset // ... // } const feeTier = this.safeInteger (accountInfo, 'feeTier'); const feeTiers = this.fees['trading']['tiers']; const maker = feeTiers['maker'][feeTier][1]; const taker = feeTiers['taker'][feeTier][1]; for (let i = 0; i < marketSymbols.length; i++) { const symbol = marketSymbols[i]; fees[symbol] = { 'info': { 'feeTier': feeTier, }, 'symbol': symbol, 'maker': maker, 'taker': taker, }; } return fees; } async transferIn (code, amount, params = {}) { // transfer from spot wallet to usdm futures wallet return await this.futuresTransfer (code, amount, 1, params); } async transferOut (code, amount, params = {}) { // transfer from usdm futures wallet to spot wallet return await this.futuresTransfer (code, amount, 2, params); } async fetchFundingRate (symbol = undefined, params = undefined) { await this.loadMarkets (); let market = undefined; const request = {}; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } const response = await this.fapiPublicGetPremiumIndex (this.extend (request, params)); // // { // "symbol": "BTCUSDT", // "markPrice": "45802.81129892", // "indexPrice": "45745.47701915", // "estimatedSettlePrice": "45133.91753671", // "lastFundingRate": "0.00063521", // "interestRate": "0.00010000", // "nextFundingTime": "1621267200000", // "time": "1621252344001" // } // if (Array.isArray (response)) { const result = []; const values = Object.values (response); for (let i = 0; i < values.length; i++) { const parsed = this.parseFundingRate (values[i]); result.push (parsed); } return result; } else { return this.parseFundingRate (response); } } async loadLeverageBrackets (reload = false, params = {}) { await this.loadMarkets (); // by default cache the leverage bracket // it contains useful stuff like the maintenance margin and initial margin for positions if ((this.options['leverageBrackets'] === undefined) || (reload)) { const response = await this.fapiPrivateGetLeverageBracket (params); this.options['leverageBrackets'] = {}; for (let i = 0; i < response.length; i++) { const entry = response[i]; const marketId = this.safeString (entry, 'symbol'); const symbol = this.safeSymbol (marketId); const brackets = this.safeValue (entry, 'brackets'); const result = []; for (let j = 0; j < brackets.length; j++) { const bracket = brackets[j]; // we use floats here internally on purpose const notionalFloor = this.safeFloat (bracket, 'notionalFloor'); const maintenanceMarginPercentage = this.safeString (bracket, 'maintMarginRatio'); result.push ([ notionalFloor, maintenanceMarginPercentage ]); } this.options['leverageBrackets'][symbol] = result; } } return this.options['leverageBrackets']; } async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); await this.loadLeverageBrackets (); const account = await this.fapiPrivateGetAccount (params); const result = this.parseAccountPositions (account); if (symbols === undefined) { return result; } else { return this.filterByArray (result, 'symbol', symbols, false); } } async fetchIsolatedPositions (symbol = undefined, params = {}) { // only supported in usdm futures await this.loadMarkets (); await this.loadLeverageBrackets (); const request = {}; let market = undefined; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } const response = await this.fapiPrivateGetPositionRisk (this.extend (request, params)); if (symbol === undefined) { const result = []; for (let i = 0; i < response.length; i++) { const parsed = this.parsePositionRisk (response[i], market); if (parsed['marginType'] === 'isolated') { result.push (parsed); } } return result; } else { return this.parsePositionRisk (this.safeValue (response, 0), market); } } async fetchFundingHistory (symbol = undefined, since = undefined, limit = undefined, params = undefined) { await this.loadMarkets (); let market = undefined; // "TRANSFER","WELCOME_BONUS", "REALIZED_PNL","FUNDING_FEE", "COMMISSION" and "INSURANCE_CLEAR" const request = { 'incomeType': 'FUNDING_FEE', }; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } if (since !== undefined) { request['startTime'] = since; } if (limit !== undefined) { request['limit'] = limit; } const response = await this.fapiPrivateGetIncome (this.extend (request, params)); return this.parseIncomes (response, market, since, limit); } async setLeverage (symbol, leverage, params = {}) { // WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS // AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS if ((leverage < 1) || (leverage > 125)) { throw new BadRequest (this.id + ' leverage should be between 1 and 125'); } await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], 'leverage': leverage, }; return await this.fapiPrivatePostLeverage (this.extend (request, params)); } async setMode (symbol, marginType, params = {}) { // // { "code": -4048 , "msg": "Margin type cannot be changed if there exists position." } // // or // // { "code": 200, "msg": "success" } // marginType = marginType.toUpperCase (); if ((marginType !== 'ISOLATED') && (marginType !== 'CROSSED')) { throw new BadRequest (this.id + ' marginType must be either isolated or crossed'); } await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], 'marginType': marginType, }; return await this.fapiPrivatePostMarginType (this.extend (request, params)); } };