Published
Edited
Nov 8, 2019
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//the left chart only shows calls for a single series.
//the right chart shows all series.
//the difference is only there to show the variety
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
ChartingAllPuts = {
let puts = OptionChain.map(x => [...x.puts]).reduce(function(arr, value) {
return (arr = [...value, ...arr]);
}, []);
let options = puts.map(x => x[PROPERTY]);

let strikes = puts.map(x => x.strike);

if (options.length !== strikes.length)
throw 'diff num of options and strikes';

let x = d3
.scaleLinear()
.domain(d3.extent(strikes))
.range([
width / 2 + DIM.CHART_LEFT_PADDING,
width / 2 + DIM.CHART_LEFT_PADDING + CHART_WIDTH
]);

let y = d3
.scaleLinear()
.domain(d3.extent(options))
.nice()
.range([
height - DIM.BOTTOM_MARGIN - DIM.CHART_BOTTOM_PADDING,
DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING
])
.clamp(true)
.unknown(height - DIM.BOTTOM_MARGIN - box[1]);
let xAxis = g =>
g
.attr(
"transform",
`translate(${0},
${DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING})`
)
.call(
d3
.axisBottom(x)
.tickSize(CHART_HEIGHT)
.tickPadding(5)
.tickValues(strikes)
.tickFormat(function(d, i) {
return strikes.includes(d) ? d3.format('3,.4')(d) : "";
})
);
let yAxis = g =>
g
.attr(
"transform",
`translate(${width / 2 + DIM.CHART_LEFT_PADDING},
${0})`
)
.call(d3.axisLeft(y).tickSize(-CHART_WIDTH))
.call(g => g.select(".domain").remove())
.call(g =>
g
.select(".tick:last-of-type text")
.clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(d => "y-axis units")
);

d3.select(Puts)
.selectAll('.xAxis')
.data(['_'], d => d)
.join('g')
.classed('xAxis', true)
.call(xAxis);
d3.select(Puts)
.selectAll('.yAxis')
.data(['_'], d => d)
.join('g')
.classed('yAxis', true)
.call(yAxis);

d3.select(Puts)
.selectAll('.put-box')
.data(strikes, (d, i) => i)
.join('rect')
.attr('class', 'put-box')
.attr('x', d => x(d) - box[0] / 2)
.attr('width', box[0])
.attr('y', (d, i) => {
let value = puts[i][PROPERTY] ? puts[i][PROPERTY] : 'null';
return y(value) - box[1] / 2;
})
.attr('height', box[1])
.attr('stroke', 'white');
}
Insert cell
ChartingPuts = {
let puts = OptionChain[0].puts;

let options = puts.map(x => x[PROPERTY]);

let strikes = puts.map(x => x.strike);

if (options.length !== strikes.length)
throw 'diff num of options and strikes';

let x = d3
.scaleLinear()
.domain(d3.extent(strikes))
.range([
width / 2 + DIM.CHART_LEFT_PADDING,
width / 2 + DIM.CHART_LEFT_PADDING + CHART_WIDTH
]);

let y = d3
.scaleLinear()
.domain(d3.extent(options))
.nice()
.range([
height - DIM.BOTTOM_MARGIN - DIM.CHART_BOTTOM_PADDING,
DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING
])
.clamp(true)
.unknown(height - DIM.BOTTOM_MARGIN - box[1]);
let xAxis = g =>
g
.attr(
"transform",
`translate(${0},
${DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING})`
)
.call(
d3
.axisBottom(x)
.tickSize(CHART_HEIGHT)
.tickPadding(5)
.tickValues(strikes)
.tickFormat(function(d, i) {
return strikes.includes(d) ? d3.format('3,.4')(d) : "";
})
);
let yAxis = g =>
g
.attr(
"transform",
`translate(${width / 2 + DIM.CHART_LEFT_PADDING},
${0})`
)
.call(d3.axisLeft(y).tickSize(-CHART_WIDTH))
.call(g => g.select(".domain").remove())
.call(g =>
g
.select(".tick:last-of-type text")
.clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(d => "y-axis units")
);

d3.select(Puts)
.selectAll('.xAxis')
.data(['_'], d => d)
.join('g')
.classed('xAxis', true)
.call(xAxis);
d3.select(Puts)
.selectAll('.yAxis')
.data(['_'], d => d)
.join('g')
.classed('yAxis', true)
.call(yAxis);

d3.select(Puts)
.selectAll('.put-box')
.data(strikes, (d, i) => i)
.join('rect')
.attr('class', 'put-box')
.attr('x', d => x(d) - box[0] / 2)
.attr('width', box[0])
.attr('y', (d, i) => {
let value = puts[i][PROPERTY] ? puts[i][PROPERTY] : 'null';
return y(value) - box[1] / 2;
})
.attr('height', box[1])
.attr('stroke', 'white');
}
Insert cell
ChartingCalls = {
let calls = OptionChain[0].calls;

let options = calls.map(x => x[PROPERTY]);

let strikes = calls.map(x => x.strike);

let x = d3
.scaleLinear()
.domain(d3.extent(strikes))
.range([DIM.CHART_LEFT_PADDING, DIM.CHART_LEFT_PADDING + CHART_WIDTH]);

let y = d3
.scaleLinear()
.domain(d3.extent(options))
.nice()
.range([
height - DIM.BOTTOM_MARGIN - DIM.CHART_BOTTOM_PADDING,
DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING
])
.unknown(height - DIM.BOTTOM_MARGIN - box[1]);

let xAxis = g =>
g
.attr(
"transform",
`translate(${0},
${DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING})`
)
.call(
d3
.axisBottom(x)
.tickSize(CHART_HEIGHT)
.tickPadding(5)
.tickValues(strikes)
.tickFormat(function(d, i) {
return strikes.includes(d) ? d3.format('3,.4')(d) : "";
})
);
let yAxis = g =>
g
.attr(
"transform",
`translate(${DIM.CHART_LEFT_PADDING},
${0})`
)
.call(d3.axisLeft(y).tickSize(-CHART_WIDTH))
.call(g => g.select(".domain").remove())
.call(g =>
g
.select(".tick:last-of-type text")
.clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(d => "y-axis units")
);

d3.select(Scene)
.select('.calls')
.selectAll('.xAxis')
.data(['_'], d => d)
.join('g')
.classed('xAxis', true)
.call(xAxis);
d3.select(Calls)
.selectAll('.yAxis')
.data(['_'], d => d)
.join('g')
.classed('yAxis', true)
.call(yAxis);
d3.select(Calls)
.selectAll('.call-box')
.data(strikes, (d, i) => i)
.join('rect')
.attr('class', 'call-box')
.attr('x', d => x(d) - box[0] / 2)
.attr('height', box[1])

.attr('y', (d, i) => y(options[i]) - box[1] / 2)
.attr('width', box[0])
.attr('stroke', 'white');
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
box = [4, 6]
Insert cell
Insert cell
Background = svg`<g><rect class="bg" x=0 y=0 width=${width} height=${height} fill=#0A0A0A></rect><g/>`
Insert cell
Heading = svg`<g class="heading"><rect class="heading-bg" x=0 y=0 height=${DIM.TOP_MARGIN} width=${width} fill="#4B4B4B"></rect>`
Insert cell
Legend = svg`
<g class="legend">
<rect class="legend-bg"
x=0
y=${height - DIM.BOTTOM_MARGIN}
height=${DIM.BOTTOM_MARGIN}
width=${width}
fill="#1B1B1B"></rect>
</g>`
Insert cell
Calls = svg`
<g class="calls">
<rect class="calls-bg"
x=${DIM.CHART_LEFT_PADDING}
y=${DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING}
height=${height -
DIM.BOTTOM_MARGIN -
DIM.TOP_MARGIN -
DIM.CHART_TOP_PADDING -
DIM.CHART_BOTTOM_PADDING}
width=${width / 2 - DIM.CHART_LEFT_PADDING - DIM.CHART_RIGHT_PADDING}
fill="#1B1B1B">
</rect>
</g>`
Insert cell
Puts = svg`<g class="puts">
<rect
class="puts-bg"
x=${width / 2 + DIM.CHART_LEFT_PADDING}
y=${DIM.TOP_MARGIN + DIM.CHART_TOP_PADDING}
height=${height -
DIM.BOTTOM_MARGIN -
DIM.TOP_MARGIN -
DIM.CHART_TOP_PADDING -
DIM.CHART_BOTTOM_PADDING}
width=${width / 2 - DIM.CHART_LEFT_PADDING - DIM.CHART_RIGHT_PADDING}
fill="#1B1B1B"></rect>
</g>`
Insert cell
Insert cell
// {
// let container = this || html`<div class="container"/>`;
// yield container;
// let series = d3
// .select(container)
// .attr('id', '#container')
// .selectAll('.option-series')
// .data(OptionChain, d => d3.timeParse('%s')(d.expirationDate))
// .join('div')
// .style('background', 'red')
// .html(d => {
// return `<span class="label">${d3.timeFormat('%Y-%m-%d')(
// d3.timeParse('%s')(d.expirationDate)
// )}</span>`;
// })
// .attr('class', 'option-series');
// }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more