{"schemaVersion":2,"courseId":"coint","module":{"id":"unit-roots","title":"1 · Unit roots and spurious regression","summary":"Distinguish persistent stochastic trends from stable relationships.","stages":[{"type":"read","id":"coint-unit-roots-guide","skillIds":["coint.unit-roots","coint.spurious-regression"],"estimatedMinutes":7,"difficulty":"core","title":"Unit roots and spurious regression: research guide","html":"<h2>Unit roots and spurious regression</h2><p class=\"lead\">Distinguish persistent stochastic trends from stable relationships.</p><p>Unrelated integrated series can produce impressive t statistics and R-squared; residual persistence reveals the spurious fit.</p><div class=\"callout\"><b>Workflow.</b> Specify deterministic terms and interpret tests with their low-power limitations.</div><p><b>Diagnostic:</b> Inspect trend specification, lag length, and complementary evidence. The main failure to avoid is classifying persistence from one test statistic alone.</p>","prerequisiteStageIds":[]},{"type":"interactive","id":"coint-unit-roots-lab","skillIds":["coint.unit-roots"],"estimatedMinutes":6,"difficulty":"core","title":"Unit-root testing intuition lab","note":"Regress one series on a totally unrelated one — push persistence toward 1 and watch the spurious t-stat and R-squared explode even though nothing links them.","params":[{"name":"phi","label":"Persistence φ","min":0.5,"max":1,"step":0.05,"value":0.95},{"name":"n","label":"Sample length n","min":40,"max":300,"step":10,"value":150}],"template":"import numpy as np, statsmodels.api as sm, matplotlib.pyplot as plt\nrng = np.random.default_rng(0)\nn = int({{n}}); phi = {{phi}}\ndef ar1(phi, n, rng):\n    e = rng.normal(0, 1, n); y = np.zeros(n)\n    for t in range(1, n):\n        y[t] = phi*y[t-1] + e[t]\n    return y\nx = ar1(phi, n, rng)      # two INDEPENDENT series\ny = ar1(phi, n, rng)      # nothing links them at all\nres = sm.OLS(y, sm.add_constant(x)).fit()\ntstat = res.tvalues[1]; r2 = res.rsquared\nfig, ax = plt.subplots(1, 2, figsize=(7.2, 3.4))\nax[0].plot(x, color='#da9100', lw=1.2, label='x')\nax[0].plot(y, color='#4f8fba', lw=1.2, label='y')\nax[0].legend(fontsize=8); ax[0].set_title('Two INDEPENDENT series')\nax[1].scatter(x, y, s=10, color='#8888aa', alpha=0.5)\nxs = np.linspace(x.min(), x.max(), 50)\nax[1].plot(xs, res.params[0] + res.params[1]*xs, color='#c0392b', lw=2)\nax[1].set_title(f'|t|={abs(tstat):.1f}   R2={r2:.2f}')\nplt.tight_layout()\nprint(f'phi={phi:.2f}  n={n}  slope t-stat={tstat:.2f}  R2={r2:.3f}')\nprint('These series are unrelated, so an honest |t| should exceed 2 only ~5% of the time.')\n","prerequisiteStageIds":["coint-unit-roots-guide"]},{"type":"code","id":"coint-unit-roots-worked","skillIds":["coint.unit-roots"],"estimatedMinutes":10,"difficulty":"core","title":"Unit roots and spurious regression: worked Python model","note":"Run the reproducible example, then change one assumption and compare the output.","code":"import numpy as np\nrng = np.random.default_rng(7)\nphi = 0.72\ny = np.zeros(160)\nfor t in range(1, len(y)):\n    y[t] = phi*y[t-1] + rng.normal(scale=0.8)\nX, target = y[:-1, None], y[1:]\nphi_hat = np.linalg.lstsq(X, target, rcond=None)[0][0]\nforecast = phi_hat*y[-1]\nprint(f\"Estimated persistence: {phi_hat:.3f}\")\nprint(f\"One-step forecast: {forecast:.3f}\")","prerequisiteStageIds":["coint-unit-roots-lab"]},{"type":"codechallenge","id":"coint-unit-roots-challenge","skillIds":["coint.unit-roots"],"estimatedMinutes":12,"difficulty":"core","title":"Unit-root testing code challenge","note":"Estimate an AR(1) coefficient by least squares and store the final one-step forecast.","starter":"import numpy as np\ny = np.array([0.2, 0.4, 0.1, 0.5, 0.7, 0.6])\nphi_hat = ...\nforecast = ...","tests":"expected = np.linalg.lstsq(y[:-1, None], y[1:], rcond=None)[0][0]\nassert np.isclose(phi_hat, expected)\nassert np.isclose(forecast, expected*y[-1])\nprint(\"grader: AR estimate and forecast are correct\")","hints":["Regress y[1:] on y[:-1] without an intercept.","The one-step forecast is phi_hat times the last observation."],"success":"The numerical result and the unit-root testing workflow both pass the grader.","prerequisiteStageIds":["coint-unit-roots-worked"],"variantId":"coint-unit-roots-challenge-core"},{"type":"case","id":"coint-unit-roots-case","skillIds":["coint.spurious-regression"],"estimatedMinutes":8,"difficulty":"core","title":"Spurious regression: model decision","note":"A team is about to report results without checking residual persistence and integration orders.","steps":[{"prompt":"What is the best next action?","choices":["Treat high R-squared among unrelated persistent levels as a warning.","Increase decimal precision and report immediately.","Drop observations until the preferred coefficient appears."],"answer":0,"explain":"The defensible workflow is to treat high R-squared among unrelated persistent levels as a warning."},{"prompt":"Which risk should the final report address explicitly?","choices":["Only whether the sample mean is positive.","significant level regressions created by shared stochastic trends","Whether every coefficient has the same sign."],"answer":1,"explain":"The relevant failure mode is significant level regressions created by shared stochastic trends."}],"prerequisiteStageIds":["coint-unit-roots-challenge"],"variantId":"coint-unit-roots-case-core"},{"type":"match","id":"coint-unit-roots-match","skillIds":["coint.spurious-regression"],"estimatedMinutes":7,"difficulty":"core","title":"Spurious regression: evidence map","note":"Match each research role to the course-specific evidence.","pairs":[{"left":"Good practice","right":"Treat high R-squared among unrelated persistent levels as a warning."},{"left":"Diagnostic evidence","right":"residual persistence and integration orders"},{"left":"Failure to guard against","right":"significant level regressions created by shared stochastic trends"}],"prerequisiteStageIds":["coint-unit-roots-case"],"variantId":"coint-unit-roots-match-core"}]}}
