Skip to content

Commit

Permalink
Merge pull request #16159 from sc0Vu/add-binance-watch-tickers
Browse files Browse the repository at this point in the history
binance: add watchTickers
  • Loading branch information
kroitor committed Jan 4, 2023
2 parents 8b98963 + 18edf5d commit 4e75dc7
Showing 1 changed file with 166 additions and 11 deletions.
177 changes: 166 additions & 11 deletions js/pro/binance.js
Expand Up @@ -4,7 +4,7 @@

const binanceRest = require ('../binance.js');
const Precise = require ('../base/Precise');
const { ExchangeError } = require ('../base/errors');
const { ExchangeError, ArgumentsRequired } = require ('../base/errors');
const { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById } = require ('./base/Cache');

// -----------------------------------------------------------------------------
Expand All @@ -20,7 +20,7 @@ module.exports = class binance extends binanceRest {
'watchOrderBook': true,
'watchOrders': true,
'watchTicker': true,
'watchTickers': false, // for now
'watchTickers': true,
'watchTrades': true,
},
'urls': {
Expand Down Expand Up @@ -64,6 +64,9 @@ module.exports = class binance extends binanceRest {
'watchTicker': {
'name': 'ticker', // ticker = 1000ms L1+OHLCV, bookTicker = real-time L1
},
'watchTickers': {
'name': 'ticker', // ticker or miniTicker or bookTicker
},
'watchBalance': {
'fetchBalanceSnapshot': false, // or true
'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
Expand Down Expand Up @@ -745,12 +748,76 @@ module.exports = class binance extends binanceRest {
return await this.watch (url, messageHash, this.extend (request, params), messageHash, subscribe);
}

handleTicker (client, message) {
//
// 24hr rolling window ticker statistics for a single symbol
// These are NOT the statistics of the UTC day, but a 24hr rolling window for the previous 24hrs
// Update Speed 1000ms
async watchTickers (symbols = undefined, params = {}) {
/**
* @method
* @name binance#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
* @param {Array} symbols unified symbol of the market to fetch the ticker for
* @param {object} params extra parameters specific to the binance api endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
*/
await this.loadMarkets ();
symbols = this.marketSymbols (symbols);
const marketIds = this.marketIds (symbols);
let market = undefined;
if (marketIds !== undefined) {
market = this.safeMarket (marketIds[0]);
}
let type = undefined;
[ type, params ] = this.handleMarketTypeAndParams ('watchTickers', market, params);
const options = this.safeValue (this.options, 'watchTickers', {});
let name = this.safeString (options, 'name', 'ticker');
name = this.safeString (params, 'name', name);
const oriParams = params;
params = this.omit (params, 'name');
let wsParams = [];
const messageHash = '!' + name + '@arr';
if (name === 'bookTicker') {
if (marketIds === undefined) {
throw new ArgumentsRequired (this.id + ' watchTickers() requires symbols for bookTicker');
}
// simulate watchTickers with subscribe multiple individual bookTicker topic
for (let i = 0; i < marketIds.length; i++) {
wsParams.push (marketIds[i].toLowerCase () + '@bookTicker');
}
} else {
wsParams = [
messageHash,
];
}
const url = this.urls['api']['ws'][type] + '/' + this.stream (type, messageHash);
const requestId = this.requestId (url);
const request = {
'method': 'SUBSCRIBE',
'params': wsParams,
'id': requestId,
};
const subscribe = {
'id': requestId,
};
const tickers = await this.watch (url, messageHash, this.extend (request, params), messageHash, subscribe);
const result = {};
for (let i = 0; i < tickers.length; i++) {
const ticker = tickers[i];
const tickerSymbol = ticker['symbol'];
if (symbols !== undefined && this.inArray (tickerSymbol, symbols)) {
result[tickerSymbol] = ticker;
}
}
const resultKeys = Object.keys (result);
if (resultKeys.length > 0) {
if (this.newUpdates) {
return result;
}
return this.filterByArray (this.tickers, 'symbol', symbols);
}
return await this.watchTickers (symbols, oriParams);
}

parseWsTicker (message) {
//
// ticker
// {
// e: '24hrTicker', // event type
// E: 1579485598569, // event time
Expand All @@ -777,12 +844,23 @@ module.exports = class binance extends binanceRest {
// n: 163222, // total number of trades
// }
//
// miniTicker
// {
// e: '24hrMiniTicker',
// E: 1671617114585,
// s: 'MOBBUSD',
// c: '0.95900000',
// o: '0.91200000',
// h: '1.04000000',
// l: '0.89400000',
// v: '2109995.32000000',
// q: '2019254.05788000'
// }
//
let event = this.safeString (message, 'e', 'bookTicker');
if (event === '24hrTicker') {
event = 'ticker';
}
const wsMarketId = this.safeStringLower (message, 's');
const messageHash = wsMarketId + '@' + event;
let timestamp = undefined;
const now = this.milliseconds ();
if (event === 'bookTicker') {
Expand All @@ -795,7 +873,7 @@ module.exports = class binance extends binanceRest {
const marketId = this.safeString (message, 's');
const symbol = this.safeSymbol (marketId);
const last = this.safeFloat (message, 'c');
const result = {
const ticker = {
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
Expand All @@ -817,8 +895,78 @@ module.exports = class binance extends binanceRest {
'quoteVolume': this.safeFloat (message, 'q'),
'info': message,
};
return ticker;
}

handleTicker (client, message) {
//
// 24hr rolling window ticker statistics for a single symbol
// These are NOT the statistics of the UTC day, but a 24hr rolling window for the previous 24hrs
// Update Speed 1000ms
//
// {
// e: '24hrTicker', // event type
// E: 1579485598569, // event time
// s: 'ETHBTC', // symbol
// p: '-0.00004000', // price change
// P: '-0.209', // price change percent
// w: '0.01920495', // weighted average price
// x: '0.01916500', // the price of the first trade before the 24hr rolling window
// c: '0.01912500', // last (closing) price
// Q: '0.10400000', // last quantity
// b: '0.01912200', // best bid
// B: '4.10400000', // best bid quantity
// a: '0.01912500', // best ask
// A: '0.00100000', // best ask quantity
// o: '0.01916500', // open price
// h: '0.01956500', // high price
// l: '0.01887700', // low price
// v: '173518.11900000', // base volume
// q: '3332.40703994', // quote volume
// O: 1579399197842, // open time
// C: 1579485597842, // close time
// F: 158251292, // first trade id
// L: 158414513, // last trade id
// n: 163222, // total number of trades
// }
//
let event = this.safeString (message, 'e', 'bookTicker');
if (event === '24hrTicker') {
event = 'ticker';
} else if (event === '24hrMiniTicker') {
event = 'miniTicker';
}
const wsMarketId = this.safeStringLower (message, 's');
const messageHash = wsMarketId + '@' + event;
const result = this.parseWsTicker (message);
const symbol = result['symbol'];
this.tickers[symbol] = result;
client.resolve (result, messageHash);
if (event === 'bookTicker') {
// watch bookTickers
client.resolve ([ result ], '!' + 'bookTicker@arr');
}
}

handleTickers (client, message) {
let event = undefined;
for (let i = 0; i < message.length; i++) {
const ticker = message[i];
event = this.safeString (ticker, 'e');
if (event === '24hrTicker') {
event = 'ticker';
} else if (event === '24hrMiniTicker') {
event = 'miniTicker';
}
const wsMarketId = this.safeStringLower (ticker, 's');
const messageHash = wsMarketId + '@' + event;
const result = this.parseWsTicker (ticker);
const symbol = result['symbol'];
this.tickers[symbol] = result;
client.resolve (result, messageHash);
}
const values = Object.values (this.tickers);
client.resolve (values, '!' + event + '@arr');
}

async authenticate (params = {}) {
Expand Down Expand Up @@ -1478,15 +1626,22 @@ module.exports = class binance extends binanceRest {
'trade': this.handleTrade,
'aggTrade': this.handleTrade,
'kline': this.handleOHLCV,
'24hrTicker@arr': this.handleTickers,
'24hrMiniTicker@arr': this.handleTickers,
'24hrTicker': this.handleTicker,
'24hrMiniTicker': this.handleTicker,
'bookTicker': this.handleTicker,
'outboundAccountPosition': this.handleBalance,
'balanceUpdate': this.handleBalance,
'ACCOUNT_UPDATE': this.handleBalance,
'executionReport': this.handleOrderUpdate,
'ORDER_TRADE_UPDATE': this.handleOrderUpdate,
};
const event = this.safeString (message, 'e');
let event = this.safeString (message, 'e');
if (Array.isArray (message)) {
const data = message[0];
event = this.safeString (data, 'e') + '@arr';
}
const method = this.safeValue (methods, event);
if (method === undefined) {
const requestId = this.safeString (message, 'id');
Expand Down

0 comments on commit 4e75dc7

Please sign in to comment.