{"spec_id":"frontier-efficient","library":"muix","language":"javascript","code":"// anyplot.ai\n// frontier-efficient: Efficient Frontier for Portfolio Optimization\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 87/100 | Created: 2026-09-02\n//# anyplot-orientation: landscape\n// anyplot.ai\n// frontier-efficient: Efficient Frontier for Portfolio Optimization\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-09-02\n\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { LinePlot } from \"@mui/x-charts/LineChart\";\nimport { ScatterPlot } from \"@mui/x-charts/ScatterChart\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { ChartsGrid } from \"@mui/x-charts/ChartsGrid\";\nimport { ChartsLegend } from \"@mui/x-charts/ChartsLegend\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport { useXScale, useYScale } from \"@mui/x-charts/hooks\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Linear algebra helpers (Gauss-Jordan inverse, dot / matrix-vector) -----\nfunction invertMatrix(M) {\n  const n = M.length;\n  const A = M.map((row, i) => [...row, ...Array.from({ length: n }, (_, j) => (i === j ? 1 : 0))]);\n  for (let col = 0; col < n; col++) {\n    let pivotRow = col;\n    let maxVal = Math.abs(A[col][col]);\n    for (let r = col + 1; r < n; r++) {\n      if (Math.abs(A[r][col]) > maxVal) {\n        maxVal = Math.abs(A[r][col]);\n        pivotRow = r;\n      }\n    }\n    [A[col], A[pivotRow]] = [A[pivotRow], A[col]];\n    const pivot = A[col][col];\n    for (let j = 0; j < 2 * n; j++) A[col][j] /= pivot;\n    for (let r = 0; r < n; r++) {\n      if (r === col) continue;\n      const factor = A[r][col];\n      for (let j = 0; j < 2 * n; j++) A[r][j] -= factor * A[col][j];\n    }\n  }\n  return A.map((row) => row.slice(n));\n}\nconst matVec = (M, v) => M.map((row) => row.reduce((s, mij, j) => s + mij * v[j], 0));\nconst dot = (a, b) => a.reduce((s, ai, i) => s + ai * b[i], 0);\n\n// --- Asset universe (annualized historical return / vol / correlation) -----\nconst MU = [0.095, 0.075, 0.11, 0.035, 0.085, 0.045];\nconst VOL = [0.16, 0.18, 0.24, 0.055, 0.19, 0.15];\nconst CORR = [\n  [1.0, 0.82, 0.72, -0.08, 0.58, 0.02],\n  [0.82, 1.0, 0.78, -0.04, 0.52, 0.08],\n  [0.72, 0.78, 1.0, -0.12, 0.48, 0.12],\n  [-0.08, -0.04, -0.12, 1.0, 0.1, 0.18],\n  [0.58, 0.52, 0.48, 0.1, 1.0, 0.06],\n  [0.02, 0.08, 0.12, 0.18, 0.06, 1.0],\n];\nconst N = MU.length;\nconst COV = CORR.map((row, i) => row.map((c, j) => c * VOL[i] * VOL[j]));\nconst COV_INV = invertMatrix(COV);\nconst ONES = Array(N).fill(1);\nconst RF = 0.02; // risk-free rate\n\n// Two-fund theorem scalars for the analytic minimum-variance frontier\nconst A_ = dot(ONES, matVec(COV_INV, ONES));\nconst B_ = dot(ONES, matVec(COV_INV, MU));\nconst C_ = dot(MU, matVec(COV_INV, MU));\nconst D_ = A_ * C_ - B_ * B_;\n\nconst R_GMV = B_ / A_;\nconst RISK_GMV = Math.sqrt(1 / A_);\n\n// Tangency (max Sharpe ratio) portfolio: w = Sigma^-1 (mu - rf) / 1'Sigma^-1(mu - rf)\nconst excess = MU.map((m) => m - RF);\nconst zTan = matVec(COV_INV, excess);\nconst sumZTan = zTan.reduce((a, b) => a + b, 0);\nconst wTan = zTan.map((z) => z / sumZTan);\nconst R_TAN = dot(wTan, MU);\nconst RISK_TAN = Math.sqrt(dot(wTan, matVec(COV, wTan)));\nconst SHARPE_TAN = (R_TAN - RF) / RISK_TAN;\n\n// Analytic efficient frontier: risk(r) = sqrt((A*r^2 - 2*B*r + C) / D) for r >= r_gmv\nconst R_MAX = Math.max(...MU) * 1.18;\nconst FN = 80;\nconst frontierReturns = Array.from({ length: FN }, (_, i) => R_GMV + ((R_MAX - R_GMV) * i) / (FN - 1));\nconst frontierRisks = frontierReturns.map((r) => Math.sqrt(Math.max(0, (A_ * r * r - 2 * B_ * r + C_) / D_)));\n\n// Reproducible LCG (seed 7) — no Math.random() in browser harness context\nlet seed = 7;\nfunction rng() {\n  seed = (Math.imul(1664525, seed) + 1013904223) >>> 0;\n  return seed / 4294967296;\n}\nconst randExp = () => -Math.log(1 - rng());\n\n// 300 randomly weighted long-only portfolios (Dirichlet(1) weights via normalized exponentials)\nconst N_PORT = 300;\nconst portfolios = Array.from({ length: N_PORT }, (_, k) => {\n  const e = Array.from({ length: N }, randExp);\n  const s = e.reduce((a, b) => a + b, 0);\n  const w = e.map((v) => v / s);\n  const r = dot(w, MU);\n  const risk = Math.sqrt(dot(w, matVec(COV, w)));\n  return { id: `p${k}`, x: risk, y: r, z: (r - RF) / risk };\n});\nconst sharpeVals = portfolios.map((p) => p.z);\nconst SHARPE_MIN = Math.min(...sharpeVals);\nconst SHARPE_MAX = Math.max(...sharpeVals, SHARPE_TAN);\n\nconst X_MAX = Math.max(RISK_TAN, RISK_GMV, ...frontierRisks, ...portfolios.map((p) => p.x)) * 1.08;\nconst Y_MIN = Math.min(RF, R_GMV, ...portfolios.map((p) => p.y)) - 0.015;\nconst Y_MAX = Math.max(R_MAX, ...portfolios.map((p) => p.y)) * 1.04;\n\nconst pct = (v) => `${(v * 100).toFixed(0)}%`;\n\n// Capital Market Line: r = rf + Sharpe_tan * risk, drawn via axis-scale hooks.\n// Clip the endpoint to the visible plot bounds (intersect the ray with y = Y_MAX) so the\n// line never overshoots the chart, and place the label ~60% along the visible segment\n// (well clear of both the top-right legend and the bottom-left risk-free reference line).\nconst CML_X_END = SHARPE_TAN > 0 ? Math.min(X_MAX, (Y_MAX - RF) / SHARPE_TAN) : X_MAX;\nconst CML_Y_END = RF + SHARPE_TAN * CML_X_END;\nconst CML_LABEL_X = 0.6 * CML_X_END;\nconst CML_LABEL_Y = RF + SHARPE_TAN * CML_LABEL_X;\n\nfunction CapitalMarketLine() {\n  const xScale = useXScale(\"risk\");\n  const yScale = useYScale(\"return\");\n  if (!xScale || !yScale) return null;\n  const x1 = xScale(0);\n  const y1 = yScale(RF);\n  const x2 = xScale(CML_X_END);\n  const y2 = yScale(CML_Y_END);\n  const xLabel = xScale(CML_LABEL_X);\n  const yLabel = yScale(CML_LABEL_Y);\n  return (\n    <g>\n      <line x1={x1} y1={y1} x2={x2} y2={y2} stroke={t.palette[1]} strokeWidth={2.5} strokeDasharray=\"10,6\" />\n      <text x={xLabel} y={yLabel - 22} textAnchor=\"middle\" fontSize={14} fontWeight={600} fill={t.palette[1]}>\n        Capital Market Line\n      </text>\n    </g>\n  );\n}\n\nconst TITLE = \"frontier-efficient · javascript · muix · anyplot.ai\";\n\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n  const TITLE_H = 56;\n  const COLORBAR_H = 54;\n  const chartH = height - TITLE_H - COLORBAR_H;\n\n  return (\n    <Box sx={{ width, height, background: t.pageBg, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}>\n      <Typography sx={{ fontSize: \"22px\", fontWeight: 600, color: t.ink, textAlign: \"center\", pt: \"14px\", pb: \"6px\" }}>\n        {TITLE}\n      </Typography>\n      <ChartContainer\n        width={width}\n        height={chartH}\n        margin={{ top: 24, right: 64, bottom: 76, left: 132 }}\n        sx={{ \"& .MuiLineElement-root\": { strokeWidth: 4 } }}\n        series={[\n          {\n            type: \"line\",\n            id: \"frontier\",\n            data: frontierReturns,\n            xAxisId: \"risk\",\n            yAxisId: \"return\",\n            color: t.ink,\n            showMark: false,\n            curve: \"monotoneX\",\n            label: \"Efficient Frontier\",\n          },\n          {\n            type: \"scatter\",\n            id: \"cloud\",\n            data: portfolios,\n            xAxisId: \"risk\",\n            yAxisId: \"return\",\n            zAxisId: \"sharpe\",\n            markerSize: 6,\n          },\n          {\n            type: \"scatter\",\n            id: \"gmv\",\n            data: [{ x: RISK_GMV, y: R_GMV, id: \"gmv\" }],\n            xAxisId: \"risk\",\n            yAxisId: \"return\",\n            zAxisId: \"flat\",\n            color: t.ink,\n            markerSize: 20,\n            label: \"Min-Variance Portfolio\",\n          },\n          {\n            type: \"scatter\",\n            id: \"tan\",\n            data: [{ x: RISK_TAN, y: R_TAN, id: \"tan\" }],\n            xAxisId: \"risk\",\n            yAxisId: \"return\",\n            zAxisId: \"flat\",\n            color: t.palette[0],\n            markerSize: 20,\n            label: \"Max-Sharpe (Tangency) Portfolio\",\n          },\n        ]}\n        xAxis={[\n          {\n            id: \"risk\",\n            scaleType: \"linear\",\n            data: frontierRisks,\n            min: 0,\n            max: X_MAX,\n            label: \"Portfolio Risk (Annualized Std Dev)\",\n            valueFormatter: pct,\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n            labelStyle: { fontSize: 16, fill: t.ink },\n          },\n        ]}\n        yAxis={[\n          {\n            id: \"return\",\n            min: Y_MIN,\n            max: Y_MAX,\n            label: \"Expected Portfolio Return (Annualized)\",\n            valueFormatter: pct,\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n            labelStyle: { fontSize: 16, fill: t.ink },\n          },\n        ]}\n        zAxis={[\n          {\n            id: \"sharpe\",\n            min: SHARPE_MIN,\n            max: SHARPE_MAX,\n            colorMap: { type: \"continuous\", min: SHARPE_MIN, max: SHARPE_MAX, color: [t.seq[0], t.seq[1]] },\n          },\n          // No colorMap: gives the highlight markers below an escape hatch from the\n          // \"sharpe\" colorScale, which MUI X otherwise applies to every scatter series\n          // that doesn't set its own zAxisId (ScatterPlot.js falls back to zAxisIds[0]).\n          { id: \"flat\" },\n        ]}\n      >\n        <ChartsGrid horizontal vertical />\n        <LinePlot skipAnimation />\n        <ScatterPlot skipAnimation />\n        <CapitalMarketLine />\n        <ChartsReferenceLine\n          y={RF}\n          axisId=\"return\"\n          label=\"Risk-free rate\"\n          labelAlign=\"end\"\n          labelStyle={{ fill: t.inkSoft, fontSize: 12 }}\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"4,4\", strokeWidth: 1, opacity: 0.5 }}\n        />\n        <ChartsXAxis axisId=\"risk\" tickLabelStyle={{ fontSize: 14, fill: t.inkSoft }} labelStyle={{ fontSize: 16, fill: t.ink }} />\n        <ChartsYAxis\n          axisId=\"return\"\n          tickFontSize={30}\n          tickLabelStyle={{ fontSize: 14, fill: t.inkSoft }}\n          labelStyle={{ fontSize: 16, fill: t.ink }}\n        />\n        <ChartsLegend\n          position={{ vertical: \"top\", horizontal: \"right\" }}\n          slotProps={{\n            legend: {\n              itemMarkWidth: 16,\n              itemMarkHeight: 16,\n              markGap: 8,\n              itemGap: 24,\n              labelStyle: { fontSize: 14, fill: t.ink },\n            },\n          }}\n        />\n      </ChartContainer>\n      {/* Sharpe-ratio colorbar for the random-portfolio cloud */}\n      <Box sx={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", gap: \"12px\", pb: \"14px\" }}>\n        <Typography sx={{ fontSize: \"13px\", color: t.inkSoft }}>Low Sharpe ratio</Typography>\n        <Box sx={{ width: 220, height: 14, borderRadius: \"3px\", background: `linear-gradient(to right, ${t.seq[0]}, ${t.seq[1]})` }} />\n        <Typography sx={{ fontSize: \"13px\", color: t.inkSoft }}>High Sharpe ratio</Typography>\n      </Box>\n    </Box>\n  );\n}\n"}