UNPKG

sfccxt

Version:

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

1,032 lines (1,010 loc) 92.3 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, ExchangeNotAvailable, OnMaintenance, InvalidOrder, OrderNotFound, InsufficientFunds, ArgumentsRequired, BadSymbol, BadRequest, RequestTimeout, NetworkError } = require ('./base/errors'); const { TRUNCATE, TICK_SIZE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- module.exports = class huobijp extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'huobijp', 'name': 'Huobi Japan', 'countries': [ 'JP' ], 'rateLimit': 100, 'userAgent': this.userAgents['chrome39'], 'certified': false, 'version': 'v1', 'accounts': undefined, 'accountsById': undefined, 'hostname': 'api-cloud.huobi.co.jp', 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': undefined, 'swap': false, 'future': false, 'option': false, 'cancelAllOrders': true, 'cancelOrder': true, 'cancelOrders': true, 'createOrder': true, 'createStopLimitOrder': false, 'createStopMarketOrder': false, 'createStopOrder': false, 'fetchAccounts': true, 'fetchBalance': true, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchOrderTrades': true, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingLimits': true, 'fetchWithdrawals': true, 'withdraw': true, }, 'timeframes': { '1m': '1min', '5m': '5min', '15m': '15min', '30m': '30min', '1h': '60min', '4h': '4hour', '1d': '1day', '1w': '1week', '1M': '1mon', '1y': '1year', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/85734211-85755480-b705-11ea-8b35-0b7f1db33a2f.jpg', 'api': { 'market': 'https://{hostname}', 'public': 'https://{hostname}', 'private': 'https://{hostname}', 'v2Public': 'https://{hostname}', 'v2Private': 'https://{hostname}', }, 'www': 'https://www.huobi.co.jp', 'referral': 'https://www.huobi.co.jp/register/?invite_code=znnq3', 'doc': 'https://api-doc.huobi.co.jp', 'fees': 'https://www.huobi.co.jp/support/fee', }, 'api': { 'v2Public': { 'get': { 'reference/currencies': 1, // 币链参考信息 'market-status': 1, // 获取当前市场状态 }, }, 'v2Private': { 'get': { 'account/ledger': 1, 'account/withdraw/quota': 1, 'account/withdraw/address': 1, // 提币地址查询(限母用户可用) 'account/deposit/address': 1, 'account/repayment': 5, // 还币交易记录查询 'reference/transact-fee-rate': 1, 'account/asset-valuation': 0.2, // 获取账户资产估值 'point/account': 5, // 点卡余额查询 'sub-user/user-list': 1, // 获取子用户列表 'sub-user/user-state': 1, // 获取特定子用户的用户状态 'sub-user/account-list': 1, // 获取特定子用户的账户列表 'sub-user/deposit-address': 1, // 子用户充币地址查询 'sub-user/query-deposit': 1, // 子用户充币记录查询 'user/api-key': 1, // 母子用户API key信息查询 'user/uid': 1, // 母子用户获取用户UID 'algo-orders/opening': 1, // 查询未触发OPEN策略委托 'algo-orders/history': 1, // 查询策略委托历史 'algo-orders/specific': 1, // 查询特定策略委托 'c2c/offers': 1, // 查询借入借出订单 'c2c/offer': 1, // 查询特定借入借出订单及其交易记录 'c2c/transactions': 1, // 查询借入借出交易记录 'c2c/repayment': 1, // 查询还币交易记录 'c2c/account': 1, // 查询账户余额 'etp/reference': 1, // 基础参考信息 'etp/transactions': 5, // 获取杠杆ETP申赎记录 'etp/transaction': 5, // 获取特定杠杆ETP申赎记录 'etp/rebalance': 1, // 获取杠杆ETP调仓记录 'etp/limit': 1, // 获取ETP持仓限额 }, 'post': { 'account/transfer': 1, 'account/repayment': 5, // 归还借币(全仓逐仓通用) 'point/transfer': 5, // 点卡划转 'sub-user/management': 1, // 冻结/解冻子用户 'sub-user/creation': 1, // 子用户创建 'sub-user/tradable-market': 1, // 设置子用户交易权限 'sub-user/transferability': 1, // 设置子用户资产转出权限 'sub-user/api-key-generation': 1, // 子用户API key创建 'sub-user/api-key-modification': 1, // 修改子用户API key 'sub-user/api-key-deletion': 1, // 删除子用户API key 'sub-user/deduct-mode': 1, // 设置子用户手续费抵扣模式 'algo-orders': 1, // 策略委托下单 'algo-orders/cancel-all-after': 1, // 自动撤销订单 'algo-orders/cancellation': 1, // 策略委托(触发前)撤单 'c2c/offer': 1, // 借入借出下单 'c2c/cancellation': 1, // 借入借出撤单 'c2c/cancel-all': 1, // 撤销所有借入借出订单 'c2c/repayment': 1, // 还币 'c2c/transfer': 1, // 资产划转 'etp/creation': 5, // 杠杆ETP换入 'etp/redemption': 5, // 杠杆ETP换出 'etp/{transactId}/cancel': 10, // 杠杆ETP单个撤单 'etp/batch-cancel': 50, // 杠杆ETP批量撤单 }, }, 'market': { 'get': { 'history/kline': 1, // 获取K线数据 'detail/merged': 1, // 获取聚合行情(Ticker) 'depth': 1, // 获取 Market Depth 数据 'trade': 1, // 获取 Trade Detail 数据 'history/trade': 1, // 批量获取最近的交易记录 'detail': 1, // 获取 Market Detail 24小时成交量数据 'tickers': 1, 'etp': 1, // 获取杠杆ETP实时净值 }, }, 'public': { 'get': { 'common/symbols': 1, // 查询系统支持的所有交易对 'common/currencys': 1, // 查询系统支持的所有币种 'common/timestamp': 1, // 查询系统当前时间 'common/exchange': 1, // order limits 'settings/currencys': 1, // ?language=en-US }, }, 'private': { 'get': { 'account/accounts': 0.2, // 查询当前用户的所有账户(即account-id) 'account/accounts/{id}/balance': 0.2, // 查询指定账户的余额 'account/accounts/{sub-uid}': 1, 'account/history': 4, 'cross-margin/loan-info': 1, 'margin/loan-info': 1, // 查询借币币息率及额度 'fee/fee-rate/get': 1, 'order/openOrders': 0.4, 'order/orders': 0.4, 'order/orders/{id}': 0.4, // 查询某个订单详情 'order/orders/{id}/matchresults': 0.4, // 查询某个订单的成交明细 'order/orders/getClientOrder': 0.4, 'order/history': 1, // 查询当前委托、历史委托 'order/matchresults': 1, // 查询当前成交、历史成交 // 'dw/withdraw-virtual/addresses', // 查询虚拟币提现地址(Deprecated) 'query/deposit-withdraw': 1, // 'margin/loan-info', // duplicate 'margin/loan-orders': 0.2, // 借贷订单 'margin/accounts/balance': 0.2, // 借贷账户详情 'cross-margin/loan-orders': 1, // 查询借币订单 'cross-margin/accounts/balance': 1, // 借币账户详情 'points/actions': 1, 'points/orders': 1, 'subuser/aggregate-balance': 10, 'stable-coin/exchange_rate': 1, 'stable-coin/quote': 1, }, 'post': { 'account/transfer': 1, // 资产划转(该节点为母用户和子用户进行资产划转的通用接口。) 'futures/transfer': 1, 'order/batch-orders': 0.4, 'order/orders/place': 0.2, // 创建并执行一个新订单 (一步下单, 推荐使用) 'order/orders/submitCancelClientOrder': 0.2, 'order/orders/batchCancelOpenOrders': 0.4, // 'order/orders', // 创建一个新的订单请求 (仅创建订单,不执行下单) // 'order/orders/{id}/place', // 执行一个订单 (仅执行已创建的订单) 'order/orders/{id}/submitcancel': 0.2, // 申请撤销一个订单请求 'order/orders/batchcancel': 0.4, // 批量撤销订单 // 'dw/balance/transfer', // 资产划转 'dw/withdraw/api/create': 1, // 申请提现虚拟币 // 'dw/withdraw-virtual/create', // 申请提现虚拟币 // 'dw/withdraw-virtual/{id}/place', // 确认申请虚拟币提现(Deprecated) 'dw/withdraw-virtual/{id}/cancel': 1, // 申请取消提现虚拟币 'dw/transfer-in/margin': 10, // 现货账户划入至借贷账户 'dw/transfer-out/margin': 10, // 借贷账户划出至现货账户 'margin/orders': 10, // 申请借贷 'margin/orders/{id}/repay': 10, // 归还借贷 'cross-margin/transfer-in': 1, // 资产划转 'cross-margin/transfer-out': 1, // 资产划转 'cross-margin/orders': 1, // 申请借币 'cross-margin/orders/{id}/repay': 1, // 归还借币 'stable-coin/exchange': 1, 'subuser/transfer': 10, }, }, }, 'fees': { 'trading': { 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': this.parseNumber ('0.002'), 'taker': this.parseNumber ('0.002'), }, }, 'precisionMode': TICK_SIZE, 'exceptions': { 'broad': { 'contract is restricted of closing positions on API. Please contact customer service': OnMaintenance, 'maintain': OnMaintenance, }, 'exact': { // err-code 'bad-request': BadRequest, 'base-date-limit-error': BadRequest, // {"status":"error","err-code":"base-date-limit-error","err-msg":"date less than system limit","data":null} 'api-not-support-temp-addr': PermissionDenied, // {"status":"error","err-code":"api-not-support-temp-addr","err-msg":"API withdrawal does not support temporary addresses","data":null} 'timeout': RequestTimeout, // {"ts":1571653730865,"status":"error","err-code":"timeout","err-msg":"Request Timeout"} 'gateway-internal-error': ExchangeNotAvailable, // {"status":"error","err-code":"gateway-internal-error","err-msg":"Failed to load data. Try again later.","data":null} 'account-frozen-balance-insufficient-error': InsufficientFunds, // {"status":"error","err-code":"account-frozen-balance-insufficient-error","err-msg":"trade account balance is not enough, left: `0.0027`","data":null} 'invalid-amount': InvalidOrder, // eg "Paramemter `amount` is invalid." 'order-limitorder-amount-min-error': InvalidOrder, // limit order amount error, min: `0.001` 'order-limitorder-amount-max-error': InvalidOrder, // market order amount error, max: `1000000` 'order-marketorder-amount-min-error': InvalidOrder, // market order amount error, min: `0.01` 'order-limitorder-price-min-error': InvalidOrder, // limit order price error 'order-limitorder-price-max-error': InvalidOrder, // limit order price error 'order-holding-limit-failed': InvalidOrder, // {"status":"error","err-code":"order-holding-limit-failed","err-msg":"Order failed, exceeded the holding limit of this currency","data":null} 'order-orderprice-precision-error': InvalidOrder, // {"status":"error","err-code":"order-orderprice-precision-error","err-msg":"order price precision error, scale: `4`","data":null} 'order-etp-nav-price-max-error': InvalidOrder, // {"status":"error","err-code":"order-etp-nav-price-max-error","err-msg":"Order price cannot be higher than 5% of NAV","data":null} 'order-orderstate-error': OrderNotFound, // canceling an already canceled order 'order-queryorder-invalid': OrderNotFound, // querying a non-existent order 'order-update-error': ExchangeNotAvailable, // undocumented error 'api-signature-check-failed': AuthenticationError, 'api-signature-not-valid': AuthenticationError, // {"status":"error","err-code":"api-signature-not-valid","err-msg":"Signature not valid: Incorrect Access key [Access key错误]","data":null} 'base-record-invalid': OrderNotFound, // https://github.com/ccxt/ccxt/issues/5750 'base-symbol-trade-disabled': BadSymbol, // {"status":"error","err-code":"base-symbol-trade-disabled","err-msg":"Trading is disabled for this symbol","data":null} 'base-symbol-error': BadSymbol, // {"status":"error","err-code":"base-symbol-error","err-msg":"The symbol is invalid","data":null} 'system-maintenance': OnMaintenance, // {"status": "error", "err-code": "system-maintenance", "err-msg": "System is in maintenance!", "data": null} // err-msg 'invalid symbol': BadSymbol, // {"ts":1568813334794,"status":"error","err-code":"invalid-parameter","err-msg":"invalid symbol"} 'symbol trade not open now': BadSymbol, // {"ts":1576210479343,"status":"error","err-code":"invalid-parameter","err-msg":"symbol trade not open now"}, 'invalid-address': BadRequest, // {"status":"error","err-code":"invalid-address","err-msg":"Invalid address.","data":null}, 'base-currency-chain-error': BadRequest, // {"status":"error","err-code":"base-currency-chain-error","err-msg":"The current currency chain does not exist","data":null}, 'dw-insufficient-balance': InsufficientFunds, // {"status":"error","err-code":"dw-insufficient-balance","err-msg":"Insufficient balance. You can only transfer `12.3456` at most.","data":null} }, }, 'options': { 'defaultNetwork': 'ERC20', 'networks': { 'ETH': 'erc20', 'TRX': 'trc20', 'HRC20': 'hrc20', 'HECO': 'hrc20', 'HT': 'hrc20', 'ALGO': 'algo', 'OMNI': '', }, // https://github.com/ccxt/ccxt/issues/5376 'fetchOrdersByStatesMethod': 'private_get_order_orders', // 'private_get_order_history' // https://github.com/ccxt/ccxt/pull/5392 'fetchOpenOrdersMethod': 'fetch_open_orders_v1', // 'fetch_open_orders_v2' // https://github.com/ccxt/ccxt/issues/5388 'createMarketBuyOrderRequiresPrice': true, 'fetchMarketsMethod': 'publicGetCommonSymbols', 'fetchBalanceMethod': 'privateGetAccountAccountsIdBalance', 'createOrderMethod': 'privatePostOrderOrdersPlace', 'language': 'en-US', 'broker': { 'id': 'AA03022abc', }, }, 'commonCurrencies': { // https://github.com/ccxt/ccxt/issues/6081 // https://github.com/ccxt/ccxt/issues/3365 // https://github.com/ccxt/ccxt/issues/2873 'GET': 'Themis', // conflict with GET (Guaranteed Entrance Token, GET Protocol) 'GTC': 'Game.com', // conflict with Gitcoin and Gastrocoin 'HIT': 'HitChain', 'HOT': 'Hydro Protocol', // conflict with HOT (Holo) https://github.com/ccxt/ccxt/issues/4929 // https://github.com/ccxt/ccxt/issues/7399 // https://coinmarketcap.com/currencies/pnetwork/ // https://coinmarketcap.com/currencies/penta/markets/ // https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/ 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', 'BIFI': 'Bitcoin File', // conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706 }, }); } async fetchTime (params = {}) { /** * @method * @name huobijp#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ const response = await this.publicGetCommonTimestamp (params); return this.safeInteger (response, 'data'); } async fetchTradingLimits (symbols = undefined, params = {}) { // this method should not be called directly, use loadTradingLimits () instead // by default it will try load withdrawal fees of all currencies (with separate requests) // however if you define symbols = [ 'ETH/BTC', 'LTC/BTC' ] in args it will only load those await this.loadMarkets (); if (symbols === undefined) { symbols = this.symbols; } const result = {}; for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; result[symbol] = await this.fetchTradingLimitsById (this.marketId (symbol), params); } return result; } async fetchTradingLimitsById (id, params = {}) { const request = { 'symbol': id, }; const response = await this.publicGetCommonExchange (this.extend (request, params)); // // { status: "ok", // data: { symbol: "aidocbtc", // 'buy-limit-must-less-than': 1.1, // 'sell-limit-must-greater-than': 0.9, // 'limit-order-must-greater-than': 1, // 'limit-order-must-less-than': 5000000, // 'market-buy-order-must-greater-than': 0.0001, // 'market-buy-order-must-less-than': 100, // 'market-sell-order-must-greater-than': 1, // 'market-sell-order-must-less-than': 500000, // 'circuit-break-when-greater-than': 10000, // 'circuit-break-when-less-than': 10, // 'market-sell-order-rate-must-less-than': 0.1, // 'market-buy-order-rate-must-less-than': 0.1 } } // return this.parseTradingLimits (this.safeValue (response, 'data', {})); } parseTradingLimits (limits, symbol = undefined, params = {}) { // // { symbol: "aidocbtc", // 'buy-limit-must-less-than': 1.1, // 'sell-limit-must-greater-than': 0.9, // 'limit-order-must-greater-than': 1, // 'limit-order-must-less-than': 5000000, // 'market-buy-order-must-greater-than': 0.0001, // 'market-buy-order-must-less-than': 100, // 'market-sell-order-must-greater-than': 1, // 'market-sell-order-must-less-than': 500000, // 'circuit-break-when-greater-than': 10000, // 'circuit-break-when-less-than': 10, // 'market-sell-order-rate-must-less-than': 0.1, // 'market-buy-order-rate-must-less-than': 0.1 } // return { 'info': limits, 'limits': { 'amount': { 'min': this.safeNumber (limits, 'limit-order-must-greater-than'), 'max': this.safeNumber (limits, 'limit-order-must-less-than'), }, }, }; } costToPrecision (symbol, cost) { return this.decimalToPrecision (cost, TRUNCATE, this.markets[symbol]['precision']['cost'], this.precisionMode); } async fetchMarkets (params = {}) { /** * @method * @name huobijp#fetchMarkets * @description retrieves data on all markets for huobijp * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ const method = this.options['fetchMarketsMethod']; const response = await this[method] (params); // // { // "status": "ok", // "data": [ // { // "base-currency": "xrp", // "quote-currency": "btc", // "price-precision": 9, // "amount-precision": 2, // "symbol-partition": "default", // "symbol": "xrpbtc", // "state": "online", // "value-precision": 8, // "min-order-amt": 1, // "max-order-amt": 5000000, // "min-order-value": 0.0001, // "limit-order-min-order-amt": 1, // "limit-order-max-order-amt": 5000000, // "limit-order-max-buy-amt": 5000000, // "limit-order-max-sell-amt": 5000000, // "sell-market-min-order-amt": 1, // "sell-market-max-order-amt": 500000, // "buy-market-max-order-value": 100, // "leverage-ratio": 5, // "super-margin-leverage-ratio": 3, // "api-trading": "enabled", // "tags": "" // } // ... // ] // } // const markets = this.safeValue (response, 'data', []); const numMarkets = markets.length; if (numMarkets < 1) { throw new NetworkError (this.id + ' fetchMarkets() returned empty response: ' + this.json (markets)); } const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; const baseId = this.safeString (market, 'base-currency'); const quoteId = this.safeString (market, 'quote-currency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const state = this.safeString (market, 'state'); const leverageRatio = this.safeString (market, 'leverage-ratio', '1'); const superLeverageRatio = this.safeString (market, 'super-margin-leverage-ratio', '1'); const margin = Precise.stringGt (leverageRatio, '1') || Precise.stringGt (superLeverageRatio, '1'); const fee = (base === 'OMG') ? 0 : 0.2 / 100; result.push ({ 'id': baseId + quoteId, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': margin, 'swap': false, 'future': false, 'option': false, 'active': (state === 'online'), 'contract': false, 'linear': undefined, 'inverse': undefined, 'taker': fee, 'maker': fee, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'price-precision'))), 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'amount-precision'))), 'cost': this.parseNumber (this.parsePrecision (this.safeString (market, 'value-precision'))), }, 'limits': { 'leverage': { 'min': this.parseNumber ('1'), 'max': this.parseNumber (leverageRatio), 'superMax': this.parseNumber (superLeverageRatio), }, 'amount': { 'min': this.safeNumber (market, 'min-order-amt'), 'max': this.safeNumber (market, 'max-order-amt'), }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.safeNumber (market, 'min-order-value'), 'max': undefined, }, }, 'info': market, }); } return result; } parseTicker (ticker, market = undefined) { // // fetchTicker // // { // "amount": 26228.672978342216, // "open": 9078.95, // "close": 9146.86, // "high": 9155.41, // "id": 209988544334, // "count": 265846, // "low": 8988.0, // "version": 209988544334, // "ask": [ 9146.87, 0.156134 ], // "vol": 2.3822168242201668E8, // "bid": [ 9146.86, 0.080758 ], // } // // fetchTickers // { // symbol: "bhdht", // open: 2.3938, // high: 2.4151, // low: 2.3323, // close: 2.3909, // amount: 628.992, // vol: 1493.71841095, // count: 2088, // bid: 2.3643, // bidSize: 0.7136, // ask: 2.4061, // askSize: 0.4156 // } // const symbol = this.safeSymbol (undefined, market); const timestamp = this.safeInteger (ticker, 'ts'); let bid = undefined; let bidVolume = undefined; let ask = undefined; let askVolume = undefined; if ('bid' in ticker) { if (Array.isArray (ticker['bid'])) { bid = this.safeString (ticker['bid'], 0); bidVolume = this.safeString (ticker['bid'], 1); } else { bid = this.safeString (ticker, 'bid'); bidVolume = this.safeString (ticker, 'bidSize'); } } if ('ask' in ticker) { if (Array.isArray (ticker['ask'])) { ask = this.safeString (ticker['ask'], 0); askVolume = this.safeString (ticker['ask'], 1); } else { ask = this.safeString (ticker, 'ask'); askVolume = this.safeString (ticker, 'askSize'); } } const open = this.safeString (ticker, 'open'); const close = this.safeString (ticker, 'close'); const baseVolume = this.safeString (ticker, 'amount'); const quoteVolume = this.safeString (ticker, 'vol'); return this.safeTicker ({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': this.safeString (ticker, 'high'), 'low': this.safeString (ticker, 'low'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, 'askVolume': askVolume, 'vwap': undefined, 'open': open, 'close': close, 'last': close, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, }, market); } async fetchOrderBook (symbol, limit = undefined, params = {}) { /** * @method * @name huobijp#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int|undefined} limit the maximum amount of order book entries to return * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], 'type': 'step0', }; const response = await this.marketGetDepth (this.extend (request, params)); // // { // "status": "ok", // "ch": "market.btcusdt.depth.step0", // "ts": 1583474832790, // "tick": { // "bids": [ // [ 9100.290000000000000000, 0.200000000000000000 ], // [ 9099.820000000000000000, 0.200000000000000000 ], // [ 9099.610000000000000000, 0.205000000000000000 ], // ], // "asks": [ // [ 9100.640000000000000000, 0.005904000000000000 ], // [ 9101.010000000000000000, 0.287311000000000000 ], // [ 9101.030000000000000000, 0.012121000000000000 ], // ], // "ts":1583474832008, // "version":104999698780 // } // } // if ('tick' in response) { if (!response['tick']) { throw new BadSymbol (this.id + ' fetchOrderBook() returned empty response: ' + this.json (response)); } const tick = this.safeValue (response, 'tick'); const timestamp = this.safeInteger (tick, 'ts', this.safeInteger (response, 'ts')); const result = this.parseOrderBook (tick, symbol, timestamp); result['nonce'] = this.safeInteger (tick, 'version'); return result; } throw new ExchangeError (this.id + ' fetchOrderBook() returned unrecognized response: ' + this.json (response)); } async fetchTicker (symbol, params = {}) { /** * @method * @name huobijp#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], }; const response = await this.marketGetDetailMerged (this.extend (request, params)); // // { // "status": "ok", // "ch": "market.btcusdt.detail.merged", // "ts": 1583494336669, // "tick": { // "amount": 26228.672978342216, // "open": 9078.95, // "close": 9146.86, // "high": 9155.41, // "id": 209988544334, // "count": 265846, // "low": 8988.0, // "version": 209988544334, // "ask": [ 9146.87, 0.156134 ], // "vol": 2.3822168242201668E8, // "bid": [ 9146.86, 0.080758 ], // } // } // const ticker = this.parseTicker (response['tick'], market); const timestamp = this.safeInteger (response, 'ts'); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); return ticker; } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name huobijp#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @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 huobijp api endpoint * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); symbols = this.marketSymbols (symbols); const response = await this.marketGetTickers (params); const tickers = this.safeValue (response, 'data', []); const timestamp = this.safeInteger (response, 'ts'); const result = {}; for (let i = 0; i < tickers.length; i++) { const marketId = this.safeString (tickers[i], 'symbol'); const market = this.safeMarket (marketId); const symbol = market['symbol']; const ticker = this.parseTicker (tickers[i], market); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } parseTrade (trade, market = undefined) { // // fetchTrades (public) // // { // "amount": 0.010411000000000000, // "trade-id": 102090736910, // "ts": 1583497692182, // "id": 10500517034273194594947, // "price": 9096.050000000000000000, // "direction": "sell" // } // // fetchMyTrades (private) // // { // 'symbol': 'swftcbtc', // 'fee-currency': 'swftc', // 'filled-fees': '0', // 'source': 'spot-api', // 'id': 83789509854000, // 'type': 'buy-limit', // 'order-id': 83711103204909, // 'filled-points': '0.005826843283532154', // 'fee-deduct-currency': 'ht', // 'filled-amount': '45941.53', // 'price': '0.0000001401', // 'created-at': 1597933260729, // 'match-id': 100087455560, // 'role': 'maker', // 'trade-id': 100050305348 // }, // const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger2 (trade, 'ts', 'created-at'); const order = this.safeString (trade, 'order-id'); let side = this.safeString (trade, 'direction'); let type = this.safeString (trade, 'type'); if (type !== undefined) { const typeParts = type.split ('-'); side = typeParts[0]; type = typeParts[1]; } const takerOrMaker = this.safeString (trade, 'role'); const priceString = this.safeString (trade, 'price'); const amountString = this.safeString2 (trade, 'filled-amount', 'amount'); const price = this.parseNumber (priceString); const amount = this.parseNumber (amountString); const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; let feeCost = this.safeNumber (trade, 'filled-fees'); let feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-currency')); const filledPoints = this.safeNumber (trade, 'filled-points'); if (filledPoints !== undefined) { if ((feeCost === undefined) || (feeCost === 0.0)) { feeCost = filledPoints; feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-deduct-currency')); } } if (feeCost !== undefined) { fee = { 'cost': feeCost, 'currency': feeCurrency, }; } const tradeId = this.safeString2 (trade, 'trade-id', 'tradeId'); const id = this.safeString (trade, 'id', tradeId); return { 'id': id, 'info': trade, 'order': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': symbol, 'type': type, 'side': side, 'takerOrMaker': takerOrMaker, 'price': price, 'amount': amount, 'cost': cost, 'fee': fee, }; } async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name huobijp#fetchOrderTrades * @description fetch all the trades made from a single order * @param {string} id order id * @param {string|undefined} symbol unified market symbol * @param {int|undefined} since the earliest time in ms to fetch trades for * @param {int|undefined} limit the maximum number of trades to retrieve * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure} */ await this.loadMarkets (); const request = { 'id': id, }; const response = await this.privateGetOrderOrdersIdMatchresults (this.extend (request, params)); return this.parseTrades (response['data'], undefined, since, limit); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name huobijp#fetchMyTrades * @description fetch all trades made by the user * @param {string|undefined} symbol unified market symbol * @param {int|undefined} since the earliest time in ms to fetch trades for * @param {int|undefined} limit the maximum number of trades structures to retrieve * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure} */ await this.loadMarkets (); let market = undefined; const request = {}; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } if (limit !== undefined) { request['size'] = limit; // 1-100 orders, default is 100 } if (since !== undefined) { request['start-time'] = since; // a date within 120 days from today // request['end-time'] = this.sum (since, 172800000); // 48 hours window } const response = await this.privateGetOrderMatchresults (this.extend (request, params)); return this.parseTrades (response['data'], market, since, limit); } async fetchTrades (symbol, since = undefined, limit = 1000, params = {}) { /** * @method * @name huobijp#fetchTrades * @description get the list of most recent trades for a particular symbol * @param {string} symbol unified symbol of the market to fetch trades for * @param {int|undefined} since timestamp in ms of the earliest trade to fetch * @param {int|undefined} limit the maximum amount of trades to fetch * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], }; if (limit !== undefined) { request['size'] = limit; } const response = await this.marketGetHistoryTrade (this.extend (request, params)); // // { // "status": "ok", // "ch": "market.btcusdt.trade.detail", // "ts": 1583497692365, // "data": [ // { // "id": 105005170342, // "ts": 1583497692182, // "data": [ // { // "amount": 0.010411000000000000, // "trade-id": 102090736910, // "ts": 1583497692182, // "id": 10500517034273194594947, // "price": 9096.050000000000000000, // "direction": "sell" // } // ] // }, // // ... // ] // } // const data = this.safeValue (response, 'data', []); let result = []; for (let i = 0; i < data.length; i++) { const trades = this.safeValue (data[i], 'data', []); for (let j = 0; j < trades.length; j++) { const trade = this.parseTrade (trades[j], market); result.push (trade); } } result = this.sortBy (result, 'timestamp'); return this.filterBySymbolSinceLimit (result, market['symbol'], since, limit); } parseOHLCV (ohlcv, market = undefined) { // // { // "amount":1.2082, // "open":0.025096, // "close":0.025095, // "high":0.025096, // "id":1591515300, // "count":6, // "low":0.025095, // "vol":0.0303205097 // } // return [ this.safeTimestamp (ohlcv, 'id'), this.safeNumber (ohlcv, 'open'), this.safeNumber (ohlcv, 'high'), this.safeNumber (ohlcv, 'low'), this.safeNumber (ohlcv, 'close'), this.safeNumber (ohlcv, 'amount'), ]; } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = 1000, params = {}) { /** * @method * @name huobijp#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @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|undefined} since timestamp in ms of the earliest candle to fetch * @param {int|undefined} limit the maximum amount of candles to fetch * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'symbol': market['id'], 'period': this.timeframes[timeframe], }; if (limit !== undefined) { request['size'] = limit; } const response = await this.marketGetHistoryKline (this.extend (request, params)); // // { // "status":"ok", // "ch":"market.ethbtc.kline.1min", // "ts":1591515374371, // "data":[ // {"amount":0.0,"open":0.025095,"close":0.025095,"high":0.025095,"id":1591515360,"count":0,"low":0.025095,"vol":0.0}, // {"amount":1.2082,"open":0.025096,"close":0.025095,"high":0.025096,"id":1591515300,"count":6,"low":0.025095,"vol":0.0303205097}, // {"amount":0.0648,"open":0.025096,"close":0.025096,"high":0.025096,"id":1591515240,"count":2,"low":0.025096,"vol":0.0016262208}, // ] // } // const data = this.safeValue (response, 'data', []); return this.parseOHLCVs (data, market, timeframe, since, limit); } async fetchAccounts (params = {}) { /** * @method * @name huobijp#fetchAccounts * @description fetch all the accounts associated with a profile * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/en/latest/manual.html#account-structure} indexed by the account type */ await this.loadMarkets (); const response = await this.privateGetAccountAccounts (params); return response['data']; } async fetchCurrencies (params = {}) { /** * @method * @name huobijp#fetchCurrencies * @description fetches all available currencies on an exchange * @param {object} params extra parameters specific to the huobijp api endpoint * @returns {object} an associative dictionary of currencies */ const request = { 'language': this.options['language'], }; const response = await this.publicGetSettingsCurrencys (this.extend (request, params)); // // { // "status":"ok", // "data":[ // { // "currency-addr-with-tag":false, // "fast-confirms":12, // "safe-confirms":12, // "currency-type":"eth", // "quote-currency":true, // "withdraw-enable-timestamp":1609430400000, // "deposit-enable-timestamp":1609430400000, // "currency-partition":"all", // "support-sites":["OTC","INSTITUTION","MINEPOOL"], // "withdraw-precision":6, // "visible-assets-timestamp":1508839200000, // "deposit-min-amount":"1", // "withdraw-min-amount":"10", // "show-precision":"8", // "tags":"", // "weight":23, // "full-name":"Tether