@melonproject/orderbook-visualisation
Version:
Simple order book (or depth of market) visualisation with d3
80 lines (66 loc) • 2.5 kB
JavaScript
const draw = (unsortedData, target, d3 = window.d3) => {
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = target.node().clientWidth - margin.left - margin.right;
const height = target.node().clientHeight - margin.top - margin.bottom;
const x = d3.scaleLinear().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
const g = target.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const data = unsortedData.sort((a, b) => (a.price > b.price ? 1 : -1));
x.domain([
d3.min(data, d => d.price),
d3.max(data, d => d.price) + 1,
]);
y.domain([0, d3.max(data, d => d.total)]);
g.append('g')
.attr('class', 'axis axis--x')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom(x));
g.append('g')
.attr('class', 'axis axis--y')
.call(d3.axisLeft(y));
// Define the div for the tooltip
const tooltip = d3.select('body').append('div')
.attr('class', 'orderbook-visualisation-tooltip')
.style('position', 'absolute')
.style('top', `${target.node().parentNode.offsetTop}px`)
.style('left', `${(target.node().parentNode.offsetLeft + margin.left + (width / 2)) - 100}px`)
.style('width', '200px')
.style('opacity', 0)
.html('');
g.selectAll('.bar')
.data(data)
.enter().append('rect')
.attr('class', d => `bar ${d.type}`)
.attr('x', d => x(d.price))
.attr('y', d => y(d.total))
.attr('width', (d, i) => {
// is there a next element and do they have the same type:
// fill until the next order
if (data[i + 1] && data[i + 1].type === d.type) {
return x(data[i + 1].price) - x(d.price);
// is there a next element and they don't have the same type:
// market price valley
} else if (data[i + 1]) {
return (x.range()[1] - x.range()[0]) / data.length;
}
// this is the last element: fill until the end of the graph
return x.range()[1] - x(d.price);
})
.attr('height', d => height - y(d.total))
.on('mouseover', (d) => {
tooltip.transition()
.duration(500)
.style('opacity', 1);
let html = '<table>';
Object.keys(d).forEach((key) => {
html += `<tr><td><b>${key}</b></td><td>${d[key]}</td></tr>`;
});
html += '</table>';
tooltip.html(html);
})
.on('mouseout', () =>
tooltip.transition().duration(500).style('opacity', 0),
);
};
module.exports = draw;