chart = {
const svg = d3.select(DOM.svg(width, height + bottomBarHeight + margin.bottom * 2));
const initialHoldings = {quantity: 100, price: 90}
svg.append("g").call(xAxis);
svg.append("g").call(xAxisBuySell);
svg.append("g").call(yAxis);
svg.append("g").call(yAxis2);
svg.append('line')
.attr('x1', margin.left)
.attr('y1', buySellY(0))
.attr('x2', width - margin.right)
.attr('y2', buySellY(0))
.attr('stroke', '#1b1e23')
.attr('stroke-opacity', 0.2)
svg.append("g")
.selectAll("rect")
.data(transactions)
.join("rect")
.attr("x", (d, i) => x(d.date))
.attr("y", d => d.value > 0 ? buySellY(d.value) : buySellY(d.value) - Math.abs(buySellY(0) - buySellY(d.value)))
.attr("height", d => Math.abs(buySellY(0) - buySellY(d.value)))
.attr("width", 10)
.attr("fill", d => d.value > 0 ? 'green' : 'red')
.on("click", d => setDatum(d))
const positionSize = 2
const [notHolding, holding] = _.partition(data, ({date}) =>
buyDatum.quantity > 0 ? date < buyDatum.date : date > buyDatum.date)
const priceChartSegments = [
{color: 'rgba(27, 30, 35, 0.6)', data: notHolding, dashed: true},
{color: 'green', data: holding, dashed: false},
]
priceChartSegments.forEach(({data, color, dashed}) =>
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", color)
.attr("stroke-width", dashed ? 1 : positionSize)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", d3.line()
.x(d => x(d.date))
.y(d => y(d.value)))
.style('stroke-dasharray', dashed ? '3,3' : null)
)
;[buyDatum].forEach(bD => {
const preColor = bD.quantity > 0 ? 'green' : 'rgba(27, 30, 35, 0.6)'
svg.append('line')
.attr('x1', margin.left)
.attr('y1', y(bD.value))
.attr('x2', x(bD.date))
.attr('y2', y(bD.value))
.attr('stroke', preColor)
.attr('stroke-width', bD.quantity > 0 ? positionSize : 1)
.style("stroke-dasharray", '3,3')
const postColor = bD.quantity > 0 ? 'rgba(27, 30, 35, 0.6)' : 'green'
svg.append('line')
.attr('x1', x(bD.date))
.attr('y1', y(bD.value))
.attr('x2', width - margin.right)
.attr('y2', y(bD.value))
.attr('stroke', postColor)
.attr('stroke-width', bD.quantity > 0 ? 1 : positionSize)
.style("stroke-dasharray", '3,3')
})
if (buyDatum.quantity < 0) {
svg.append("rect")
.attr('x', width - margin.right)
.attr('y', y(buyDatum.value) - 6)
.attr('fill', buyDatum.quantity > 0 ? 'black' : 'green')
.attr('width', `${margin.right}px`)
.attr('height', '12px')
svg.append("text")
.attr('x', width - margin.right + 6)
.attr('y', y(buyDatum.value))
.attr('font-size', '10px')
.attr('fill', 'white')
.attr("dy", ".32em")
.attr('text-anchor', 'start')
.text(format(Math.abs(buyDatum.quantity) * buyDatum.value));
}
if (buyDatum.quantity > 0) {
svg.append("rect")
.attr('x', 0)
.attr('y', y(buyDatum.value) - 6)
.attr('fill', 'green')
.attr('width', `${margin.right}px`)
.attr('height', '12px')
svg.append("text")
.attr('x', margin.right - 6)
.attr('y', y(buyDatum.value))
.attr('font-size', '10px')
.attr('fill', 'white')
.attr("dy", ".32em")
.attr('text-anchor', 'end')
.text(format(Math.abs(buyDatum.quantity) * buyDatum.value));
}
if (buyDatum.quantity > 0) {
svg.append("rect")
.attr('x', width - margin.right)
.attr('y', y(_.last(data).value) - 6)
.attr('fill', 'green')
.attr('width', `${margin.right}px`)
.attr('height', '12px')
svg.append("text")
.attr('x', width - margin.right + 6)
.attr('y', y(_.last(data).value))
.attr('font-size', '10px')
.attr('fill', 'white')
.attr("dy", ".32em")
.attr('text-anchor', 'start')
.text(format(
buyDatum.quantity * _.last(data).value
));
}
if (buyDatum.quantity < 0) {
svg.append("rect")
.attr('x', 0)
.attr('y', y(data[0].value) - 6)
.attr('fill', 'green')
.attr('width', `${margin.left}px`)
.attr('height', '12px')
svg.append("text")
.attr('x', margin.left - 6)
.attr('text-anchor', 'end')
.attr('y', y(data[0].value))
.attr('font-size', '10px')
.attr('fill', 'white')
.attr("dy", ".32em")
.text(format(
initialHoldings.quantity * initialHoldings.price
));
}
return svg.node();
}