{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3"
  },
  "language_info": {
   "name": "python"
  },
  "colab": {
   "provenance": []
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day 73: Sharp Regression Discontinuity\n",
    "\n",
    "*Beginner to Ninja: Math for Causal Inference*\n",
    "\n",
    "When treatment switches on at a known threshold of a running variable, units just above and just below are comparable. The jump in the outcome at the cutoff identifies the effect there, under one assumption: potential outcomes are continuous in the running variable.\n",
    "\n",
    "**Learning outcomes**\n",
    "\n",
    "- Define the sharp RD estimand and state the continuity assumption.\n",
    "- Estimate the jump with separate linear fits on each side and explain why a raw difference in means is biased.\n",
    "- Prove identification and explain why the effect is local to the cutoff.\n",
    "- Apply RD to drinking age, incumbency, scholarships and Medicare eligibility."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Theory\n",
    "\n",
    "### Design\n",
    "\n",
    "A **running variable** $X$ (age, test score, vote margin, income) determines treatment by a rule: $D = \\mathbf 1[X \\ge c]$. There is no overlap: every unit with $X \\ge c$ is treated and every unit below is not. Units cannot be compared at the same $X$, but they can be compared arbitrarily close to $c$.\n",
    "\n",
    "### Estimand and assumption\n",
    "\n",
    "$$\n",
    "\\tau_{SRD} = \\lim_{x \\downarrow c}E[Y \\mid X = x] - \\lim_{x \\uparrow c}E[Y \\mid X = x].\n",
    "$$\n",
    "\n",
    "**Continuity:** $E[Y(0) \\mid X = x]$ and $E[Y(1) \\mid X = x]$ are continuous at $x = c$. Then\n",
    "\n",
    "$$\n",
    "\\tau_{SRD} = E[Y(1) - Y(0) \\mid X = c].\n",
    "$$\n",
    "\n",
    "Continuity fails if something else also changes at the cutoff (another policy at age 21), or if units manipulate $X$ to land on the desired side (Day 77).\n",
    "\n",
    "### Estimation\n",
    "\n",
    "Fit $E[Y \\mid X]$ separately on each side near $c$ and take the difference of the two fitted values at $c$. The standard choice is **local linear regression** within a bandwidth $h$ (Days 74–75):\n",
    "\n",
    "$$\n",
    "Y_i = \\alpha + \\tau D_i + \\beta_1(X_i - c) + \\beta_2 D_i(X_i - c) + \\varepsilon_i, \\qquad |X_i - c| \\le h.\n",
    "$$\n",
    "\n",
    "A **raw difference in means** within $[c - h, c + h]$ is biased whenever $E[Y \\mid X]$ has a slope; **high-order global polynomials** fitted to the whole range give erratic estimates and should be avoided (Gelman and Imbens).\n",
    "\n",
    "### What RD identifies\n",
    "\n",
    "The effect for units at the cutoff, an extreme form of locality. Away from $c$ the data say nothing without further assumptions. Heterogeneity in effects along $X$ can be studied only with extrapolation or multiple cutoffs.\n",
    "\n",
    "### Two views\n",
    "\n",
    "- **Continuity:** limits of conditional expectations, estimated by local polynomials.\n",
    "- **Local randomisation:** within a small window, treatment is as good as random (for instance when $X$ includes a random component that units cannot control precisely); analyse as an experiment.\n",
    "\n",
    "## Part 1 · Warm-up"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1 · A jump\n",
    "\n",
    "At the cutoff, the fitted line from the left reaches 90 and the fitted line from the right starts at 98. Estimate the effect.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 98 - 90 = 8$.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2 · Find the design\n",
    "\n",
    "Name the running variable, cutoff and treatment: (a) Medicare eligibility; (b) a merit scholarship; (c) the effect of being the incumbent party; (d) a class-size cap of 40 pupils.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** (a) Age, 65, Medicare coverage.\n",
    "\n",
    "**Step 2.** (b) Exam score, the qualifying score, receiving the scholarship.\n",
    "\n",
    "**Step 3.** (c) Vote margin in the previous election, 0, holding the seat.\n",
    "\n",
    "**Step 4.** (d) Enrolment, 41 (and 81, ...), being split into smaller classes (fuzzy in practice, Day 76).\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3 · Separate lines\n",
    "\n",
    "Left of the cutoff the fitted line is $50 + 2(x - c)$; right of it, $55 + 1.5(x - c)$. Estimate the effect and say whether the effect varies with $x$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** At $x = c$: $55 - 50 = 5$.\n",
    "\n",
    "**Step 2.** The slopes differ, but RD identifies only the jump at $c$; the difference in slopes does not reveal how the effect varies away from $c$ without extra assumptions.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4 · Bias of a difference in means\n",
    "\n",
    "$E[Y \\mid X] = a + s(x - c) + \\tau\\mathbf 1[x \\ge c]$, with $X$ uniform near $c$. What does the difference in means between $[c, c + h]$ and $[c - h, c)$ estimate?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Right mean: $a + \\tau + sh/2$. Left mean: $a - sh/2$.\n",
    "\n",
    "**Step 2.** Difference: $\\tau + sh$.\n",
    "\n",
    "**Answer:** biased by $sh$; with slope 2 and $h = 1$, by 2. Local linear fits remove this bias.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5 · Local effect\n",
    "\n",
    "An RD at a scholarship cutoff finds an effect on college completion of 10 points. Does a policy lowering the cutoff by 50 points have the same effect?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The estimate applies to students scoring at the current cutoff.\n",
    "\n",
    "**Step 2.** Students 50 points lower may benefit more (or less); the design does not tell us.\n",
    "\n",
    "**Answer:** not necessarily; extrapolation needs assumptions or other evidence.\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 2 · Proofs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 6 · Identification\n",
    "\n",
    "Prove $\\tau_{SRD} = E[Y(1) - Y(0) \\mid X = c]$ under continuity.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** For $x \\ge c$, $E[Y \\mid X = x] = E[Y(1) \\mid X = x]$; for $x < c$, $E[Y \\mid X = x] = E[Y(0) \\mid X = x]$.\n",
    "\n",
    "**Step 2.** By continuity, $\\lim_{x \\downarrow c}E[Y(1) \\mid X = x] = E[Y(1) \\mid X = c]$ and $\\lim_{x \\uparrow c}E[Y(0) \\mid X = x] = E[Y(0) \\mid X = c]$.\n",
    "\n",
    "**Step 3.** Subtract. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 7 · The general bias of a window comparison\n",
    "\n",
    "Let $\\mu_d(x) = E[Y(d) \\mid X = x]$ be differentiable with slope $\\mu_d'(c)$ at $c$ and $X$ uniform near $c$. Show that, to first order, the window difference in means is $\\tau + \\frac h2(\\mu_1'(c) + \\mu_0'(c))$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Right mean $\\approx \\mu_1(c) + \\mu_1'(c)\\,h/2$; left mean $\\approx \\mu_0(c) - \\mu_0'(c)\\,h/2$.\n",
    "\n",
    "**Step 2.** Subtract: $\\tau + \\frac h2(\\mu_1'(c) + \\mu_0'(c))$. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 8 · Separate regressions\n",
    "\n",
    "Show that the pooled regression $Y = \\alpha + \\tau D + \\beta_1(X - c) + \\beta_2 D(X - c)$ within the window gives the same $\\hat\\tau$ as fitting separate lines on each side and differencing their intercepts at $c$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The pooled regression has a separate intercept and slope for each side ($\\alpha, \\beta_1$ left; $\\alpha + \\tau, \\beta_1 + \\beta_2$ right).\n",
    "\n",
    "**Step 2.** With no shared parameters, the least-squares problem splits into two separate problems.\n",
    "\n",
    "**Step 3.** $\\hat\\tau$ is the difference of the two fitted intercepts at $X = c$. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 9 · No extrapolation without assumptions\n",
    "\n",
    "Construct two models consistent with the same observed $E[Y \\mid X]$ but with different effects at $x = c + 1$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Observed: $E[Y \\mid X] = x$ for $x < c$ and $x + 5$ for $x \\ge c$.\n",
    "\n",
    "**Step 2.** Model A: $\\mu_0(x) = x$ everywhere, $\\mu_1(x) = x + 5$: effect 5 at all $x$.\n",
    "\n",
    "**Step 3.** Model B: $\\mu_0(x) = x$ for $x < c$ and $x + 2(x - c)$ for $x \\ge c$ (unobserved there); $\\mu_1(x) = x + 5$: effect $5 - 2(x - c)$, which is 3 at $c + 1$.\n",
    "\n",
    "**Answer:** both match the data; $\\mu_0$ is never observed right of $c$. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 10 · Covariates do not change the estimand\n",
    "\n",
    "Let $W$ be a pre-treatment covariate with $E[W \\mid X]$ continuous at $c$. Explain why adding $W$ linearly to the local linear regression leaves the estimand unchanged (in large samples) but can reduce variance.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Including $W$ changes $\\hat\\tau$ by its coefficient times the jump in $E[W \\mid X]$ at $c$ (FWL).\n",
    "\n",
    "**Step 2.** Continuity of $E[W \\mid X]$ makes that jump zero in the limit.\n",
    "\n",
    "**Step 3.** $W$ explains outcome variance, shrinking residuals and the standard error.\n",
    "\n",
    "**Answer:** same estimand, possibly more precision; a jump in $W$ would instead signal a violation (Day 77). $\\blacksquare$\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 3 · Applied"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 11 · The minimum legal drinking age\n",
    "\n",
    "Mortality of young adults (deaths per 100,000 person-years) approaches 94 from below age 21 and 103 from above. Estimate the effect of legal access to alcohol and state the key assumption.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 103 - 94 = 9$ deaths per 100,000, about 9.6%.\n",
    "\n",
    "**Step 2.** Assumption: nothing else that affects mortality changes discontinuously at 21.\n",
    "\n",
    "**Answer:** about 9 extra deaths per 100,000 (mostly motor-vehicle accidents and suicides in studies of this design); only age-21-specific changes (for example, casino access in some states) would threaten it.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 12 · The incumbency advantage\n",
    "\n",
    "In US House elections, the Democratic vote share in the next election approaches 0.47 for districts where Democrats lost narrowly and 0.55 where they won narrowly. Estimate and interpret.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 0.55 - 0.47 = 0.08$.\n",
    "\n",
    "**Step 2.** Bare winners and bare losers are similar; winning confers incumbency.\n",
    "\n",
    "**Answer:** incumbency raises the next-election vote share by about 8 points for marginal seats.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 13 · A merit scholarship\n",
    "\n",
    "College enrolment approaches 0.60 just below the qualifying score and 0.68 just above. Estimate the effect, and say for whom.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 0.08$.\n",
    "\n",
    "**Answer:** an 8-point rise in enrolment for students scoring at the threshold, typically above-average students; effects for students far below the threshold are not identified.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 14 · Medicare at 65\n",
    "\n",
    "Insurance coverage rises from 88% to 97% at age 65, and hospital admissions jump by 8%. Is this a sharp RD for \"having insurance\"? What can be estimated?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Medicare eligibility is sharp at 65, but insurance coverage jumps only from 88% to 97%: for coverage, the design is fuzzy.\n",
    "\n",
    "**Step 2.** The sharp RD estimates the effect of *eligibility* (reaching 65) on admissions: +8%.\n",
    "\n",
    "**Answer:** the effect of insurance itself requires scaling by the jump in coverage (Day 76), and must account for changes in the type of coverage (secondary insurance), not just its presence.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 15 · Global polynomials\n",
    "\n",
    "In the simulation below, compare the local linear estimate within a bandwidth with a global fourth-order polynomial and with a raw window difference in means. Which behaves badly and why?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The local linear estimate is close to the true jump on average.\n",
    "\n",
    "**Step 2.** The window difference in means is biased by the slope (Exercise 4).\n",
    "\n",
    "**Step 3.** The global quartic is roughly unbiased here but noisier (SD about 1.0 versus 0.7): it puts large weight on observations far from the cutoff and is sensitive to the polynomial order.\n",
    "\n",
    "**Answer:** prefer local linear (or local quadratic) fits with a data-driven bandwidth (Day 75).\n",
    "\n",
    "</details>\n",
    "\n",
    "## Verify in Python"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "rng = np.random.default_rng(73)\n",
    "c, tau = 0.0, 5.0\n",
    "mu0 = lambda x: 50 + 8 * x + 6 * x ** 2 - 4 * x ** 3          # smooth untreated outcome\n",
    "def sample(n=1000):\n",
    "    x = rng.uniform(-1, 1, n); y = mu0(x) + tau * (x >= c) + rng.normal(0, 3, n)\n",
    "    return x, y\n",
    "def local_linear(x, y, h):\n",
    "    m = np.abs(x - c) <= h; d = (x >= c).astype(float)\n",
    "    X = np.column_stack([np.ones(m.sum()), d[m], x[m] - c, d[m] * (x[m] - c)])\n",
    "    return np.linalg.lstsq(X, y[m], rcond=None)[0][1]\n",
    "def window_means(x, y, h):\n",
    "    return y[(x >= c) & (x <= c + h)].mean() - y[(x < c) & (x >= c - h)].mean()\n",
    "def global_poly(x, y, p=4):\n",
    "    d = (x >= c).astype(float)\n",
    "    X = np.column_stack([np.ones_like(x), d] + [x ** k for k in range(1, p + 1)] + [d * x ** k for k in range(1, p + 1)])\n",
    "    return np.linalg.lstsq(X, y, rcond=None)[0][1]\n",
    "res = {\"local linear h=0.3\": [], \"window means h=0.3\": [], \"global quartic\": []}\n",
    "for _ in range(1000):\n",
    "    x, y = sample()\n",
    "    res[\"local linear h=0.3\"].append(local_linear(x, y, .3))\n",
    "    res[\"window means h=0.3\"].append(window_means(x, y, .3))\n",
    "    res[\"global quartic\"].append(global_poly(x, y))\n",
    "for k, v in res.items():\n",
    "    print(f\"{k:20s} mean {np.mean(v):6.2f}  sd {np.std(v):5.2f}  (truth {tau})\")\n",
    "print(\"Ex 4 bias s*h:\", 2 * 1, \" | Ex 11:\", 103 - 94, f\"({(103 - 94) / 94:.1%})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Key takeaways\n",
    "\n",
    "- Sharp RD identifies the effect at the cutoff as the jump in $E[Y \\mid X]$, assuming potential outcomes are continuous there.\n",
    "- Estimate with local linear fits on each side; raw window means are biased by the slope, global polynomials are fragile.\n",
    "- The effect is local; extrapolating away from the cutoff needs extra assumptions."
   ]
  }
 ]
}