diff --git a/exchanges/binance.exchange.ts b/exchanges/binance.exchange.ts new file mode 100644 index 0000000..4fbbf3d --- /dev/null +++ b/exchanges/binance.exchange.ts @@ -0,0 +1,132 @@ +import { Ticker } from './../ticker'; +import { CurrencyPair } from './../currencypair'; +import { Exchange } from './../exchange'; +var request = require('request'); + +export class Binance extends Exchange { + exch_code = 'BINA'; + exch_name = 'Binance'; + + private symbolsUrl = 'https://api.binance.com/api/v1/ticker/24hr'; + private tickerUrl = 'https://api.binance.com/api/v1/ticker/allPrices'; + private pairsByName = {}; + private pairsInQueue : Array; + + GetUrl(primary: string, base: string):string { + return `https://www.binance.com/trade.html?symbol=${primary}_${base}`; + } + + GetNextInQueue(finalCallback) { + if(this.pairsInQueue.length > 0) + { + let x = this.pairsInQueue.shift(); + let symbol: string = x.symbol; + let curr1 = symbol.substring(0, symbol.length-3); + let curr2 = symbol.substring(symbol.length-3); + if(symbol.indexOf('USDT')>0) { + curr1 = symbol.substring(0, symbol.length-4); + curr2 = symbol.substring(symbol.length-4); + } + let cp = new CurrencyPair(curr1, curr2, this); + cp.base_volume = x.quoteVolume; + cp.primary_volume = x.volume; + cp.GetHistory(() => { + this.currencyPairs.push(cp); + this.pairsByName[x.symbol] = cp; + this.GetNextInQueue(finalCallback); + }); + } else { + finalCallback(this.currencyPairs); + } + } + + GetCurrencyPairs(callback : (pairs: Array)=>void) { + request(this.symbolsUrl, (err, res, body) => { + if (!err && res.statusCode == 200) { + this.pairsInQueue = JSON.parse(body); + this.GetNextInQueue(callback); + } else { + console.log('Error'); + console.log(err); + } + }); + } + + TickerTimer(time_ms: number) { + setTimeout(()=> { + this.GetTicker(() => { + this.TickerTimer(time_ms); + }); + }, time_ms); + } + + GetTicker(callback) { + request(this.tickerUrl, (err, res, body) => { + if (!err && res.statusCode == 200) { + let tickers = JSON.parse(body); + tickers.forEach(element => { + let cp : CurrencyPair = this.pairsByName[element.symbol]; + if(cp) { + let ticker = new Ticker(); + ticker.last_price = element.price; + ticker.tick_time = Math.floor(+new Date()/1000); + ticker.base_volume_24 = cp.base_volume; + ticker.primary_volume_24 = cp.primary_volume; + cp.NewTick(ticker); + } + }); + callback(); + } else { + if(err) + { + console.log('Binance ticker error:'); + console.log(err); + } else { + console.log('Binance result code: ' + res.resultCode); + } + callback(); + } + }); + + } + + GetLastOrders(currency1:string, currency2:string, timestamp: number, callback) { + request(`https://www.binance.com/api/v1/trades?symbol=${currency1.toUpperCase()}${currency2.toUpperCase()}`, (err, res, body) => { + if (!err && res.statusCode == 200) { + + let result = JSON.parse(body).reverse(); + let lastTimeStamp = result[0].time; + let sameTimeOrders = 0; + let tempNoOrders = 0; + let tempTimeStamp = lastTimeStamp; + result.forEach(element => { + if(element.time == tempTimeStamp) + tempNoOrders++; + else + { + sameTimeOrders = Math.max(sameTimeOrders, tempNoOrders); + if(lastTimeStamp - element.time < 3000) + { + tempTimeStamp = element.time; + tempNoOrders = 1; + } else + { + tempNoOrders = 0; + } + } + }); + callback(sameTimeOrders); + } else { + if(err) + { + console.log('Bittrex last prices error:'); + console.log(err); + } else { + console.log('Bittrex last prices result code: ' + res.resultCode); + } + callback(0); + } + }); + } + +} \ No newline at end of file diff --git a/index.ts b/index.ts index 68f29b5..3384682 100644 --- a/index.ts +++ b/index.ts @@ -1,4 +1,5 @@ import { Slack } from './slack'; +import { Binance } from './exchanges/binance.exchange'; import { Poloniex } from './exchanges/poloniex.exchange'; import { Bittrex } from './exchanges/bittrex.exchange'; import { HitBtc } from './exchanges/hitbtc.exchange'; @@ -12,6 +13,7 @@ var fs = require('fs'); var hitbtc = new HitBtc(); var bittrex = new Bittrex(); var poloniex = new Poloniex(); +var binance = new Binance(); var slackkey = ""; // Check if a file exists @@ -96,7 +98,12 @@ if(slackkey && slackkey.length > 0) // Get all currenct pairs on Poloniex and download history poloniex.GetCurrencyPairs(() => { console.log("Poloniex history downloaded"); - }); + // Start subscribing to Binance ticker + binance.TickerTimer(1000); + binance.GetCurrencyPairs(() => { + console.log("Binance history downloaded"); + }); + }); }); //}); @@ -189,6 +196,13 @@ cli.command('rescan').description('Rescan all charts.').action((a, cb) => { x.lastBaseCandle = null; }); + binance.currencyPairs.forEach(x => { + x.lastLowerTime = 0; + x.lastDropState = false; + x.lastCurrentLow = 0; + x.lastBaseCandle = null; + }); + cb(); }); @@ -213,6 +227,11 @@ cli.command('pairdata').description('Show data for all pairs.').action((a, cb) = console.log(`${x.base_curr}/${x.primary_curr} LastLowerTime: ${x.lastLowerTime}, LastDropState: ${x.lastDropState}, LastCurrentLow: ${x.lastCurrentLow}, LastBaseCandle: ${x.lastBaseCandle?JSON.stringify(x.lastBaseCandle):"null"}`); }); + console.log('\n\nBinance\n\n'); + binance.currencyPairs.forEach(x => { + console.log(`${x.base_curr}/${x.primary_curr} LastLowerTime: ${x.lastLowerTime}, LastDropState: ${x.lastDropState}, LastCurrentLow: ${x.lastCurrentLow}, LastBaseCandle: ${x.lastBaseCandle?JSON.stringify(x.lastBaseCandle):"null"}`); + }); + cb(); }); @@ -226,6 +245,9 @@ cli.command('ignore ').description("Don't alert for cu case 'btrx': exchange = bittrex; break; + case 'bina': + exchange = binance; + break; } if(exchange) { let pairs = exchange.currencyPairs.filter(x => (x.base_curr.toLowerCase() == a.curr1.toLowerCase() && x.primary_curr.toLowerCase() == a.curr2.toLowerCase()) || (x.base_curr.toLowerCase() == a.curr2.toLowerCase() && x.primary_curr.toLowerCase() == a.curr1.toLowerCase())); @@ -250,6 +272,9 @@ cli.command('unignore ').description("Stop ignoring cu case 'btrx': exchange = bittrex; break; + case 'bina': + exchange = binance; + break; } if(exchange) { let pairs = exchange.currencyPairs.filter(x => (x.base_curr.toLowerCase() == a.curr1.toLowerCase() && x.primary_curr.toLowerCase() == a.curr2.toLowerCase()) || (x.base_curr.toLowerCase() == a.curr2.toLowerCase() && x.primary_curr.toLowerCase() == a.curr1.toLowerCase())); @@ -272,6 +297,7 @@ cli.command('stats').description('Print statistics.').action((a, cb) => { console.log('Bittrex: ' + bittrex.currencyPairs.length); console.log('HitBTC: ' + hitbtc.currencyPairs.length); console.log('Poloniex: ' + poloniex.currencyPairs.length); + console.log('Binance: ' + binance.currencyPairs.length); let btrx1h = 0; let btrx1m = 0; bittrex.currencyPairs.forEach(x => { @@ -293,15 +319,24 @@ cli.command('stats').description('Print statistics.').action((a, cb) => { plnx1m += x.candles_1m.length; }); + let bina1h = 0; + let bina1m = 0; + binance.currencyPairs.forEach(x => { + bina1h += x.candles_1h.length; + bina1m += x.candles_1m.length; + }); + console.log('\nNumber of 1h candles: '); console.log('Bittrex: ' + btrx1h); console.log('HitBTC: ' + hitb1h); console.log('Poloniex: ' + plnx1h); + console.log('Binance: ' + bina1h); console.log('\nNumber of 1m candles: '); console.log('Bittrex: ' + btrx1m); console.log('HitBTC: ' + hitb1m); console.log('Poloniex: ' + plnx1m); + console.log('Binance: ' + bina1m); cb(); });