{"spec_id":"depth-order-book","library":"muix","language":"javascript","code":"// anyplot.ai\n// depth-order-book: Order Book Depth Chart\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 87/100 | Created: 2026-06-15\n//# anyplot-orientation: landscape\n// anyplot.ai\n// depth-order-book: Order Book Depth Chart\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-06-15\n\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) -----------------------------------------\nconst MID_PRICE = 60000;\nconst BEST_BID = 59995;\nconst BEST_ASK = 60005;\nconst N = 50;\nconst TICK = 5;\n\n// Minimal LCG for reproducible pseudo-random data (seed = 42)\nlet _s = 42;\nconst rng = () => {\n  _s = (Math.imul(1664525, _s) + 1013904223) >>> 0;\n  return _s / 4294967296;\n};\n\n// Bid quantities: index 0 = best bid (nearest mid), index N-1 = worst bid\nconst bidQtys = Array.from({ length: N }, (_, i) => {\n  const base = 0.4 + rng() * 2.0;\n  const wall = i === 14 || i === 31 ? rng() * 35 + 18 : 0;\n  return +(base + wall).toFixed(3);\n});\n\n// Ask quantities: index 0 = best ask (nearest mid), index N-1 = worst ask\nconst askQtys = Array.from({ length: N }, (_, i) => {\n  const base = 0.4 + rng() * 2.0;\n  const wall = i === 11 || i === 37 ? rng() * 35 + 18 : 0;\n  return +(base + wall).toFixed(3);\n});\n\n// Cumulative sums from best price outward\nconst accumulate = (arr) =>\n  arr.map((_, i) =>\n    +arr\n      .slice(0, i + 1)\n      .reduce((a, b) => a + b, 0)\n      .toFixed(3)\n  );\n\nconst bidCum = accumulate(bidQtys); // [cum_at_best_bid, ..., cum_at_worst_bid]\nconst askCum = accumulate(askQtys); // [cum_at_best_ask, ..., cum_at_worst_ask]\n\n// Bid prices sorted ascending: worst bid (leftmost) → best bid (rightmost)\nconst bidPricesAsc = Array.from(\n  { length: N },\n  (_, i) => BEST_BID - (N - 1 - i) * TICK\n);\n// Reverse cumulative so max cum is at left (worst bid), min cum at right (best bid)\nconst bidCumAsc = [...bidCum].reverse();\n\n// Ask prices sorted ascending: best ask (leftmost) → worst ask (rightmost)\nconst askPricesAsc = Array.from({ length: N }, (_, i) => BEST_ASK + i * TICK);\n\n// Combined x-axis (all prices, ascending); bid and ask regions separated by spread gap\nconst xData = [...bidPricesAsc, ...askPricesAsc];\nconst bidData = [...bidCumAsc, ...Array(N).fill(null)]; // null at ask positions → gap\nconst askData = [...Array(N).fill(null), ...askCum]; // null at bid positions → gap\n\nconst SPREAD = BEST_ASK - BEST_BID;\n\nconst W = window.ANYPLOT_SIZE.width;\nconst H = window.ANYPLOT_SIZE.height;\nconst TITLE_H = 60;\n\n// --- Chart -------------------------------------------------------------------\nexport default function Chart() {\n  return (\n    <div style={{ width: W, height: H, display: \"flex\", flexDirection: \"column\" }}>\n      <div\n        style={{\n          height: TITLE_H,\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          color: t.ink,\n          fontSize: 22,\n          fontWeight: 500,\n          letterSpacing: 0.3,\n        }}\n      >\n        BTC/USD Order Book · depth-order-book · javascript · muix · anyplot.ai\n      </div>\n      <LineChart\n        width={W}\n        height={H - TITLE_H}\n        skipAnimation\n        xAxis={[\n          {\n            data: xData,\n            scaleType: \"linear\",\n            label: \"Price (USD)\",\n            valueFormatter: (v) => `$${v.toLocaleString(\"en-US\")}`,\n            labelStyle: { fill: t.ink, fontSize: 14 },\n            tickLabelStyle: { fill: t.inkSoft, fontSize: 14 },\n            tickNumber: 10,\n          },\n        ]}\n        yAxis={[\n          {\n            label: \"Cumulative Volume (BTC)\",\n            labelStyle: { fill: t.ink, fontSize: 14 },\n            tickLabelStyle: { fill: t.inkSoft, fontSize: 14 },\n            min: 0,\n          },\n        ]}\n        series={[\n          {\n            id: \"bids\",\n            data: bidData,\n            label: \"Bids\",\n            color: t.palette[0],\n            area: true,\n            curve: \"stepAfter\",\n            connectNulls: false,\n            showMark: false,\n          },\n          {\n            id: \"asks\",\n            data: askData,\n            label: \"Asks\",\n            color: t.palette[4],\n            area: true,\n            curve: \"stepAfter\",\n            connectNulls: false,\n            showMark: false,\n          },\n        ]}\n        grid={{ horizontal: true }}\n        sx={{\n          \"& .MuiAreaElement-series-bids\": { fillOpacity: 0.35 },\n          \"& .MuiAreaElement-series-asks\": { fillOpacity: 0.35 },\n          \"& .MuiLineElement-series-bids\": { strokeWidth: 2 },\n          \"& .MuiLineElement-series-asks\": { strokeWidth: 2 },\n          \"& .MuiChartsAxis-directionX .MuiChartsAxis-line\": { strokeOpacity: 0.4 },\n          \"& .MuiChartsAxis-directionY .MuiChartsAxis-line\": { strokeOpacity: 0.4 },\n          \"& .MuiChartsGrid-line\": { strokeOpacity: 0.5 },\n        }}\n        slotProps={{\n          legend: {\n            labelStyle: { fill: t.inkSoft, fontSize: 14 },\n          },\n        }}\n        margin={{ top: 20, right: 60, bottom: 70, left: 95 }}\n      >\n        <ChartsReferenceLine\n          x={MID_PRICE}\n          label={`Mid: $${MID_PRICE.toLocaleString(\"en-US\")} · Spread: $${SPREAD}`}\n          labelStyle={{ fill: t.inkSoft, fontSize: 13 }}\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"6 4\",\n            strokeWidth: 1.5,\n          }}\n          labelAlign=\"end\"\n        />\n      </LineChart>\n    </div>\n  );\n}\n"}