{"spec_id":"line-multi","library":"echarts","language":"javascript","code":"// anyplot.ai\n// line-multi: Multi-Line Comparison Plot\n// Library: echarts 6.1.0 | JavaScript 22.23.1\n// Quality: 93/100 | Created: 2026-08-05\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ---------------------------------------\n// Indexed closing price (start = 100) for 4 tech companies over 60 trading days.\n// A tiny fixed-seed LCG drives a random-walk-with-drift per company so the\n// series diverge in both level and trend, which is the point of the chart.\nfunction makeLcg(seed) {\n  let s = seed >>> 0;\n  return () => {\n    s = (s * 1664525 + 1013904223) >>> 0;\n    return s / 4294967296;\n  };\n}\n\nconst NUM_DAYS = 60;\nconst days = Array.from({ length: NUM_DAYS }, (_, i) => i + 1);\n\nconst companies = [\n  { name: \"NovaChip\", seed: 11, drift: 0.55, vol: 1.6 },\n  { name: \"Solaris Energy\", seed: 29, drift: 0.15, vol: 2.0 },\n  { name: \"Vertex Biotech\", seed: 47, drift: -0.25, vol: 2.4 },\n  { name: \"Cascade Retail\", seed: 63, drift: 0.05, vol: 1.2 },\n];\n\nconst series = companies.map((c) => {\n  const rand = makeLcg(c.seed);\n  let price = 100;\n  const data = [price];\n  for (let i = 1; i < NUM_DAYS; i++) {\n    price += c.drift + (rand() - 0.5) * c.vol;\n    data.push(+price.toFixed(2));\n  }\n  return { name: c.name, data };\n});\n\nconst lineStyles = [\"solid\", \"solid\", \"dashed\", \"dotted\"];\n\n// --- Init -------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option -----------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"line-multi · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    top: 20,\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: \"bold\" },\n  },\n  legend: {\n    top: 64,\n    textStyle: { color: t.ink, fontSize: 16 },\n    itemWidth: 26,\n    itemHeight: 4,\n  },\n  grid: { left: 90, right: 130, top: 130, bottom: 80 },\n  tooltip: { trigger: \"axis\" },\n  labelLayout: { moveOverlap: \"shiftY\" },\n  xAxis: {\n    type: \"category\",\n    data: days,\n    name: \"Trading Day\",\n    nameLocation: \"middle\",\n    nameGap: 42,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14, interval: 9 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"value\",\n    scale: true,\n    name: \"Indexed Price (Day 1 = 100)\",\n    nameLocation: \"middle\",\n    nameGap: 62,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: series.map((s, i) => ({\n    name: s.name,\n    type: \"line\",\n    data: s.data,\n    symbol: \"none\",\n    smooth: false,\n    lineStyle: { color: t.palette[i], width: 3, type: lineStyles[i] },\n    itemStyle: { color: t.palette[i] },\n    emphasis: { focus: \"series\" },\n    endLabel: {\n      show: true,\n      formatter: (p) => Number(p.value).toFixed(1),\n      color: t.palette[i],\n      fontSize: 14,\n      fontWeight: \"bold\",\n      distance: 10,\n    },\n    markLine:\n      i === 0\n        ? {\n            symbol: \"none\",\n            silent: true,\n            animation: false,\n            label: {\n              show: true,\n              formatter: \"Day 1 = 100\",\n              position: \"insideEndTop\",\n              color: t.inkSoft,\n              fontSize: 12,\n            },\n            lineStyle: { color: t.inkSoft, type: \"dashed\", width: 1.5 },\n            data: [{ yAxis: 100 }],\n          }\n        : undefined,\n  })),\n});\n"}