UNPKG

ccxt

Version:

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

1,115 lines (1,113 loc) • 78.7 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // --------------------------------------------------------------------------- import bitmexRest from '../bitmex.js'; import { AuthenticationError, ExchangeError, RateLimitExceeded } from '../base/errors.js'; import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js'; import { sha256 } from '../static_dependencies/noble-hashes/sha256.js'; // --------------------------------------------------------------------------- export default class bitmex extends bitmexRest { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchBalance': true, 'watchLiquidations': true, 'watchLiquidationsForSymbols': true, 'watchMyLiquidations': undefined, 'watchMyLiquidationsForSymbols': undefined, 'watchMyTrades': true, 'watchOHLCV': true, 'watchOrderBook': true, 'watchOrderBookForSymbols': true, 'watchOrders': true, 'watchPostions': true, 'watchTicker': true, 'watchTickers': true, 'watchTrades': true, 'watchTradesForSymbols': true, }, 'urls': { 'test': { 'ws': 'wss://ws.testnet.bitmex.com/realtime', }, 'api': { 'ws': 'wss://ws.bitmex.com/realtime', }, }, // 'versions': { // 'ws': '0.2.0', // }, 'options': { 'watchOrderBookLevel': 'orderBookL2', 'tradesLimit': 1000, 'OHLCVLimit': 1000, }, 'exceptions': { 'ws': { 'exact': {}, 'broad': { 'Rate limit exceeded': RateLimitExceeded, }, }, }, }); } /** * @method * @name bitmex#watchTicker * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @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 watchTicker(symbol, params = {}) { await this.loadMarkets(); symbol = this.symbol(symbol); const tickers = await this.watchTickers([symbol], params); return tickers[symbol]; } /** * @method * @name bitmex#watchTickers * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @param {string[]} symbols 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 watchTickers(symbols = undefined, params = {}) { await this.loadMarkets(); symbols = this.marketSymbols(symbols, undefined, true); const name = 'instrument'; const url = this.urls['api']['ws']; const messageHashes = []; const rawSubscriptions = []; if (symbols !== undefined) { for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const market = this.market(symbol); const subscription = name + ':' + market['id']; rawSubscriptions.push(subscription); const messageHash = 'ticker:' + symbol; messageHashes.push(messageHash); } } else { rawSubscriptions.push(name); messageHashes.push('alltickers'); } const request = { 'op': 'subscribe', 'args': rawSubscriptions, }; const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), rawSubscriptions); if (this.newUpdates) { const result = {}; result[ticker['symbol']] = ticker; return result; } return this.filterByArray(this.tickers, 'symbol', symbols); } handleTicker(client, message) { // // { // "table": "instrument", // "action": "partial", // "keys": [ "symbol" ], // "types": { // "symbol": "symbol", // "rootSymbol": "symbol", // "state": "symbol", // "typ": "symbol", // "listing": "timestamp", // "front": "timestamp", // "expiry": "timestamp", // "settle": "timestamp", // "relistInterval": "timespan", // "inverseLeg": "symbol", // "sellLeg": "symbol", // "buyLeg": "symbol", // "optionStrikePcnt": "float", // "optionStrikeRound": "float", // "optionStrikePrice": "float", // "optionMultiplier": "float", // "positionCurrency": "symbol", // "underlying": "symbol", // "quoteCurrency": "symbol", // "underlyingSymbol": "symbol", // "reference": "symbol", // "referenceSymbol": "symbol", // "calcInterval": "timespan", // "publishInterval": "timespan", // "publishTime": "timespan", // "maxOrderQty": "long", // "maxPrice": "float", // "lotSize": "long", // "tickSize": "float", // "multiplier": "long", // "settlCurrency": "symbol", // "underlyingToPositionMultiplier": "long", // "underlyingToSettleMultiplier": "long", // "quoteToSettleMultiplier": "long", // "isQuanto": "boolean", // "isInverse": "boolean", // "initMargin": "float", // "maintMargin": "float", // "riskLimit": "long", // "riskStep": "long", // "limit": "float", // "capped": "boolean", // "taxed": "boolean", // "deleverage": "boolean", // "makerFee": "float", // "takerFee": "float", // "settlementFee": "float", // "insuranceFee": "float", // "fundingBaseSymbol": "symbol", // "fundingQuoteSymbol": "symbol", // "fundingPremiumSymbol": "symbol", // "fundingTimestamp": "timestamp", // "fundingInterval": "timespan", // "fundingRate": "float", // "indicativeFundingRate": "float", // "rebalanceTimestamp": "timestamp", // "rebalanceInterval": "timespan", // "openingTimestamp": "timestamp", // "closingTimestamp": "timestamp", // "sessionInterval": "timespan", // "prevClosePrice": "float", // "limitDownPrice": "float", // "limitUpPrice": "float", // "bankruptLimitDownPrice": "float", // "bankruptLimitUpPrice": "float", // "prevTotalVolume": "long", // "totalVolume": "long", // "volume": "long", // "volume24h": "long", // "prevTotalTurnover": "long", // "totalTurnover": "long", // "turnover": "long", // "turnover24h": "long", // "homeNotional24h": "float", // "foreignNotional24h": "float", // "prevPrice24h": "float", // "vwap": "float", // "highPrice": "float", // "lowPrice": "float", // "lastPrice": "float", // "lastPriceProtected": "float", // "lastTickDirection": "symbol", // "lastChangePcnt": "float", // "bidPrice": "float", // "midPrice": "float", // "askPrice": "float", // "impactBidPrice": "float", // "impactMidPrice": "float", // "impactAskPrice": "float", // "hasLiquidity": "boolean", // "openInterest": "long", // "openValue": "long", // "fairMethod": "symbol", // "fairBasisRate": "float", // "fairBasis": "float", // "fairPrice": "float", // "markMethod": "symbol", // "markPrice": "float", // "indicativeTaxRate": "float", // "indicativeSettlePrice": "float", // "optionUnderlyingPrice": "float", // "settledPrice": "float", // "timestamp": "timestamp" // }, // "foreignKeys": { // "inverseLeg": "instrument", // "sellLeg": "instrument", // "buyLeg": "instrument" // }, // "attributes": { symbol: "unique" }, // "filter": { symbol: "XBTUSD" }, // "data": [ // { // "symbol": "XBTUSD", // "rootSymbol": "XBT", // "state": "Open", // "typ": "FFWCSX", // "listing": "2016-05-13T12:00:00.000Z", // "front": "2016-05-13T12:00:00.000Z", // "expiry": null, // "settle": null, // "relistInterval": null, // "inverseLeg": '', // "sellLeg": '', // "buyLeg": '', // "optionStrikePcnt": null, // "optionStrikeRound": null, // "optionStrikePrice": null, // "optionMultiplier": null, // "positionCurrency": "USD", // "underlying": "XBT", // "quoteCurrency": "USD", // "underlyingSymbol": "XBT=", // "reference": "BMEX", // "referenceSymbol": ".BXBT", // "calcInterval": null, // "publishInterval": null, // "publishTime": null, // "maxOrderQty": 10000000, // "maxPrice": 1000000, // "lotSize": 1, // "tickSize": 0.5, // "multiplier": -100000000, // "settlCurrency": "XBt", // "underlyingToPositionMultiplier": null, // "underlyingToSettleMultiplier": -100000000, // "quoteToSettleMultiplier": null, // "isQuanto": false, // "isInverse": true, // "initMargin": 0.01, // "maintMargin": 0.005, // "riskLimit": 20000000000, // "riskStep": 10000000000, // "limit": null, // "capped": false, // "taxed": true, // "deleverage": true, // "makerFee": -0.00025, // "takerFee": 0.00075, // "settlementFee": 0, // "insuranceFee": 0, // "fundingBaseSymbol": ".XBTBON8H", // "fundingQuoteSymbol": ".USDBON8H", // "fundingPremiumSymbol": ".XBTUSDPI8H", // "fundingTimestamp": "2020-01-29T12:00:00.000Z", // "fundingInterval": "2000-01-01T08:00:00.000Z", // "fundingRate": 0.000597, // "indicativeFundingRate": 0.000652, // "rebalanceTimestamp": null, // "rebalanceInterval": null, // "openingTimestamp": "2020-01-29T11:00:00.000Z", // "closingTimestamp": "2020-01-29T12:00:00.000Z", // "sessionInterval": "2000-01-01T01:00:00.000Z", // "prevClosePrice": 9063.96, // "limitDownPrice": null, // "limitUpPrice": null, // "bankruptLimitDownPrice": null, // "bankruptLimitUpPrice": null, // "prevTotalVolume": 1989881049026, // "totalVolume": 1990196740950, // "volume": 315691924, // "volume24h": 4491824765, // "prevTotalTurnover": 27865497128425564, // "totalTurnover": 27868891594857150, // "turnover": 3394466431587, // "turnover24h": 48863390064843, // "homeNotional24h": 488633.9006484273, // "foreignNotional24h": 4491824765, // "prevPrice24h": 9091, // "vwap": 9192.8663, // "highPrice": 9440, // "lowPrice": 8886, // "lastPrice": 9287, // "lastPriceProtected": 9287, // "lastTickDirection": "PlusTick", // "lastChangePcnt": 0.0216, // "bidPrice": 9286, // "midPrice": 9286.25, // "askPrice": 9286.5, // "impactBidPrice": 9285.9133, // "impactMidPrice": 9286.75, // "impactAskPrice": 9287.6382, // "hasLiquidity": true, // "openInterest": 967826984, // "openValue": 10432207060536, // "fairMethod": "FundingRate", // "fairBasisRate": 0.6537149999999999, // "fairBasis": 0.33, // "fairPrice": 9277.2, // "markMethod": "FairPrice", // "markPrice": 9277.2, // "indicativeTaxRate": 0, // "indicativeSettlePrice": 9276.87, // "optionUnderlyingPrice": null, // "settledPrice": null, // "timestamp": "2020-01-29T11:31:37.114Z" // } // ] // } // const data = this.safeList(message, 'data', []); const tickers = {}; for (let i = 0; i < data.length; i++) { const update = data[i]; const marketId = this.safeString(update, 'symbol'); const symbol = this.safeSymbol(marketId); if (!(symbol in this.tickers)) { this.tickers[symbol] = this.parseTicker({}); } const updatedTicker = this.parseTicker(update); const fullParsedTicker = this.deepExtend(this.tickers[symbol], updatedTicker); tickers[symbol] = fullParsedTicker; this.tickers[symbol] = fullParsedTicker; const messageHash = 'ticker:' + symbol; client.resolve(fullParsedTicker, messageHash); client.resolve(fullParsedTicker, 'alltickers'); } return message; } /** * @method * @name bitmex#watchLiquidations * @description watch the public liquidations of a trading pair * @see https://www.bitmex.com/app/wsAPI#Liquidation * @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 bitmex api endpoint * @returns {object} an array of [liquidation structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure} */ async watchLiquidations(symbol, since = undefined, limit = undefined, params = {}) { return this.watchLiquidationsForSymbols([symbol], since, limit, params); } /** * @method * @name bitmex#watchLiquidationsForSymbols * @description watch the public liquidations of a trading pair * @see https://www.bitmex.com/app/wsAPI#Liquidation * @param {string[]} symbols * @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 bitmex api endpoint * @returns {object} an array of [liquidation structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure} */ async watchLiquidationsForSymbols(symbols = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); symbols = this.marketSymbols(symbols, undefined, true, true); const messageHashes = []; const subscriptionHashes = []; if (this.isEmpty(symbols)) { subscriptionHashes.push('liquidation'); messageHashes.push('liquidations'); } else { for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const market = this.market(symbol); subscriptionHashes.push('liquidation:' + market['id']); messageHashes.push('liquidations::' + symbol); } } const url = this.urls['api']['ws']; const request = { 'op': 'subscribe', 'args': subscriptionHashes, }; const newLiquidations = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), subscriptionHashes); if (this.newUpdates) { return newLiquidations; } return this.filterBySymbolsSinceLimit(this.liquidations, symbols, since, limit, true); } handleLiquidation(client, message) { // // { // "table":"liquidation", // "action":"partial", // "keys":[ // "orderID" // ], // "types":{ // "orderID":"guid", // "symbol":"symbol", // "side":"symbol", // "price":"float", // "leavesQty":"long" // }, // "filter":{}, // "data":[ // { // "orderID":"e0a568ee-7830-4428-92c3-73e82b9576ce", // "symbol":"XPLAUSDT", // "side":"Sell", // "price":0.206, // "leavesQty":340 // } // ] // } // const rawLiquidations = this.safeValue(message, 'data', []); const newLiquidations = []; for (let i = 0; i < rawLiquidations.length; i++) { const rawLiquidation = rawLiquidations[i]; const liquidation = this.parseLiquidation(rawLiquidation); const symbol = liquidation['symbol']; let liquidations = this.safeValue(this.liquidations, symbol); if (liquidations === undefined) { const limit = this.safeInteger(this.options, 'liquidationsLimit', 1000); liquidations = new ArrayCache(limit); } liquidations.append(liquidation); this.liquidations[symbol] = liquidations; newLiquidations.push(liquidation); } client.resolve(newLiquidations, 'liquidations'); const liquidationsBySymbol = this.indexBy(newLiquidations, 'symbol'); const symbols = Object.keys(liquidationsBySymbol); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; client.resolve(liquidationsBySymbol[symbol], 'liquidations::' + symbol); } } /** * @method * @name bitmex#watchBalance * @description watch balance and get the amount of funds available for trading or funds locked in orders * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure} */ async watchBalance(params = {}) { await this.loadMarkets(); await this.authenticate(); const messageHash = 'margin'; const url = this.urls['api']['ws']; const request = { 'op': 'subscribe', 'args': [ messageHash, ], }; return await this.watch(url, messageHash, this.extend(request, params), messageHash); } handleBalance(client, message) { // // { // "table": "margin", // "action": "partial", // "keys": [ "account" ], // "types": { // "account": "long", // "currency": "symbol", // "riskLimit": "long", // "prevState": "symbol", // "state": "symbol", // "action": "symbol", // "amount": "long", // "pendingCredit": "long", // "pendingDebit": "long", // "confirmedDebit": "long", // "prevRealisedPnl": "long", // "prevUnrealisedPnl": "long", // "grossComm": "long", // "grossOpenCost": "long", // "grossOpenPremium": "long", // "grossExecCost": "long", // "grossMarkValue": "long", // "riskValue": "long", // "taxableMargin": "long", // "initMargin": "long", // "maintMargin": "long", // "sessionMargin": "long", // "targetExcessMargin": "long", // "varMargin": "long", // "realisedPnl": "long", // "unrealisedPnl": "long", // "indicativeTax": "long", // "unrealisedProfit": "long", // "syntheticMargin": "long", // "walletBalance": "long", // "marginBalance": "long", // "marginBalancePcnt": "float", // "marginLeverage": "float", // "marginUsedPcnt": "float", // "excessMargin": "long", // "excessMarginPcnt": "float", // "availableMargin": "long", // "withdrawableMargin": "long", // "timestamp": "timestamp", // "grossLastValue": "long", // "commission": "float" // }, // "foreignKeys": {}, // "attributes": { account: "sorted" }, // "filter": { account: 1455728 }, // "data": [ // { // "account": 1455728, // "currency": "XBt", // "riskLimit": 1000000000000, // "prevState": '', // "state": '', // "action": '', // "amount": 263542, // "pendingCredit": 0, // "pendingDebit": 0, // "confirmedDebit": 0, // "prevRealisedPnl": 0, // "prevUnrealisedPnl": 0, // "grossComm": 0, // "grossOpenCost": 0, // "grossOpenPremium": 0, // "grossExecCost": 0, // "grossMarkValue": 0, // "riskValue": 0, // "taxableMargin": 0, // "initMargin": 0, // "maintMargin": 0, // "sessionMargin": 0, // "targetExcessMargin": 0, // "varMargin": 0, // "realisedPnl": 0, // "unrealisedPnl": 0, // "indicativeTax": 0, // "unrealisedProfit": 0, // "syntheticMargin": null, // "walletBalance": 263542, // "marginBalance": 263542, // "marginBalancePcnt": 1, // "marginLeverage": 0, // "marginUsedPcnt": 0, // "excessMargin": 263542, // "excessMarginPcnt": 1, // "availableMargin": 263542, // "withdrawableMargin": 263542, // "timestamp": "2020-08-03T12:01:01.246Z", // "grossLastValue": 0, // "commission": null // } // ] // } // const data = this.safeValue(message, 'data'); const balance = this.parseBalance(data); this.balance = this.extend(this.balance, balance); const messageHash = this.safeString(message, 'table'); client.resolve(this.balance, messageHash); } handleTrades(client, message) { // // initial snapshot // // { // "table": "trade", // "action": "partial", // "keys": [], // "types": { // "timestamp": "timestamp", // "symbol": "symbol", // "side": "symbol", // "size": "long", // "price": "float", // "tickDirection": "symbol", // "trdMatchID": "guid", // "grossValue": "long", // "homeNotional": "float", // "foreignNotional": "float" // }, // "foreignKeys": { symbol: "instrument", side: "side" }, // "attributes": { timestamp: "sorted", symbol: "grouped" }, // "filter": { symbol: "XBTUSD" }, // "data": [ // { // "timestamp": "2020-01-30T17:03:07.854Z", // "symbol": "XBTUSD", // "side": "Buy", // "size": 15000, // "price": 9378, // "tickDirection": "ZeroPlusTick", // "trdMatchID": "5b426e7f-83d1-2c80-295d-ee995b8ceb4a", // "grossValue": 159945000, // "homeNotional": 1.59945, // "foreignNotional": 15000 // } // ] // } // // updates // // { // "table": "trade", // "action": "insert", // "data": [ // { // "timestamp": "2020-01-30T17:31:40.160Z", // "symbol": "XBTUSD", // "side": "Sell", // "size": 37412, // "price": 9521.5, // "tickDirection": "ZeroMinusTick", // "trdMatchID": "a4bfc6bc-6cf1-1a11-622e-270eef8ca5c7", // "grossValue": 392938236, // "homeNotional": 3.92938236, // "foreignNotional": 37412 // } // ] // } // const table = 'trade'; const data = this.safeValue(message, 'data', []); const dataByMarketIds = this.groupBy(data, 'symbol'); const marketIds = Object.keys(dataByMarketIds); for (let i = 0; i < marketIds.length; i++) { const marketId = marketIds[i]; const market = this.safeMarket(marketId); const symbol = market['symbol']; const messageHash = table + ':' + symbol; const trades = this.parseTrades(dataByMarketIds[marketId], market); let stored = this.safeValue(this.trades, symbol); if (stored === undefined) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); stored = new ArrayCache(limit); this.trades[symbol] = stored; } for (let j = 0; j < trades.length; j++) { stored.append(trades[j]); } client.resolve(stored, messageHash); } } /** * @method * @name bitmex#watchTrades * @description get the list of most recent trades for a particular symbol * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @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} */ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) { return await this.watchTradesForSymbols([symbol], since, limit, params); } async authenticate(params = {}) { const url = this.urls['api']['ws']; const client = this.client(url); const messageHash = 'authenticated'; const future = client.future(messageHash); const authenticated = this.safeValue(client.subscriptions, messageHash); if (authenticated === undefined) { this.checkRequiredCredentials(); const timestamp = this.milliseconds(); const payload = 'GET' + '/realtime' + timestamp.toString(); const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256); const request = { 'op': 'authKeyExpires', 'args': [ this.apiKey, timestamp, signature, ], }; const message = this.extend(request, params); this.watch(url, messageHash, message, messageHash); } return await future; } handleAuthenticationMessage(client, message) { const authenticated = this.safeBool(message, 'success', false); const messageHash = 'authenticated'; if (authenticated) { // we resolve the future here permanently so authentication only happens once const future = this.safeValue(client.futures, messageHash); future.resolve(true); } else { const error = new AuthenticationError(this.json(message)); client.reject(error, messageHash); if (messageHash in client.subscriptions) { delete client.subscriptions[messageHash]; } } } /** * @method * @name bitmex#watchPositions * @description watch all open positions * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @param {string[]|undefined} symbols list of unified market symbols * @param {int} [since] the earliest time in ms to watch positions for * @param {int} [limit] the maximum number of positions to retrieve * @param {object} params extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure} */ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); await this.authenticate(); const subscriptionHash = 'position'; let messageHash = 'positions'; if (!this.isEmpty(symbols)) { messageHash = '::' + symbols.join(','); } const url = this.urls['api']['ws']; const request = { 'op': 'subscribe', 'args': [ subscriptionHash, ], }; const newPositions = await this.watch(url, messageHash, request, subscriptionHash); if (this.newUpdates) { return newPositions; } return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true); } handlePositions(client, message) { // // partial // { // table: 'position', // action: 'partial', // keys: [ 'account', 'symbol' ], // types: { // account: 'long', // symbol: 'symbol', // currency: 'symbol', // underlying: 'symbol', // quoteCurrency: 'symbol', // commission: 'float', // initMarginReq: 'float', // maintMarginReq: 'float', // riskLimit: 'long', // leverage: 'float', // crossMargin: 'boolean', // deleveragePercentile: 'float', // rebalancedPnl: 'long', // prevRealisedPnl: 'long', // prevUnrealisedPnl: 'long', // openingQty: 'long', // openOrderBuyQty: 'long', // openOrderBuyCost: 'long', // openOrderBuyPremium: 'long', // openOrderSellQty: 'long', // openOrderSellCost: 'long', // openOrderSellPremium: 'long', // currentQty: 'long', // currentCost: 'long', // currentComm: 'long', // realisedCost: 'long', // unrealisedCost: 'long', // grossOpenPremium: 'long', // isOpen: 'boolean', // markPrice: 'float', // markValue: 'long', // riskValue: 'long', // homeNotional: 'float', // foreignNotional: 'float', // posState: 'symbol', // posCost: 'long', // posCross: 'long', // posComm: 'long', // posLoss: 'long', // posMargin: 'long', // posMaint: 'long', // initMargin: 'long', // maintMargin: 'long', // realisedPnl: 'long', // unrealisedPnl: 'long', // unrealisedPnlPcnt: 'float', // unrealisedRoePcnt: 'float', // avgCostPrice: 'float', // avgEntryPrice: 'float', // breakEvenPrice: 'float', // marginCallPrice: 'float', // liquidationPrice: 'float', // bankruptPrice: 'float', // timestamp: 'timestamp' // }, // filter: { account: 412475 }, // data: [ // { // account: 412475, // symbol: 'XBTUSD', // currency: 'XBt', // underlying: 'XBT', // quoteCurrency: 'USD', // commission: 0.00075, // initMarginReq: 0.01, // maintMarginReq: 0.0035, // riskLimit: 20000000000, // leverage: 100, // crossMargin: true, // deleveragePercentile: 1, // rebalancedPnl: 0, // prevRealisedPnl: 0, // prevUnrealisedPnl: 0, // openingQty: 400, // openOrderBuyQty: 0, // openOrderBuyCost: 0, // openOrderBuyPremium: 0, // openOrderSellQty: 0, // openOrderSellCost: 0, // openOrderSellPremium: 0, // currentQty: 400, // currentCost: -912269, // currentComm: 684, // realisedCost: 0, // unrealisedCost: -912269, // grossOpenPremium: 0, // isOpen: true, // markPrice: 43772, // markValue: -913828, // riskValue: 913828, // homeNotional: 0.00913828, // foreignNotional: -400, // posCost: -912269, // posCross: 1559, // posComm: 694, // posLoss: 0, // posMargin: 11376, // posMaint: 3887, // initMargin: 0, // maintMargin: 9817, // realisedPnl: -684, // unrealisedPnl: -1559, // unrealisedPnlPcnt: -0.0017, // unrealisedRoePcnt: -0.1709, // avgCostPrice: 43846.7643, // avgEntryPrice: 43846.7643, // breakEvenPrice: 43880, // marginCallPrice: 20976, // liquidationPrice: 20976, // bankruptPrice: 20941, // timestamp: '2023-12-07T00:09:00.709Z' // } // ] // } // update // { // table: 'position', // action: 'update', // data: [ // { // account: 412475, // symbol: 'XBTUSD', // currency: 'XBt', // currentQty: 400, // markPrice: 43772.75, // markValue: -913812, // riskValue: 913812, // homeNotional: 0.00913812, // posCross: 1543, // posComm: 693, // posMargin: 11359, // posMaint: 3886, // maintMargin: 9816, // unrealisedPnl: -1543, // unrealisedRoePcnt: -0.1691, // liquidationPrice: 20976, // timestamp: '2023-12-07T00:09:10.760Z' // } // ] // } // if (this.positions === undefined) { this.positions = new ArrayCacheBySymbolBySide(); } const cache = this.positions; const rawPositions = this.safeValue(message, 'data', []); const newPositions = []; for (let i = 0; i < rawPositions.length; i++) { const rawPosition = rawPositions[i]; const position = this.parsePosition(rawPosition); newPositions.push(position); cache.append(position); } const messageHashes = this.findMessageHashes(client, 'positions::'); for (let i = 0; i < messageHashes.length; i++) { const messageHash = messageHashes[i]; const parts = messageHash.split('::'); const symbolsString = parts[1]; const symbols = symbolsString.split(','); const positions = this.filterByArray(newPositions, 'symbol', symbols, false); if (!this.isEmpty(positions)) { client.resolve(positions, messageHash); } } client.resolve(newPositions, 'positions'); } /** * @method * @name bitmex#watchOrders * @description watches information on multiple orders made by the user * @see https://www.bitmex.com/app/wsAPI#Subscriptions * @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 * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); await this.authenticate(); const name = 'order'; const subscriptionHash = name; let messageHash = name; if (symbol !== undefined) { symbol = this.symbol(symbol); messageHash += ':' + symbol; } const url = this.urls['api']['ws']; const request = { 'op': 'subscribe', 'args': [ subscriptionHash, ], }; const orders = await this.watch(url, messageHash, request, subscriptionHash); if (this.newUpdates) { limit = orders.getLimit(symbol, limit); } return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true); } handleOrders(client, message) { // // { // "table": "order", // "action": "partial", // "keys": [ "orderID" ], // "types": { // "orderID": "guid", // "clOrdID": "string", // "clOrdLinkID": "symbol", // "account": "long", // "symbol": "symbol", // "side": "symbol", // "simpleOrderQty": "float", // "orderQty": "long", // "price": "float", // "displayQty": "long", // "stopPx": "float", // "pegOffsetValue": "float", // "pegPriceType": "symbol", // "currency": "symbol", // "settlCurrency": "symbol", // "ordType": "symbol", // "timeInForce": "symbol", // "execInst": "symbol", // "contingencyType": "symbol", // "exDestination": "symbol", // "ordStatus": "symbol", // "triggered": "symbol", // "workingIndicator": "boolean", // "ordRejReason": "symbol", // "simpleLeavesQty": "float", // "leavesQty": "long", // "simpleCumQty": "float", // "cumQty": "long", // "avgPx": "float", // "multiLegReportingType": "symbol", // "text": "string", // "transactTime": "timestamp", // "timestamp": "timestamp" // }, // "foreignKeys": { symbol: 'instrument', side: "side", ordStatus: "ordStatus" }, // "attributes": { // "orderID": "grouped", // "account": "grouped", // "ordStatus": "grouped", // "workingIndicator": "grouped" // }, // "filter": { account: 1455728 }, // "data": [ // { // "orderID": "56222c7a-9956-413a-82cf-99f4812c214b", // "clOrdID": '', // "clOrdLinkID": '', // "account": 1455728, // "symbol": "XBTUSD", // "side": "Sell", // "simpleOrderQty": null, // "orderQty": 1, // "price": 40000, // "displayQty": null, // "stopPx": null, // "pegOffsetValue": null, // "pegPriceType": '', // "currency": "USD", // "settlCurrency": "XBt", // "ordType": "Limit", // "timeInForce": "GoodTillCancel", // "execInst": '', // "contingencyType": '', // "exDestination": "XBME", // "ordStatus": "New", // "triggered": '', // "workingIndicator": true, // "ordRejReason": '', // "simpleLeavesQty": null, // "leavesQty": 1, // "simpleCumQty": null, // "cumQty": 0, // "avgPx": null, // "multiLegReportingType": "SingleSecurity", // "text": "Submitted via API.", // "transactTime": "2021-01-02T21:38:49.246Z", // "timestamp": "2021-01-02T21:38:49.246Z" // } // ] // } // // { // "table": "order", // "action": "insert", // "data": [ // { // "orderID": "fa993d8e-f7e4-46ed-8097-04f8e9393585", // "clOrdID": '', // "clOrdLinkID": '', // "account": 1455728, // "symbol": "XBTUSD", // "side": "Sell", // "simpleOrderQty": null, // "orderQty": 1, // "price": 40000, // "displayQty": null, // "stopPx": null, // "pegOffsetValue": null, // "pegPriceType": '', // "currency": "USD", // "settlCurrency": "XBt", // "ordType": "Limit", // "timeInForce": "GoodTillCancel", // "execInst": '', // "contingencyType": '', // "exDestination": "XBME", // "ordStatus": "New", // "triggered": '', // "workingIndicator": true, // "ordRejReason": '', // "simpleLeavesQty": null, // "leavesQty": 1, // "simpleCumQty": null, // "cumQty": 0, // "avgPx": null, // "multiLegReportingType": "SingleSecurity", // "text": "Submitted via API.", // "transactTime": "2021-01-02T23:49:02.286Z", // "timestamp": "2021-01-02T23:49:02.286Z" // } // ] // } // // // // { // "table": "order", // "action": "update", // "data": [ // { // "orderID": "fa993d8e-f7e4-46ed-8097-04f8e9393585", // "ordStatus": "Canceled", // "workingIndicator": false, // "leavesQty": 0, // "text": "Canceled: Canceled via API.\nSubmitted via API.", // "timestamp": "2021-01-02T23:50:51.272Z", // "clOrdID": '', // "account": 1455728, // "symbol": "XBTUSD" // } //