{"spec_id":"acf-pacf","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// acf-pacf: Autocorrelation and Partial Autocorrelation (ACF/PACF) Plot\n// Library: highcharts 12.6.0 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-10\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Reproducible RNG: LCG seed=42 + Box-Muller transform\nfunction makeLCG(seed) {\n  let s = seed >>> 0;\n  return () => { s = (Math.imul(1664525, s) + 1013904223) >>> 0; return s / 4294967296; };\n}\nfunction makeNormal(lcg) {\n  return () => {\n    const u1 = lcg() + 1e-10, u2 = lcg();\n    return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n  };\n}\n\n// AR(2) time series: X_t = 0.7 X_{t-1} − 0.2 X_{t-2} + ε_t  (N=300)\n// PACF cutoff after lag 2 reveals the AR(2) order clearly\nconst N = 300;\nconst randn = makeNormal(makeLCG(42));\nconst tsSeries = new Array(N).fill(0);\nfor (let i = 2; i < N; i++) {\n  tsSeries[i] = 0.7 * tsSeries[i - 1] - 0.2 * tsSeries[i - 2] + randn();\n}\n\n// ACF: sample autocorrelation for lags 0..maxLag\nfunction computeACF(x, maxLag) {\n  const n = x.length;\n  const mu = x.reduce((a, b) => a + b, 0) / n;\n  const v  = x.reduce((s, xi) => s + (xi - mu) ** 2, 0) / n;\n  const r = [1.0];\n  for (let h = 1; h <= maxLag; h++) {\n    let c = 0;\n    for (let i = 0; i < n - h; i++) c += (x[i] - mu) * (x[i + h] - mu);\n    r.push(c / (n * v));\n  }\n  return r;\n}\n\n// PACF: Durbin–Levinson recursion, returns values for lags 1..maxLag\nfunction computePACF(rho, maxLag) {\n  const p = [];\n  let phi = [rho[1]];\n  p.push(rho[1]);\n  for (let k = 2; k <= maxLag; k++) {\n    let num = rho[k], den = 1;\n    for (let j = 0; j < k - 1; j++) {\n      num -= phi[j] * rho[k - 1 - j];\n      den -= phi[j] * rho[j + 1];\n    }\n    const phikk = num / den;\n    p.push(phikk);\n    const np = new Array(k);\n    np[k - 1] = phikk;\n    for (let j = 0; j < k - 1; j++) np[j] = phi[j] - phikk * phi[k - 2 - j];\n    phi = np;\n  }\n  return p;\n}\n\nconst MAX_LAG = 35;\nconst acfVals  = computeACF(tsSeries, MAX_LAG);    // lags 0..35\nconst pacfVals = computePACF(acfVals, MAX_LAG);    // lags 1..35\nconst ci = 1.96 / Math.sqrt(N);                    // 95% confidence bound ≈ 0.113\n\nHighcharts.chart(\"container\", {\n  chart: {\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n    marginTop: 85,\n    marginBottom: 75,\n    marginLeft: 78,\n    marginRight: 50\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"acf-pacf · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" }\n  },\n  subtitle: {\n    text: \"AR(2) process · N = 300 observations · dashed lines show 95% confidence bounds\",\n    style: { color: t.inkSoft, fontSize: \"13px\" }\n  },\n  xAxis: {\n    min: 0,\n    max: MAX_LAG,\n    tickInterval: 5,\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    title: { text: \"Lag\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n    labels: { style: { color: t.inkSoft, fontSize: \"13px\" } }\n  },\n  yAxis: [\n    {\n      top: \"8%\",\n      height: \"40%\",\n      max: 1.15,\n      title: { text: \"ACF\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n      labels: {\n        style: { color: t.inkSoft, fontSize: \"12px\" },\n        format: \"{value:.2f}\"\n      },\n      gridLineColor: t.grid,\n      lineColor: t.inkSoft,\n      tickColor: t.inkSoft,\n      plotLines: [\n        { value: 0, color: t.inkSoft, width: 1, zIndex: 2 },\n        {\n          value: ci,\n          color: t.amber,\n          dashStyle: \"ShortDash\",\n          width: 1.5,\n          zIndex: 3,\n          label: {\n            text: \"95% CI\",\n            align: \"right\",\n            x: -6,\n            style: { color: t.amber, fontSize: \"11px\" }\n          }\n        },\n        { value: -ci, color: t.amber, dashStyle: \"ShortDash\", width: 1.5, zIndex: 3 }\n      ]\n    },\n    {\n      top: \"57%\",\n      height: \"38%\",\n      offset: 0,\n      title: { text: \"PACF\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n      labels: {\n        style: { color: t.inkSoft, fontSize: \"12px\" },\n        format: \"{value:.2f}\"\n      },\n      gridLineColor: t.grid,\n      lineColor: t.inkSoft,\n      tickColor: t.inkSoft,\n      plotLines: [\n        { value: 0, color: t.inkSoft, width: 1, zIndex: 2 },\n        { value:  ci, color: t.amber, dashStyle: \"ShortDash\", width: 1.5, zIndex: 3 },\n        { value: -ci, color: t.amber, dashStyle: \"ShortDash\", width: 1.5, zIndex: 3 }\n      ]\n    }\n  ],\n  plotOptions: {\n    series: { animation: false, enableMouseTracking: false },\n    column: { pointWidth: 2, borderWidth: 0, grouping: false, threshold: 0 },\n    scatter: { showInLegend: false }\n  },\n  legend: { enabled: false },\n  tooltip: { enabled: false },\n  series: [\n    {\n      name: \"ACF\",\n      type: \"column\",\n      data: acfVals.map((v, i) => ({ x: i, y: v })),\n      yAxis: 0,\n      color: t.palette[0]\n    },\n    {\n      name: \"ACF dots\",\n      type: \"scatter\",\n      data: acfVals.map((v, i) => ({ x: i, y: v })),\n      yAxis: 0,\n      color: t.palette[0],\n      marker: { radius: 4, symbol: \"circle\" }\n    },\n    {\n      name: \"PACF\",\n      type: \"column\",\n      data: pacfVals.map((v, i) => ({ x: i + 1, y: v })),\n      yAxis: 1,\n      color: t.palette[2]\n    },\n    {\n      name: \"PACF dots\",\n      type: \"scatter\",\n      data: pacfVals.map((v, i) => ({ x: i + 1, y: v })),\n      yAxis: 1,\n      color: t.palette[2],\n      marker: { radius: 4, symbol: \"circle\" }\n    }\n  ]\n});\n"}