function createFinalChart(interpolatedData) {
const netMax = d3.max(interpolatedData, d => d.net);
const changeDomainMin = -d3.max(interpolatedData, d => d.loss);
const changeDomainMax = d3.max(interpolatedData, d => d.gain);
const augmentedData = interpolatedData.map(d => ({
...d,
changeDomainMin,
changeDomainMax,
netMax
}));
const xDateEncoding = vl
.x()
.fieldT("date")
.title("Date");
const net = vl.layer(
vl
.markLine({ tooltip: true, interpolate: "step-after" })
.data(augmentedData)
.encode(
vl.x().fieldT("date"),
vl
.y()
.fieldQ("net")
.title("Net")
),
vl
.markBar({ fillOpacity: 0 })
.data(augmentedData)
.encode(
xDateEncoding,
vl.y().fieldQ("netMax"),
vl.tooltip(tooltipSpecification)
)
);
const deltas = vl.layer(
vl
.markBar({ fill: "green" })
.data(augmentedData)
.encode(xDateEncoding, vl.y().fieldQ("gain")),
vl
.markBar({ fill: "crimson" })
.data(augmentedData)
.transform({ calculate: "-datum.loss", as: "negativeLoss" })
.encode(xDateEncoding, vl.y().fieldQ("negativeLoss")),
vl
.markPoint({
stroke: "black",
fill: "white",
opacity: 1
})
.data(
augmentedData.filter(
d => d.gain !== 0 && d.loss !== 0 && d.change === 0
)
)
.encode(xDateEncoding, vl.y().fieldQ("change")),
vl
.markPoint({
stroke: "black",
fill: "green",
opacity: 1
})
.data(augmentedData.filter(d => d.change > 0))
.encode(xDateEncoding, vl.y().fieldQ("change")),
vl
.markPoint({
stroke: "black",
fill: "crimson",
opacity: 1
})
.data(augmentedData.filter(d => d.change < 0))
.encode(xDateEncoding, vl.y().fieldQ("change")),
vl
.markBar({ fillOpacity: 0 })
.data(augmentedData)
.encode(
xDateEncoding,
vl
.y()
.fieldQ("changeDomainMin")
.title("Gain, Loss, Change"),
vl.y2().fieldQ("changeDomainMax"),
vl.tooltip(tooltipSpecification)
)
);
return vl
.vconcat([net, deltas].map(d => d.width(width).height(150)))
.autosize({ type: 'fit-x', contains: 'padding' })
.render();
}