Public
Edited
Apr 24, 2022
Importers
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mutable Options_For_Selected_Date = null
Insert cell
d3
.select(March)
.selectAll('rect')
.on('mousemove touchmove', function(d, i) {
mutable hoverDate = DailyStockQuote[i];
})
Insert cell
d3
.select(March)
.selectAll('rect')
.on('click', function(d, i) {
mutable Options_For_Selected_Date = DailyOptionsQuote.find(
d => +d.DT === +hoverDate.DT
);
})
Insert cell
html`<style>


</style>`
Insert cell
Insert cell
svg.selectAll('.tick > text').attr('opacity', 0.33)
Insert cell
svg
.call(g =>
g
.append('g')
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(yScale))
)
.call(g =>
g
.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(
d3
.axisBottom(xScale)
.ticks(5)
.tickFormat(d3.timeFormat('%-m/%-d'))
)
)
Insert cell
Insert cell
Insert cell
Insert cell
mutable selectedData = data[data.length - 1]
Insert cell
Insert cell
stockQuoteData = {
const processed_data = DailyStockQuote.map((x) => {
let obj = { ...x };
obj.date = x.DT;
obj.value = x.close;
return obj;
});

return (
{ ...processed_data[0], percent_change: 0 },
[
...d3.pairs(processed_data).map((x) => {
let percent_change = (x[1].value - x[0].value) / x[0].value;
x[1].percent_change = percent_change;
return x[1];
})
]
);
}
Insert cell
Insert cell
mutable data = stock_performance_data
Insert cell
Insert cell
xScale = d3
.scaleBand()
.domain(
d3.timeDay
.range(data[0].date, +data[data.length - 1].date + 1)
.filter(d => d.getDay() !== 0 && d.getDay() !== 6)
)
.range([margin.left, chartWidth - margin.right])
.padding(0.3)
.align(1)
Insert cell
Insert cell
Insert cell
Insert cell
CalendarMonth = (dataset, feature, setCellSize = 17, color = false) => {
let margin = setCellSize / 10;
const timeWeek = d3.utcMonday;
const countDay = d => (d.getUTCDay() + 6) % 7,
formatDate = d3.utcFormat("%x"),
format = d3.format("+.2%"),
formatDay = d => d3.timeFormat('%a')(d), // " MTWTF"[d.getUTCDay()],
formatMonth = d3.utcFormat("%B");

let fontSize = d3.max([20, setCellSize / 2]);

const height = setCellSize * 6;
let width = height + setCellSize;

if (color == false) {
color = d3
.scaleSequential(d3.interpolateViridis)
.domain(d3.extent(dataset, d => +d[feature]));
}

function pathMonth(t) {
const n = 5;
const d = Math.max(0, Math.min(n, countDay(t)));
const w = timeWeek.count(d3.utcYear(t), t);
return `${
d === 0
? `M${w * setCellSize},0`
: d === n
? `M${(w + 1) * setCellSize},0`
: `M${(w + 1) * setCellSize},0V${d * setCellSize}H${w * setCellSize}`
}V${n * setCellSize}`;
}

const years = d3
.nest()
.key(d => d.date.getUTCFullYear())
.entries(dataset);

let SVG = (fontSize, height, width, setCellSize) =>
`<svg height="${height - setCellSize - fontSize}" width="${width -
setCellSize -
fontSize}" viewBox="${-setCellSize + fontSize} ${setCellSize * 0.6}
${width} ${height}" style="border:1px solid black"></svg>`;
const svgRef = html`${SVG(fontSize, height, width, setCellSize)}`;

let svg = d3.select(svgRef);

const year = svg
.selectAll("g")
.data(years)
.join("g")
.attr(
"transform",
(d, i) => `translate(40,${height * i + setCellSize * 1.5})`
);

year
.append("text")
.attr("font-weight", "bold")
.attr('font-size', fontSize * 2)
.attr('text-anchor', 'start')
.attr("x", -fontSize / 2)
.attr("dy", -2)
.text(d => d.key);

year
.append("g")
.attr("text-anchor", "end")
.selectAll("text")
.data(d3.range(2, 7).map(i => new Date(1995, 0, i)))
.join("text")
.attr("x", -2)
.attr("y", d => (countDay(d) + 0.5) * setCellSize)
.attr('font-family', 'monospace')
.attr('font-style', 'italic')
.attr("dy", -setCellSize / 2 + fontSize)
.attr('font-size', fontSize * 0.75)
.text(formatDay);

year
.append("g")
.selectAll("rect")
.data(d => d.values)
.join("rect")
.attr('stroke', 'black')
.attr("width", setCellSize - 1)
.attr("height", setCellSize - 1)
.attr("x", d => timeWeek.count(dataset[0].date, d.date) * setCellSize + 0.5)
//OLD: timeWeek.count(d3.utcYear(d.date), d.date) * setCellSize + 0.5
.attr("y", d => countDay(d.date) * setCellSize + 0.5)
.attr("fill", d => color(d[feature]))
.append("title")
.text(d => `${formatDate(d.date)}: ${format(d[feature])}`);

const month = year
.append("g")
.selectAll("g")
.data(d =>
d3.utcMonths(
d3.utcMonth(d.values[0].date),
d.values[d.values.length - 1].date
)
)
.join("g");

month
.filter((d, i) => i)
.append("path")
.attr("fill", "none")
.attr("stroke", "#fff")
.attr("stroke-width", 3)
.attr("d", pathMonth);

month
.append("text")
.attr(
"x",
d =>
timeWeek.count(dataset[0].date, dataset[dataset.length - 1].date) *
setCellSize +
setCellSize
)
//OLD: timeWeek.count(d3.utcYear(d), timeWeek.ceil(d)) * setCellSize + 2
.attr("y", -fontSize / 2)
.attr('dominant-baseline', 'middle')
.attr('text-anchor', 'end')
.attr('font-size', fontSize)
.style('font-style', 'italic')
.style('text-transform', 'uppercase')
.text(formatMonth);

return svgRef;
}
Insert cell
d3
.nest()
.key((d) => d.date.getUTCFullYear())
.entries(stock_performance_data)
Insert cell
d3_7.groups(stock_performance_data, (d) => d.date.getUTCFullYear())
Insert cell
d3_7 = require("d3@7")
Insert cell
priceFormat = d3.format('$,.2f')
Insert cell
DT_stamp = d3.timeFormat(`%a,%y-%m-%d`)
Insert cell
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