Last active
June 21, 2018 08:04
-
-
Save jonchurch/9ba520c959c525bbf20320932f108eb0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// api/stream.js | |
import historyProvider from './historyProvider.js' | |
// we use Socket.io client to connect to cryptocompare's socket.io stream | |
var io = require('socket.io-client') | |
var socket_url = 'wss://streamer.cryptocompare.com' | |
var socket = io(socket_url) | |
// keep track of subscriptions | |
var _subs = [] | |
export default { | |
subscribeBars: function(symbolInfo, resolution, updateCb, uid, resetCache) { | |
const channelString = createChannelString(symbolInfo) | |
socket.emit('SubAdd', {subs: [channelString]}) | |
var newSub = { | |
channelString, | |
uid, | |
resolution, | |
symbolInfo, | |
lastBar: historyProvider.history[symbolInfo.name].lastBar, | |
listener: updateCb, | |
} | |
_subs.push(newSub) | |
}, | |
unsubscribeBars: function(uid) { | |
var subIndex = _subs.findIndex(e => e.uid === uid) | |
if (subIndex === -1) { | |
//console.log("No subscription found for ",uid) | |
return | |
} | |
var sub = _subs[subIndex] | |
socket.emit('SubRemove', {subs: [sub.channelString]}) | |
_subs.splice(subIndex, 1) | |
} | |
} | |
socket.on('connect', () => { | |
console.log('===Socket connected') | |
}) | |
socket.on('disconnect', (e) => { | |
console.log('===Socket disconnected:', e) | |
}) | |
socket.on('error', err => { | |
console.log('====socket error', err) | |
}) | |
socket.on('m', (e) => { | |
// here we get all events the CryptoCompare connection has subscribed to | |
// we need to send this new data to our subscribed charts | |
const _data= e.split('~') | |
if (_data[0] === "3") { | |
// console.log('Websocket Snapshot load event complete') | |
return | |
} | |
const data = { | |
sub_type: parseInt(_data[0],10), | |
exchange: _data[1], | |
to_sym: _data[2], | |
from_sym: _data[3], | |
trade_id: _data[5], | |
ts: parseInt(_data[6],10), | |
volume: parseFloat(_data[7]), | |
price: parseFloat(_data[8]) | |
} | |
const channelString = `${data.sub_type}~${data.exchange}~${data.to_sym}~${data.from_sym}` | |
const sub = _subs.find(e => e.channelString === channelString) | |
if (sub) { | |
// disregard the initial catchup snapshot of trades for already closed candles | |
if (data.ts < sub.lastBar.time / 1000) { | |
return | |
} | |
var _lastBar = updateBar(data, sub) | |
// send the most recent bar back to TV's realtimeUpdate callback | |
sub.listener(_lastBar) | |
// update our own record of lastBar | |
sub.lastBar = _lastBar | |
} | |
}) | |
// Take a single trade, and subscription record, return updated bar | |
function updateBar(data, sub) { | |
var lastBar = sub.lastBar | |
let resolution = sub.resolution | |
if (resolution.includes('D')) { | |
// 1 day in minutes === 1440 | |
resolution = 1440 | |
} else if (resolution.includes('W')) { | |
// 1 week in minutes === 10080 | |
resolution = 10080 | |
} | |
var coeff = resolution * 60 | |
// console.log({coeff}) | |
var rounded = Math.floor(data.ts / coeff) * coeff | |
var lastBarSec = lastBar.time / 1000 | |
var _lastBar | |
if (rounded > lastBarSec) { | |
// create a new candle, use last close as open **PERSONAL CHOICE** | |
_lastBar = { | |
time: rounded * 1000, | |
open: lastBar.close, | |
high: lastBar.close, | |
low: lastBar.close, | |
close: data.price, | |
volume: data.volume | |
} | |
} else { | |
// update lastBar candle! | |
if (data.price < lastBar.low) { | |
lastBar.low = data.price | |
} else if (data.price > lastBar.high) { | |
lastBar.high = data.price | |
} | |
lastBar.volume += data.volume | |
lastBar.close = data.price | |
_lastBar = lastBar | |
} | |
return _lastBar | |
} | |
// takes symbolInfo object as input and creates the subscription string to send to CryptoCompare | |
function createChannelString(symbolInfo) { | |
var channel = symbolInfo.name.split(/[:/]/) | |
const exchange = channel[0] === 'GDAX' ? 'Coinbase' : channel[0] | |
const to = channel[2] | |
const from = channel[1] | |
// subscribe to the CryptoCompare trade channel for the pair and exchange | |
return `0~${exchange}~${from}~${to}` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment