UNPKG

@proton/ccxt

Version:

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

547 lines (544 loc) 23.4 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 ndaxRest from '../ndax.js'; import { ArrayCache } from '../base/ws/Cache.js'; // --------------------------------------------------------------------------- export default class ndax extends ndaxRest { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchOrderBook': true, 'watchTrades': true, 'watchTicker': true, 'watchOHLCV': true, }, 'urls': { 'test': { 'ws': 'wss://ndaxmarginstaging.cdnhop.net:10456/WSAdminGatewa/', }, 'api': { 'ws': 'wss://api.ndax.io/WSGateway', }, }, // 'options': { // 'tradesLimit': 1000, // 'ordersLimit': 1000, // 'OHLCVLimit': 1000, // }, }); } requestId() { const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1); this.options['requestId'] = requestId; return requestId; } async watchTicker(symbol, params = {}) { /** * @method * @name ndax#watchTicker * @description watches 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 ndax api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ const omsId = this.safeInteger(this.options, 'omsId', 1); await this.loadMarkets(); const market = this.market(symbol); const name = 'SubscribeLevel1'; const messageHash = name + ':' + market['id']; const url = this.urls['api']['ws']; const requestId = this.requestId(); const payload = { 'OMSId': omsId, 'InstrumentId': parseInt(market['id']), // conditionally optional // 'Symbol': market['info']['symbol'], // conditionally optional }; const request = { 'm': 0, 'i': requestId, 'n': name, 'o': this.json(payload), // JSON-formatted string containing the data being sent with the message }; const message = this.extend(request, params); return await this.watch(url, messageHash, message, messageHash); } handleTicker(client, message) { const payload = this.safeValue(message, 'o', {}); // // { // "OMSId": 1, // "InstrumentId": 1, // "BestBid": 6423.57, // "BestOffer": 6436.53, // "LastTradedPx": 6423.57, // "LastTradedQty": 0.96183964, // "LastTradeTime": 1534862990343, // "SessionOpen": 6249.64, // "SessionHigh": 11111, // "SessionLow": 4433, // "SessionClose": 6249.64, // "Volume": 0.96183964, // "CurrentDayVolume": 3516.31668185, // "CurrentDayNumTrades": 8529, // "CurrentDayPxChange": 173.93, // "CurrentNotional": 0.0, // "Rolling24HrNotional": 0.0, // "Rolling24HrVolume": 4319.63870783, // "Rolling24NumTrades": 10585, // "Rolling24HrPxChange": -0.4165607307408487, // "TimeStamp": "1534862990358" // } // const ticker = this.parseTicker(payload); const symbol = ticker['symbol']; const market = this.market(symbol); this.tickers[symbol] = ticker; const name = 'SubscribeLevel1'; const messageHash = name + ':' + market['id']; client.resolve(ticker, messageHash); } async watchTrades(symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name ndax#watchTrades * @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 ndax api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades} */ const omsId = this.safeInteger(this.options, 'omsId', 1); await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'SubscribeTrades'; const messageHash = name + ':' + market['id']; const url = this.urls['api']['ws']; const requestId = this.requestId(); const payload = { 'OMSId': omsId, 'InstrumentId': parseInt(market['id']), 'IncludeLastCount': 100, // the number of previous trades to retrieve in the immediate snapshot, 100 by default }; const request = { 'm': 0, 'i': requestId, 'n': name, 'o': this.json(payload), // JSON-formatted string containing the data being sent with the message }; const message = this.extend(request, params); const trades = await this.watch(url, messageHash, message, messageHash); if (this.newUpdates) { limit = trades.getLimit(symbol, limit); } return this.filterBySinceLimit(trades, since, limit, 'timestamp', true); } handleTrades(client, message) { const payload = this.safeValue(message, 'o', []); // // initial snapshot // // [ // [ // 6913253, // 0 TradeId // 8, // 1 ProductPairCode // 0.03340802, // 2 Quantity // 19116.08, // 3 Price // 2543425077, // 4 Order1 // 2543425482, // 5 Order2 // 1606935922416, // 6 Tradetime // 0, // 7 Direction // 1, // 8 TakerSide // 0, // 9 BlockTrade // 0, // 10 Either Order1ClientId or Order2ClientId // ] // ] // const name = 'SubscribeTrades'; const updates = {}; for (let i = 0; i < payload.length; i++) { const trade = this.parseTrade(payload[i]); const symbol = trade['symbol']; let tradesArray = this.safeValue(this.trades, symbol); if (tradesArray === undefined) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); tradesArray = new ArrayCache(limit); } tradesArray.append(trade); this.trades[symbol] = tradesArray; updates[symbol] = true; } const symbols = Object.keys(updates); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const market = this.market(symbol); const messageHash = name + ':' + market['id']; const tradesArray = this.safeValue(this.trades, symbol); client.resolve(tradesArray, messageHash); } } async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name ndax#watchOHLCV * @description watches 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 ndax api endpoint * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume */ const omsId = this.safeInteger(this.options, 'omsId', 1); await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'SubscribeTicker'; const messageHash = name + ':' + timeframe + ':' + market['id']; const url = this.urls['api']['ws']; const requestId = this.requestId(); const payload = { 'OMSId': omsId, 'InstrumentId': parseInt(market['id']), 'Interval': parseInt(this.safeString(this.timeframes, timeframe, timeframe)), 'IncludeLastCount': 100, // the number of previous candles to retrieve in the immediate snapshot, 100 by default }; const request = { 'm': 0, 'i': requestId, 'n': name, 'o': this.json(payload), // JSON-formatted string containing the data being sent with the message }; const message = this.extend(request, params); const ohlcv = await this.watch(url, messageHash, message, messageHash); if (this.newUpdates) { limit = ohlcv.getLimit(symbol, limit); } return this.filterBySinceLimit(ohlcv, since, limit, 0, true); } handleOHLCV(client, message) { // // { // m: 1, // i: 1, // n: 'SubscribeTicker', // o: [[1608284160000,23113.52,23070.88,23075.76,23075.39,162.44964300,23075.38,23075.39,8,1608284100000]], // } // const payload = this.safeValue(message, 'o', []); // // [ // [ // 1501603632000, // 0 DateTime // 2700.33, // 1 High // 2687.01, // 2 Low // 2687.01, // 3 Open // 2687.01, // 4 Close // 24.86100992, // 5 Volume // 0, // 6 Inside Bid Price // 2870.95, // 7 Inside Ask Price // 1 // 8 InstrumentId // 1608290188062.7678, // 9 candle timestamp // ] // ] // const updates = {}; for (let i = 0; i < payload.length; i++) { const ohlcv = payload[i]; const marketId = this.safeString(ohlcv, 8); const market = this.safeMarket(marketId); const symbol = market['symbol']; updates[marketId] = {}; this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {}); const keys = Object.keys(this.timeframes); for (let j = 0; j < keys.length; j++) { const timeframe = keys[j]; const interval = this.safeString(this.timeframes, timeframe, timeframe); const duration = parseInt(interval) * 1000; const timestamp = this.safeInteger(ohlcv, 0); const parsed = [ this.parseToInt((timestamp / duration) * duration), this.safeFloat(ohlcv, 3), this.safeFloat(ohlcv, 1), this.safeFloat(ohlcv, 2), this.safeFloat(ohlcv, 4), this.safeFloat(ohlcv, 5), ]; const stored = this.safeValue(this.ohlcvs[symbol], timeframe, []); const length = stored.length; if (length && (parsed[0] === stored[length - 1][0])) { const previous = stored[length - 1]; stored[length - 1] = [ parsed[0], previous[1], Math.max(parsed[1], previous[1]), Math.min(parsed[2], previous[2]), parsed[4], this.sum(parsed[5], previous[5]), ]; updates[marketId][timeframe] = true; } else { if (length && (parsed[0] < stored[length - 1][0])) { continue; } else { stored.push(parsed); const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000); if (length >= limit) { stored.shift(); } updates[marketId][timeframe] = true; } } this.ohlcvs[symbol][timeframe] = stored; } } const name = 'SubscribeTicker'; const marketIds = Object.keys(updates); for (let i = 0; i < marketIds.length; i++) { const marketId = marketIds[i]; const timeframes = Object.keys(updates[marketId]); for (let j = 0; j < timeframes.length; j++) { const timeframe = timeframes[j]; const messageHash = name + ':' + timeframe + ':' + marketId; const market = this.safeMarket(marketId); const symbol = market['symbol']; const stored = this.safeValue(this.ohlcvs[symbol], timeframe, []); client.resolve(stored, messageHash); } } } async watchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name ndax#watchOrderBook * @description watches 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 ndax api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ const omsId = this.safeInteger(this.options, 'omsId', 1); await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'SubscribeLevel2'; const messageHash = name + ':' + market['id']; const url = this.urls['api']['ws']; const requestId = this.requestId(); limit = (limit === undefined) ? 100 : limit; const payload = { 'OMSId': omsId, 'InstrumentId': parseInt(market['id']), // 'Symbol': market['info']['symbol'], // conditionally optional 'Depth': limit, // default 100 }; const request = { 'm': 0, 'i': requestId, 'n': name, 'o': this.json(payload), // JSON-formatted string containing the data being sent with the message }; const subscription = { 'id': requestId, 'messageHash': messageHash, 'name': name, 'symbol': symbol, 'marketId': market['id'], 'method': this.handleOrderBookSubscription, 'limit': limit, 'params': params, }; const message = this.extend(request, params); const orderbook = await this.watch(url, messageHash, message, messageHash, subscription); return orderbook.limit(); } handleOrderBook(client, message) { // // { // m: 3, // i: 2, // n: 'Level2UpdateEvent', // o: [[2,1,1608208308265,0,20782.49,1,25000,8,1,1]] // } // const payload = this.safeValue(message, 'o', []); // // [ // 0, // 0 MDUpdateId // 1, // 1 Number of Unique Accounts // 123, // 2 ActionDateTime in Posix format X 1000 // 0, // 3 ActionType 0 (New), 1 (Update), 2(Delete) // 0.0, // 4 LastTradePrice // 0, // 5 Number of Orders // 0.0, // 6 Price // 0, // 7 ProductPairCode // 0.0, // 8 Quantity // 0, // 9 Side // ], // const firstBidAsk = this.safeValue(payload, 0, []); const marketId = this.safeString(firstBidAsk, 7); if (marketId === undefined) { return message; } const market = this.safeMarket(marketId); const symbol = market['symbol']; const orderbook = this.safeValue(this.orderbooks, symbol); if (orderbook === undefined) { return message; } let timestamp = undefined; let nonce = undefined; for (let i = 0; i < payload.length; i++) { const bidask = payload[i]; if (timestamp === undefined) { timestamp = this.safeInteger(bidask, 2); } else { const newTimestamp = this.safeInteger(bidask, 2); timestamp = Math.max(timestamp, newTimestamp); } if (nonce === undefined) { nonce = this.safeInteger(bidask, 0); } else { const newNonce = this.safeInteger(bidask, 0); nonce = Math.max(nonce, newNonce); } // 0 new, 1 update, 2 remove const type = this.safeInteger(bidask, 3); const price = this.safeFloat(bidask, 6); const amount = this.safeFloat(bidask, 8); const side = this.safeInteger(bidask, 9); // 0 buy, 1 sell, 2 short reserved for future use, 3 unknown const orderbookSide = (side === 0) ? orderbook['bids'] : orderbook['asks']; // 0 new, 1 update, 2 remove if (type === 0) { orderbookSide.store(price, amount); } else if (type === 1) { orderbookSide.store(price, amount); } else if (type === 2) { orderbookSide.store(price, 0); } } orderbook['nonce'] = nonce; orderbook['timestamp'] = timestamp; orderbook['datetime'] = this.iso8601(timestamp); const name = 'SubscribeLevel2'; const messageHash = name + ':' + marketId; this.orderbooks[symbol] = orderbook; client.resolve(orderbook, messageHash); } handleOrderBookSubscription(client, message, subscription) { // // { // m: 1, // i: 1, // n: 'SubscribeLevel2', // o: [[1,1,1608204295901,0,20782.49,1,18200,8,1,0]] // } // const payload = this.safeValue(message, 'o', []); // // [ // [ // 0, // 0 MDUpdateId // 1, // 1 Number of Unique Accounts // 123, // 2 ActionDateTime in Posix format X 1000 // 0, // 3 ActionType 0 (New), 1 (Update), 2(Delete) // 0.0, // 4 LastTradePrice // 0, // 5 Number of Orders // 0.0, // 6 Price // 0, // 7 ProductPairCode // 0.0, // 8 Quantity // 0, // 9 Side // ], // ] // const symbol = this.safeString(subscription, 'symbol'); const snapshot = this.parseOrderBook(payload, symbol); const limit = this.safeInteger(subscription, 'limit'); const orderbook = this.orderBook(snapshot, limit); this.orderbooks[symbol] = orderbook; const messageHash = this.safeString(subscription, 'messageHash'); client.resolve(orderbook, messageHash); } handleSubscriptionStatus(client, message) { // // { // m: 1, // i: 1, // n: 'SubscribeLevel2', // o: '[[1,1,1608204295901,0,20782.49,1,18200,8,1,0]]' // } // const subscriptionsById = this.indexBy(client.subscriptions, 'id'); const id = this.safeInteger(message, 'i'); const subscription = this.safeValue(subscriptionsById, id); if (subscription !== undefined) { const method = this.safeValue(subscription, 'method'); if (method === undefined) { return message; } else { return method.call(this, client, message, subscription); } } } handleMessage(client, message) { // // { // "m": 0, // message type, 0 request, 1 reply, 2 subscribe, 3 event, unsubscribe, 5 error // "i": 0, // sequence number identifies an individual request or request-and-response pair, to your application // "n":"function name", // function name is the name of the function being called or that the server is responding to, the server echoes your call // "o":"payload", // JSON-formatted string containing the data being sent with the message // } // // { // m: 1, // i: 1, // n: 'SubscribeLevel2', // o: '[[1,1,1608204295901,0,20782.49,1,18200,8,1,0]]' // } // // { // m: 3, // i: 2, // n: 'Level2UpdateEvent', // o: '[[2,1,1608208308265,0,20782.49,1,25000,8,1,1]]' // } // const payload = this.safeString(message, 'o'); if (payload === undefined) { return message; } message['o'] = JSON.parse(payload); const methods = { 'SubscribeLevel2': this.handleSubscriptionStatus, 'SubscribeLevel1': this.handleTicker, 'Level2UpdateEvent': this.handleOrderBook, 'Level1UpdateEvent': this.handleTicker, 'SubscribeTrades': this.handleTrades, 'TradeDataUpdateEvent': this.handleTrades, 'SubscribeTicker': this.handleOHLCV, 'TickerDataUpdateEvent': this.handleOHLCV, }; const event = this.safeString(message, 'n'); const method = this.safeValue(methods, event); if (method === undefined) { return message; } else { return method.call(this, client, message); } } }