{"spec_id":"candlestick-basic","library":"echarts","language":"javascript","code":"// anyplot.ai\n// candlestick-basic: Basic Candlestick Chart\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-08-24\n\nconst t = window.ANYPLOT_TOKENS;\nconst UP = t.palette[0]; // #009E73 — bullish (price up)\nconst DOWN = \"#AE3030\"; // matte red — bearish (price down), semantic finance exception\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Small fixed-seed LCG stands in for a seeded RNG (browser has none).\nlet seed = 42;\nfunction rand() {\n  seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n  return seed / 0x7fffffff;\n}\n\nconst N = 30;\nconst dates = [];\nconst cursor = new Date(2024, 0, 2);\nwhile (dates.length < N) {\n  const weekday = cursor.getDay();\n  if (weekday !== 0 && weekday !== 6) {\n    dates.push(`${cursor.getMonth() + 1}/${cursor.getDate()}`);\n  }\n  cursor.setDate(cursor.getDate() + 1);\n}\n\nlet price = 148;\nconst ohlc = [];\nfor (let i = 0; i < N; i++) {\n  const open = price;\n  const drift = (rand() - 0.47) * 6;\n  const close = Math.max(20, open + drift);\n  const high = Math.max(open, close) + rand() * 2.5;\n  const low = Math.min(open, close) - rand() * 2.5;\n  ohlc.push([\n    Number(open.toFixed(2)),\n    Number(close.toFixed(2)),\n    Number(low.toFixed(2)),\n    Number(high.toFixed(2)),\n  ]);\n  price = close;\n}\n\n// 5-day simple moving average of the close price, for trend context.\nconst MA_PERIOD = 5;\nconst closes = ohlc.map((bar) => bar[1]);\nconst ma5 = closes.map((_, i) => {\n  if (i < MA_PERIOD - 1) return null;\n  let sum = 0;\n  for (let j = i - MA_PERIOD + 1; j <= i; j++) sum += closes[j];\n  return Number((sum / MA_PERIOD).toFixed(2));\n});\n\n// --- Init --------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option --------------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"candlestick-basic · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    textStyle: { color: t.ink, fontSize: 22 },\n  },\n  legend: {\n    top: 56,\n    left: \"center\",\n    textStyle: { color: t.ink, fontSize: 14 },\n    data: [\"5-Day MA\"],\n  },\n  grid: { left: 90, right: 60, top: 130, bottom: 70 },\n  tooltip: { trigger: \"axis\" },\n  xAxis: {\n    type: \"category\",\n    data: dates,\n    boundaryGap: true,\n    axisLabel: { color: t.inkSoft, fontSize: 14, interval: 2 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"value\",\n    scale: true,\n    name: \"Price (USD)\",\n    nameTextStyle: { color: t.inkSoft, fontSize: 14 },\n    axisLabel: { color: t.inkSoft, fontSize: 14, formatter: \"${value}\" },\n    axisLine: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [\n    {\n      type: \"candlestick\",\n      name: \"OHLC\",\n      data: ohlc,\n      itemStyle: {\n        color: UP,\n        color0: DOWN,\n        borderColor: UP,\n        borderColor0: DOWN,\n      },\n    },\n    {\n      type: \"line\",\n      name: \"5-Day MA\",\n      data: ma5,\n      symbol: \"none\",\n      lineStyle: { color: t.palette[1], width: 2 },\n      itemStyle: { color: t.palette[1] },\n      markPoint: {\n        symbolSize: 52,\n        itemStyle: { color: t.palette[1] },\n        label: {\n          color: t.pageBg,\n          fontSize: 12,\n          formatter: (p) => Math.round(p.value),\n        },\n        data: [\n          { type: \"max\", name: \"Peak\" },\n          { type: \"min\", name: \"Trough\" },\n        ],\n      },\n    },\n  ],\n});\n"}