A quick example of how to render a Market Profile chart using D3 and d3fc
Built with blockbuilder.org
xxxxxxxxxx
<script src="https://unpkg.com/d3@4.6.0"></script>
<script src="https://unpkg.com/d3fc@12.1.0"></script>
<style>
g.multi {
opacity: 0.8;
}
g.multi:hover {
opacity: 1.0;
}
g.bar text {
text-anchor: end;
alignment-baseline: middle;
fill: black;
}
.x-axis {
display: none;
}
</style>
<div id='chart' style='height: 400px'></div>
<script>
// create some random financial data
const generator = fc.randomFinancial();
const timeSeries = generator(20);
// determine the price range
const extent = fc.extentLinear()
.accessors([d => d.high, d => d.low]);
const priceRange = extent(timeSeries);
// use a d3 scale to create a set of price buckets
const priceScale = d3.scaleLinear()
.domain(priceRange);
const priceBuckets = priceScale.ticks().map(s => s.toString());
const inRange = (datum, price) => price > datum.low && price < datum.high ? 1 : 0;
// map each point in our time series, to construct the market profile
const marketProfile = timeSeries.map(
(datum, index) => priceBuckets.map(priceBucket => {
// determine how many points to the left are also within this time bucket
const base = d3.sum(timeSeries.slice(0, index).map(d => inRange(d, priceBucket)));
// add this datapoint
const arr = [
base,
base + inRange(datum, priceBucket)
];
arr.price = priceBucket;
return arr;
})
);
const color = d3.scaleOrdinal(d3.schemeCategory20);
// render using a bar series, and a multi-series
const barSeries = fc.seriesSvgBar()
.orient('horizontal')
.barWidth(fc.seriesFractionalBarWidth(1.0))
.crossValue(d => d.price)
.mainValue(d => d[1])
.baseValue(d => d[0]);
const multi = fc.seriesSvgMulti()
.mapping((data, index) => data[index])
.series(marketProfile.map(() => barSeries))
.decorate((selection) => {
// decorate in order to colour / letter series based
// on their multi-series index
selection.enter()
.each(function(data, index) {
d3.select(this)
.selectAll('g.bar')
.attr('fill', color(index))
.append('text')
.attr('transform', 'translate(-10, 0)')
.text(d => d[0] !== d[1] ? String.fromCharCode(65 + index) : '')
});
});
const xExtent = fc.extentLinear()
.accessors([a => a.map(d => d[1])])
.pad([0, 1])
.padUnit('domain');
const chart = fc.chartSvgCartesian(
d3.scaleLinear(),
d3.scalePoint())
.xDomain(xExtent(marketProfile))
.yDomain(priceBuckets)
.yOrient('left')
.yPadding(0.7)
.plotArea(multi);
d3.select('#chart')
.datum(marketProfile)
.call(chart);
</script>
https://unpkg.com/d3@4.6.0
https://unpkg.com/d3fc@12.1.0