Module 12 · Statistical Computing and Reproducibility Module demo
Production-Grade Metrics Service
Same data, run twice.
Transcript
45 sentences · select one to jump thereCode lab
Run it yourself
The demo source in one language. Edit it, run TypeScript and Python right here, and compare with the expected output.
/**
* Fintech Math Bootcamp · Module 12 demo · Production-Grade Metrics Service
* The Module 11 risk report, rebuilt as a service that gives the same answer every time it runs.
* A feed delivers twenty synthetic days of returns for two funds (60% A, 40% B) in a different order on
* every run, with a few broken records. A naive report and the production service each run twice and
* stamp their results with a checksum: the naive checksums drift, the production checksums match.
* Lessons 111–120: floating point, compensated summation, Welford variance, batch/rolling/streaming
* equivalence, input policies, seeded PRNGs, index alignment, leakage-free scaling, tolerance and property
* tests, and an audit record with an FNV-1a checksum over canonical JSON.
* Conventions: sample SD (n − 1), A = 252 trading days, loss = −return, type 7 loss quantiles.
* Synthetic example; not investment advice.
*/
export type Rec = {day: number; id: string; r: unknown};
type Stats = {count: number; mean: number; m2: number};
// 111 · floating point is finite and rounded
export const floatFacts = () => ({
sum: 0.1 + 0.2, exactlyPointThree: 0.1 + 0.2 === 0.3,
overflow: String(Number.MAX_VALUE * 2), underflow: Number.MIN_VALUE / 2, epsilon: Number.EPSILON,
});
// 112 · Neumaier (improved Kahan) compensated summation
export function stableSum(values: number[]): number {
let sum = 0, correction = 0;
for (const x of values) {
const next = sum + x;
correction += Math.abs(sum) >= Math.abs(x) ? (sum - next) + x : (x - next) + sum;
sum = next;
}
return sum + correction;
}
export const naiveSum = (values: number[]) => values.reduce((s, x) => s + x, 0);
// 113 · Welford: update count, mean and M2 one value at a time
export function welfordPush(s: Stats, x: number): Stats {
const count = s.count + 1, delta = x - s.mean, mean = s.mean + delta / count;
return {count, mean, m2: s.m2 + delta * (x - mean)};
}
export const welford = (values: number[]) => values.reduce(welfordPush, {count: 0, mean: 0, m2: 0});
export const welfordSD = (s: Stats) => Math.sqrt(s.m2 / (s.count - 1));
// the unstable textbook shortcut: (Σx² − n·mean²) / (n − 1)
export function textbookVariance(values: number[]): number {
const n = values.length, sum = naiveSum(values), sumSq = naiveSum(values.map(x => x * x));
return (sumSq - sum * sum / n) / (n - 1);
}
// two-pass batch SD with a stable mean
export function batchSD(values: number[]): number {
const m = stableSum(values) / values.length;
return Math.sqrt(stableSum(values.map(x => (x - m) ** 2)) / (values.length - 1));
}
// 114 · rolling window SD, recomputed per window from a queue of the last w observations
export function rollingSD(values: number[], w: number): (number | null)[] {
const queue: number[] = [];
return values.map(x => { queue.push(x); if (queue.length > w) queue.shift(); return queue.length === w ? welfordSD(welford(queue)) : null; });
}
// 115 · explicit input policy: missing ≠ zero ≠ invalid ≠ unsupported
export type Verdict = {day: number; id: string; raw: string; status: "accepted" | "missing" | "invalid" | "unsupported"; naive: string};
export function classify(rec: Rec): Verdict {
const raw = rec.r === null ? "null" : typeof rec.r === "string" ? JSON.stringify(rec.r) : String(rec.r);
const naive = String(Number(rec.r) || 0); // what a careless loader would store
if (rec.r === null || rec.r === undefined) return {day: rec.day, id: rec.id, raw, status: "missing", naive};
if (typeof rec.r !== "number") return {day: rec.day, id: rec.id, raw, status: "unsupported", naive};
if (!Number.isFinite(rec.r)) return {day: rec.day, id: rec.id, raw, status: "invalid", naive};
return {day: rec.day, id: rec.id, raw, status: "accepted", naive};
}
// 116 · seeded linear congruential generator (reproducible, not cryptographic)
export function lcg(seed: number) {
let state = seed >>> 0;
return () => { state = (Math.imul(1664525, state) + 1013904223) >>> 0; return state / 4294967296; };
}
// 117 · align by identifier before a dot product; a missing ID throws instead of guessing
export function alignedDot(weights: {id: string; w: number}[], rets: {id: string; r: number}[]): number {
const byId = new Map(rets.map(x => [x.id, x.r]));
return weights.reduce((s, x) => { const r = byId.get(x.id); if (r === undefined) throw new Error("Missing asset " + x.id); return s + x.w * r; }, 0);
}
export const positionalDot = (weights: {id: string; w: number}[], rets: {id: string; r: number}[]) => weights.reduce((s, x, i) => s + x.w * rets[i].r, 0);
// 118 · fit a scaler on training data only, then freeze it
export function fitScaler(train: number[]) { const s = welford(train); return {mean: s.mean, sd: welfordSD(s)}; }
export const transform = (x: number[], p: {mean: number; sd: number}) => x.map(v => (v - p.mean) / p.sd);
// 119 · tolerance comparison: |a − b| ≤ absTol + relTol · max(|a|, |b|)
export const near = (a: number, b: number, absTol = 1e-12, relTol = 1e-10) => Math.abs(a - b) <= absTol + relTol * Math.max(Math.abs(a), Math.abs(b));
// 120 · canonical JSON (sorted keys, recursively) and FNV-1a over its UTF-16 code units
export function canonical(v: unknown): string {
if (Array.isArray(v)) return "[" + v.map(canonical).join(",") + "]";
if (v !== null && typeof v === "object") return "{" + Object.keys(v as object).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).map(k => JSON.stringify(k) + ":" + canonical((v as Record<string, unknown>)[k])).join(",") + "}";
return JSON.stringify(v);
}
export function fnv1a(text: string): string {
let hash = 2166136261;
for (let k = 0; k < text.length; k++) hash = Math.imul(hash ^ text.charCodeAt(k), 16777619) >>> 0;
return hash.toString(16).padStart(8, "0");
}
/* ---------- the synthetic feed ---------- */
const A = 252, W = [{id: "A", w: 0.6}, {id: "B", w: 0.4}];
const PCT: Record<string, number[]> = {
A: [0.6, -0.5, 0.8, -0.6, 0.5, -0.3, 0.7, -0.5, 0.6, -0.4, 0.4, -0.8, -0.6, 0.6, -0.9, 0.3, -0.7, 0.5, -0.6, 0.9],
B: [-0.4, 0.7, -0.5, 0.8, -0.3, 0.6, -0.4, 0.7, -0.3, 0.7, 0.5, -0.7, -0.8, 0.5, -0.8, 0.4, -0.6, 0.6, -0.5, 0.8],
};
const LATE: Rec[] = [{day: 21, id: "A", r: null}, {day: 21, id: "B", r: NaN}, {day: 22, id: "A", r: Infinity}, {day: 22, id: "B", r: "0.003"}];
// the feed for run k: 40 good records plus 4 broken ones, shuffled by a seeded permutation (arrival order differs per run)
export function feed(run: number): Rec[] {
const recs: Rec[] = [...["A", "B"].flatMap(id => PCT[id].map((p, i) => ({day: i + 1, id, r: p / 100}))), ...LATE];
const rnd = lcg(1000 + run);
for (let i = recs.length - 1; i > 0; i--) { const j = Math.floor(rnd() * (i + 1)); [recs[i], recs[j]] = [recs[j], recs[i]]; }
return recs;
}
/* ---------- shared risk math (module 11, compact) ---------- */
function drawdownOf(port: number[]) { let w = 1, peak = 1, mdd = 0; for (const r of port) { w *= 1 + r; peak = Math.max(peak, w); mdd = Math.min(mdd, w / peak - 1); } return mdd; }
function quantile7(sorted: number[], p: number) { const h = (sorted.length - 1) * p, i = Math.floor(h); return i + 1 < sorted.length ? sorted[i] + (h - i) * (sorted[i + 1] - sorted[i]) : sorted[i]; }
function tail(port: number[], p: number) { const losses = port.map(r => -r).sort((a, b) => a - b), v = quantile7(losses, p), t = losses.filter(l => l >= v); return {var: v, es: stableSum(t) / t.length}; }
function monteCarloVaR(port: number[], seed: number, paths: number, horizon: number, p: number) {
const rnd = lcg(seed), losses: number[] = [];
for (let k = 0; k < paths; k++) { let g = 1; for (let d = 0; d < horizon; d++) g *= 1 + port[Math.floor(rnd() * port.length)]; losses.push(1 - g); }
losses.sort((a, b) => a - b);
return quantile7(losses, p);
}
const MC = {paths: 2000, horizon: 10, confidence: 0.95, seed: 42};
// the production service: policy → canonical order → aligned dot → stable statistics → seeded simulation
export function productionReport(recs: Rec[]) {
const verdicts = recs.map(classify), ok = recs.filter((_, i) => verdicts[i].status === "accepted") as {day: number; id: string; r: number}[];
const days = [...new Set(ok.map(x => x.day))].sort((a, b) => a - b);
const port = days.map(d => alignedDot(W, ok.filter(x => x.day === d).sort((a, b) => (a.id < b.id ? -1 : 1)).map(x => ({id: x.id, r: x.r}))));
const s = welford(port), sd = welfordSD(s), t = tail(port, 0.9);
return {
rejected: verdicts.filter(v => v.status !== "accepted").length, days: port.length,
meanDaily: stableSum(port) / port.length, sdDaily: sd, annualVol: sd * Math.sqrt(A), maxDrawdown: drawdownOf(port),
var90: t.var, es90: t.es, mcVar95: monteCarloVaR(port, MC.seed, MC.paths, MC.horizon, MC.confidence),
};
}
// the naive report: arrival order, coercion, positional dot product, one-pass variance, a seed that changes every run
export function naiveReport(recs: Rec[], run: number) {
const byDay = new Map<number, {id: string; r: number}[]>();
for (const x of recs) { const r = Number(x.r) || 0; if (!Number.isFinite(r)) continue; byDay.set(x.day, [...(byDay.get(x.day) ?? []), {id: x.id, r}]); }
const port = [...byDay.values()].filter(v => v.length === 2).map(v => positionalDot(W, v));
const sd = Math.sqrt(Math.max(0, textbookVariance(port))), t = tail(port, 0.9);
return {
rejected: 0, days: port.length, meanDaily: naiveSum(port) / port.length, sdDaily: sd, annualVol: sd * Math.sqrt(A),
maxDrawdown: drawdownOf(port), var90: t.var, es90: t.es, mcVar95: monteCarloVaR(port, 7919 * run + 13, MC.paths, MC.horizon, MC.confidence),
};
}
function audit(results: object) {
const record = {dataset: "synthetic-two-fund-20d", version: "metrics-service-1.0", cutoff: "day-20", method: "sample-sd, type7-var90, es90, bootstrap-var95-10d",
params: {annualization: A, confidence: 0.9, weights: {A: 0.6, B: 0.4}, mc: MC}, results};
const text = canonical(record);
return {text, checksum: fnv1a(text), bytes: text.length};
}
export function runDemo() {
// 111 and 112
const dimes = Array.from({length: 10}, () => 0.1);
const ordered = PCT.A.map((a, i) => (0.6 * a + 0.4 * PCT.B[i]) / 100), reversed = [...ordered].reverse();
const floats = {...floatFacts(), dimesNaive: naiveSum(dimes), dimesStable: stableSum(dimes),
orderNaive: [naiveSum(ordered), naiveSum(reversed)], orderStable: [stableSum(ordered), stableSum(reversed)]};
// 113 and 114
const balances = [4, 7, 13, 16].map(c => 1e9 + c);
const steps: Stats[] = []; balances.reduce((s, x) => { const n = welfordPush(s, x); steps.push(n); return n; }, {count: 0, mean: 0, m2: 0});
const prod1 = productionReport(feed(1));
const port = ordered;
const roll = rollingSD(port, 5), stream = welford(port);
const batch = batchSD(port), streaming = welfordSD(stream), rollLast = roll.at(-1)!, batchLast = batchSD(port.slice(-5));
const variance = {balances, textbook: textbookVariance(balances), welford: welford(balances).m2 / 3, steps,
batch, streaming, rolling: roll, rollingLast: rollLast, batchLast, maxGap: Math.max(Math.abs(batch - streaming), Math.abs(rollLast - batchLast))};
// 115 and 117
const policy = LATE.map(classify);
const day1 = [{id: "B", r: PCT.B[0] / 100}, {id: "A", r: PCT.A[0] / 100}];
const alignment = {weights: W, day1, positional: positionalDot(W, day1), aligned: alignedDot(W, day1),
missing: (() => { try { alignedDot(W, [{id: "A", r: 0.01}]); return "no error"; } catch (e) { return (e as Error).message; } })()};
// 116 · replay a simulation
const draws = (() => { const r = lcg(MC.seed); return [r(), r(), r()]; })();
const mc = {...MC, draws, replay: [monteCarloVaR(port, 42, MC.paths, MC.horizon, MC.confidence), monteCarloVaR(port, 42, MC.paths, MC.horizon, MC.confidence)],
otherSeeds: [7919 + 13, 7919 * 2 + 13].map(sd => monteCarloVaR(port, sd, MC.paths, MC.horizon, MC.confidence))};
// 118 · leakage-free scaling
const train = port.slice(0, 15), test = port.slice(15), fit = fitScaler(train), leaky = fitScaler(port);
const scaling = {train: train.length, test: test.length, fit, leaky, testScaled: transform(test, fit), testLeaky: transform(test, leaky)};
// 119 · fixtures, tolerances and properties
const x = [1, 2, 3, 4, 5], v = (a: number[]) => welford(a).m2 / (a.length - 1);
const prod2 = productionReport(feed(2));
const tests = [
{name: "fixture: variance [1..5] = 2.5", pass: near(v(x), 2.5)},
{name: "0.1 + 0.2 ≈ 0.3 within tolerance", pass: near(0.1 + 0.2, 0.3)},
{name: "property: shift leaves variance unchanged", pass: near(v(x.map(q => q + 100)), v(x))},
{name: "property: doubling multiplies variance by 4", pass: near(v(x.map(q => 2 * q)), 4 * v(x))},
{name: "streaming SD ≈ batch SD", pass: near(streaming, batch)},
{name: "rolling window ≈ batch on last 5 days", pass: near(rollLast, batchLast)},
{name: "seed 42 replays the simulation exactly", pass: mc.replay[0] === mc.replay[1]},
{name: "shuffled feed gives identical results", pass: canonical(prod1) === canonical(prod2)},
];
// 120 · run twice, compare checksums
const naive1 = naiveReport(feed(1), 1), naive2 = naiveReport(feed(2), 2);
const a1 = audit(prod1), a2 = audit(prod2), n1 = audit(naive1), n2 = audit(naive2);
const naiveSameSeed = [audit({...naive1, mcVar95: 0}).checksum, audit({...naive2, mcVar95: 0}).checksum];
return {
series: port, floats, variance, policy, alignment, mc, scaling, tests, passed: tests.filter(t => t.pass).length,
report: prod1, naive: [naive1, naive2],
audit: {production: [a1.checksum, a2.checksum], naive: [n1.checksum, n2.checksum], naiveWithoutSimulation: naiveSameSeed, bytes: a1.bytes, preview: a1.text.slice(0, 290)},
};
}
export const checkedResult = {"series":[0.0019999999999999996,-0.00020000000000000017,0.0027999999999999995,-0.00039999999999999926,0.0018,0.0006,0.0025999999999999994,-0.00020000000000000017,0.0024,0.0003999999999999998,0.0044,-0.0076,-0.0068000000000000005,0.005600000000000001,-0.008600000000000002,0.0034000000000000002,-0.006599999999999999,0.0054,-0.005600000000000001,0.008600000000000002],"floats":{"sum":0.30000000000000004,"exactlyPointThree":false,"overflow":"Infinity","underflow":0,"epsilon":2.220446049250313e-16,"dimesNaive":0.9999999999999999,"dimesStable":1,"orderNaive":[0.004000000000000001,0.003999999999999999],"orderStable":[0.004,0.004]},"variance":{"balances":[1000000004,1000000007,1000000013,1000000016],"textbook":-170.66666666666666,"welford":30,"steps":[{"count":1,"mean":1000000004,"m2":0},{"count":2,"mean":1000000005.5,"m2":4.5},{"count":3,"mean":1000000008,"m2":42},{"count":4,"mean":1000000010,"m2":90}],"batch":0.0048440957007365925,"streaming":0.0048440957007365925,"rolling":[null,null,null,null,0.0014212670403551892,0.0013608820668963198,0.0013608820668963195,0.0012930583900195689,0.0012033287165193057,0.001260158720161869,0.0018471599822430108,0.00455543631280254,0.005452338947644396,0.006157921727336261,0.0069799713466460606,0.006739436178197699,0.006574191965557441,0.006882441427284362,0.0063403469936589435,0.0067858676674394415],"rollingLast":0.0067858676674394415,"batchLast":0.0067858676674394415,"maxGap":0},"policy":[{"day":21,"id":"A","raw":"null","status":"missing","naive":"0"},{"day":21,"id":"B","raw":"NaN","status":"invalid","naive":"0"},{"day":22,"id":"A","raw":"Infinity","status":"invalid","naive":"Infinity"},{"day":22,"id":"B","raw":"\"0.003\"","status":"unsupported","naive":"0.003"}],"alignment":{"weights":[{"id":"A","w":0.6},{"id":"B","w":0.4}],"day1":[{"id":"B","r":-0.004},{"id":"A","r":0.006}],"positional":4.336808689942018e-19,"aligned":0.002,"missing":"Missing asset B"},"mc":{"paths":2000,"horizon":10,"confidence":0.95,"seed":42,"draws":[0.2523451747838408,0.08812504541128874,0.5772811982315034],"replay":[0.02288091697116998,0.02288091697116998],"otherSeeds":[0.0235096580423508,0.022490264485876904]},"scaling":{"train":15,"test":5,"fit":{"mean":-0.0000800000000000001,"sd":0.00428405682235225},"leaky":{"mean":0.0002000000000000001,"sd":0.0048440957007365925},"testScaled":[0.8123141555553024,-1.5219219236266006,1.2791613713916832,-1.2884983157084107,2.0261169167298925],"testLeaky":[0.6605980140965028,-1.403770779955068,1.073471772906817,-1.1973339005499115,1.73406978700332]},"tests":[{"name":"fixture: variance [1..5] = 2.5","pass":true},{"name":"0.1 + 0.2 ≈ 0.3 within tolerance","pass":true},{"name":"property: shift leaves variance unchanged","pass":true},{"name":"property: doubling multiplies variance by 4","pass":true},{"name":"streaming SD ≈ batch SD","pass":true},{"name":"rolling window ≈ batch on last 5 days","pass":true},{"name":"seed 42 replays the simulation exactly","pass":true},{"name":"shuffled feed gives identical results","pass":true}],"passed":8,"report":{"rejected":4,"days":20,"meanDaily":0.0002,"sdDaily":0.004844095700736592,"annualVol":0.07689763530687711,"maxDrawdown":-0.020744781492684217,"var90":0.0068800000000000016,"es90":0.0081,"mcVar95":0.02288091697116998},"naive":[{"rejected":0,"days":21,"meanDaily":0.00012380952380952365,"sdDaily":0.004665394384390752,"annualVol":0.07406083985481127,"maxDrawdown":-0.012361920000000026,"var90":0.0068000000000000005,"es90":0.0076,"mcVar95":0.02384626501528193},{"rejected":0,"days":21,"meanDaily":0.000019047619047619036,"sdDaily":0.00464667828105401,"annualVol":0.07376373092516404,"maxDrawdown":-0.021872247459054694,"var90":0.0068000000000000005,"es90":0.0076,"mcVar95":0.023645018842607172}],"audit":{"production":["e45c2a42","e45c2a42"],"naive":["fb4c38e3","bded2195"],"naiveWithoutSimulation":["a05d8d06","6b4b7085"],"bytes":511,"preview":"{\"cutoff\":\"day-20\",\"dataset\":\"synthetic-two-fund-20d\",\"method\":\"sample-sd, type7-var90, es90, bootstrap-var95-10d\",\"params\":{\"annualization\":252,\"confidence\":0.9,\"mc\":{\"confidence\":0.95,\"horizon\":10,\"paths\":2000,\"seed\":42},\"weights\":{\"A\":0.6,\"B\":0.4}},\"results\":{\"annualVol\":0.0768976353068"}};
// Run this file directly: npx tsx lessons/12-statistical-computing-and-reproducibility/demo-production-metrics-service.ts
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/").split("/").pop()!)) {
console.log(JSON.stringify(runDemo(), null, 2));
}
Your output
Press Run to execute the code in your browser.
Expected output
{
"series": [
0.0019999999999999996,
-0.00020000000000000017,
0.0027999999999999995,
-0.00039999999999999926,
0.0018,
0.0006,
0.0025999999999999994,
-0.00020000000000000017,
0.0024,
0.0003999999999999998,
0.0044,
-0.0076,
-0.0068000000000000005,
0.005600000000000001,
-0.008600000000000002,
0.0034000000000000002,
-0.006599999999999999,
0.0054,
-0.005600000000000001,
0.008600000000000002
],
"floats": {
"sum": 0.30000000000000004,
"exactlyPointThree": false,
"overflow": "Infinity",
"underflow": 0,
"epsilon": 2.220446049250313e-16,
"dimesNaive": 0.9999999999999999,
"dimesStable": 1,
"orderNaive": [
0.004000000000000001,
0.003999999999999999
],
"orderStable": [
0.004,
0.004
]
},
"variance": {
"balances": [
1000000004,
1000000007,
1000000013,
1000000016
],
"textbook": -170.66666666666666,
"welford": 30,
"steps": [
{
"count": 1,
"mean": 1000000004,
"m2": 0
},
{
"count": 2,
"mean": 1000000005.5,
"m2": 4.5
},
{
"count": 3,
"mean": 1000000008,
"m2": 42
},
{
"count": 4,
"mean": 1000000010,
"m2": 90
}
],
"batch": 0.0048440957007365925,
"streaming": 0.0048440957007365925,
"rolling": [
null,
null,
null,
null,
0.0014212670403551892,
0.0013608820668963198,
0.0013608820668963195,
0.0012930583900195689,
0.0012033287165193057,
0.001260158720161869,
0.0018471599822430108,
0.00455543631280254,
0.005452338947644396,
0.006157921727336261,
0.0069799713466460606,
0.006739436178197699,
0.006574191965557441,
0.006882441427284362,
0.0063403469936589435,
0.0067858676674394415
],
"rollingLast": 0.0067858676674394415,
"batchLast": 0.0067858676674394415,
"maxGap": 0
},
"policy": [
{
"day": 21,
"id": "A",
"raw": "null",
"status": "missing",
"naive": "0"
},
{
"day": 21,
"id": "B",
"raw": "NaN",
"status": "invalid",
"naive": "0"
},
{
"day": 22,
"id": "A",
"raw": "Infinity",
"status": "invalid",
"naive": "Infinity"
},
{
"day": 22,
"id": "B",
"raw": "\"0.003\"",
"status": "unsupported",
"naive": "0.003"
}
],
"alignment": {
"weights": [
{
"id": "A",
"w": 0.6
},
{
"id": "B",
"w": 0.4
}
],
"day1": [
{
"id": "B",
"r": -0.004
},
{
"id": "A",
"r": 0.006
}
],
"positional": 4.336808689942018e-19,
"aligned": 0.002,
"missing": "Missing asset B"
},
"mc": {
"paths": 2000,
"horizon": 10,
"confidence": 0.95,
"seed": 42,
"draws": [
0.2523451747838408,
0.08812504541128874,
0.5772811982315034
],
"replay": [
0.02288091697116998,
0.02288091697116998
],
"otherSeeds": [
0.0235096580423508,
0.022490264485876904
]
},
"scaling": {
"train": 15,
"test": 5,
"fit": {
"mean": -0.0000800000000000001,
"sd": 0.00428405682235225
},
"leaky": {
"mean": 0.0002000000000000001,
"sd": 0.0048440957007365925
},
"testScaled": [
0.8123141555553024,
-1.5219219236266006,
1.2791613713916832,
-1.2884983157084107,
2.0261169167298925
],
"testLeaky": [
0.6605980140965028,
-1.403770779955068,
1.073471772906817,
-1.1973339005499115,
1.73406978700332
]
},
"tests": [
{
"name": "fixture: variance [1..5] = 2.5",
"pass": true
},
{
"name": "0.1 + 0.2 ≈ 0.3 within tolerance",
"pass": true
},
{
"name": "property: shift leaves variance unchanged",
"pass": true
},
{
"name": "property: doubling multiplies variance by 4",
"pass": true
},
{
"name": "streaming SD ≈ batch SD",
"pass": true
},
{
"name": "rolling window ≈ batch on last 5 days",
"pass": true
},
{
"name": "seed 42 replays the simulation exactly",
"pass": true
},
{
"name": "shuffled feed gives identical results",
"pass": true
}
],
"passed": 8,
"report": {
"rejected": 4,
"days": 20,
"meanDaily": 0.0002,
"sdDaily": 0.004844095700736592,
"annualVol": 0.07689763530687711,
"maxDrawdown": -0.020744781492684217,
"var90": 0.0068800000000000016,
"es90": 0.0081,
"mcVar95": 0.02288091697116998
},
"naive": [
{
"rejected": 0,
"days": 21,
"meanDaily": 0.00012380952380952365,
"sdDaily": 0.004665394384390752,
"annualVol": 0.07406083985481127,
"maxDrawdown": -0.012361920000000026,
"var90": 0.0068000000000000005,
"es90": 0.0076,
"mcVar95": 0.02384626501528193
},
{
"rejected": 0,
"days": 21,
"meanDaily": 0.000019047619047619036,
"sdDaily": 0.00464667828105401,
"annualVol": 0.07376373092516404,
"maxDrawdown": -0.021872247459054694,
"var90": 0.0068000000000000005,
"es90": 0.0076,
"mcVar95": 0.023645018842607172
}
],
"audit": {
"production": [
"e45c2a42",
"e45c2a42"
],
"naive": [
"fb4c38e3",
"bded2195"
],
"naiveWithoutSimulation": [
"a05d8d06",
"6b4b7085"
],
"bytes": 511,
"preview": "{\"cutoff\":\"day-20\",\"dataset\":\"synthetic-two-fund-20d\",\"method\":\"sample-sd, type7-var90, es90, bootstrap-var95-10d\",\"params\":{\"annualization\":252,\"confidence\":0.9,\"mc\":{\"confidence\":0.95,\"horizon\":10,\"paths\":2000,\"seed\":42},\"weights\":{\"A\":0.6,\"B\":0.4}},\"results\":{\"annualVol\":0.0768976353068"
}
}Prefer your own machine? Every file is in the course repository · open it in Codespaces.
What the demo does
The Module 11 risk report rebuilt as a service that gives the same answer every run: stable sums, Welford variance, an explicit input policy, ID alignment, a seeded Monte Carlo, a leakage-free scaler, tolerance and property tests, and an audit record whose FNV-1a checksum matches across runs while a naive version drifts.
Lessons it combines
- Floating-Point Representation, Overflow, and Underflow
- Stable Summation and Mean Calculation
- Stable Online Variance and Welford’s Algorithm
- Batch, Rolling, and Streaming Statistic Equivalence
- Missing, Infinite, Invalid, and Unsupported-State Policies
- Pseudorandom Numbers, Seeds, and Reproducibility
- Vectorization, Index Alignment, and Shape Safety
- Leakage-Free Fitting, Scaling, and Preprocessing
- Fixtures, Numerical Tolerances, and Property Tests
- Reproducible Analysis, Metadata, and Audit Trails