Public
Edited
Jan 11, 2022
1 fork
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Note that month to month returns are more or less completely random at this stage. You should notice that almost all strategies have a very wide H-spread with very subtle differences - particularly in the median return value (which tends to between 1-2% for almost any given strategy).

In the next section we'll see how the differences in monthly returns will change as we start to look at the "sequence of returns" as we compound (multiply) multiple consecutive months together. In other words, the order of the monthly returns above matters far more to the success of a strategy over time than any single month return matters! (This should be obvious.)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
${Plot.plot({
y: {grid: true, label: "↑ Frequency"},
x: {grid: true, label: `${sequence_length}-mo Returns`},
width: width,
facet: {
data: selectedStrategyAggregateData,
y: "strategy",
marginRight: 150,
},
marks: [
Plot.frame(),
Plot.ruleX([0]),
Plot.barY(selectedStrategyAggregateData, Plot.binX({y: "count"}, {x: "period_return", fill: "strategy", label: "count"}))
]
})}

Insert cell
Insert cell
Insert cell
Plot.plot({
style: 'overflow: visible;',
width: width,
y: {
grid: true,
label: `↑ Frequency (Number of Months)`,
},
x: {
grid: true,
label: `Sequence Returns (CAGR normalized)`
},
facet: {
data: selectedStrategyAggregateData,
y: "window_length",
label: "Sequence Length (Months)",
},
marks: [
Plot.ruleX([0]),
Plot.ruleY([0]),
Plot.lineY(
selectedStrategyAggregateData, Plot.binX(
{y: "count"},
{x: "period_return", stroke: "strategy", strokeWidth: 3, label: "count"}
)
),
],
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
/**
* Returns a "year+month" based integer that corresponds to the year+month, where 0 represents "January 1970".
* We assume that "January" corresponds to a value of 1 for the month parameter.
*/
function getTimeId(year, month) {
return (year-1970) * 12 + month-1;
}
Insert cell
Insert cell
/** The inverse of getMonthId */
function getMonthAndYearFromTimeId(time_id) {
return {year: Math.floor(time_id / 12) + 1970, month: (time_id % 12 + 1)};
}
Insert cell
test = {
const obj = getMonthAndYearFromTimeId(getTimeId(2021, 2));
return `${obj.year} == 2021? (${obj.year == 2021}) && ${obj.month} == 2 (${obj.month == 2})`;
}
Insert cell
MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Insert cell
/** Assumes 1-based month IDs to MONTHS for mapping - not zero-based! */
function getMonthFromMonthIndex(time_id) {
return MONTHS[(time_id - 1 % 12)];
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
quartile1 = V => d3.quantile(V, 0.25)
Insert cell
quartile3 = V => d3.quantile(V, 0.75)
Insert cell
iqr1 = V => Math.max(d3.min(V), quartile1(V) * 2.5 - quartile3(V) * 1.5)
Insert cell
iqr2 = V => Math.min(d3.max(V), quartile3(V) * 2.5 - quartile1(V) * 1.5)
Insert cell
Insert cell
selectedStrategyIds = selectedStrats.map(strat => strat.Alias);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
month_intervals = [1, 3, 6, 9, 12, 18, 12*2, 12*3, 12*5]
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