{
 "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 76: Fuzzy RD as Local IV\n",
    "\n",
    "*Beginner to Ninja: Math for Causal Inference*\n",
    "\n",
    "When crossing the cutoff raises the probability of treatment without determining it, the discontinuity becomes an instrument. The ratio of the jump in outcomes to the jump in take-up identifies a local average effect for compliers at the cutoff, and is estimated by 2SLS within a bandwidth.\n",
    "\n",
    "**Learning outcomes**\n",
    "\n",
    "- Define the fuzzy RD estimand as a ratio of two jumps.\n",
    "- Prove that it equals the average effect for compliers at the cutoff under continuity and monotonicity.\n",
    "- Implement fuzzy RD as 2SLS with the same bandwidth and controls in both stages.\n",
    "- Apply it to class size, insurance at 65 and scholarship take-up, with attention to weak first stages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Theory\n",
    "\n",
    "### Fuzzy designs\n",
    "\n",
    "In a **fuzzy RD**, crossing the cutoff changes the probability of treatment by less than one:\n",
    "\n",
    "$$\n",
    "\\lim_{x \\downarrow c}P(D = 1 \\mid X = x) - \\lim_{x \\uparrow c}P(D = 1 \\mid X = x) = \\pi \\in (0, 1).\n",
    "$$\n",
    "\n",
    "Examples: eligibility rules with imperfect take-up, guidelines that doctors sometimes override, class-size caps that schools partly ignore.\n",
    "\n",
    "### Estimand\n",
    "\n",
    "$$\n",
    "\\tau_{FRD} = \\frac{\\lim_{x \\downarrow c}E[Y \\mid X = x] - \\lim_{x \\uparrow c}E[Y \\mid X = x]}{\\lim_{x \\downarrow c}E[D \\mid X = x] - \\lim_{x \\uparrow c}E[D \\mid X = x]}.\n",
    "$$\n",
    "\n",
    "It is a Wald estimator (Day 62) using $Z = \\mathbf 1[X \\ge c]$ as the instrument, evaluated at the cutoff. A sharp RD is the special case $\\pi = 1$.\n",
    "\n",
    "### Interpretation (Hahn, Todd and van der Klaauw)\n",
    "\n",
    "Let $D(x')$ denote treatment if the cutoff rule were set as if the unit's running variable were $x'$, with types defined at the cutoff. Under continuity of potential outcomes and type shares in $x$, monotonicity (crossing the cutoff never discourages treatment) and exclusion (the cutoff affects $Y$ only through $D$),\n",
    "\n",
    "$$\n",
    "\\tau_{FRD} = E[Y(1) - Y(0) \\mid \\text{complier}, X = c].\n",
    "$$\n",
    "\n",
    "It is doubly local: compliers, and at the cutoff.\n",
    "\n",
    "### Estimation\n",
    "\n",
    "Within bandwidth $h$ (kernel-weighted), run 2SLS:\n",
    "\n",
    "- First stage: $D_i = \\gamma_0 + \\pi Z_i + \\gamma_1(X_i - c) + \\gamma_2 Z_i(X_i - c) + v_i$.\n",
    "- Second stage: $Y_i = \\alpha_0 + \\tau D_i + \\alpha_1(X_i - c) + \\alpha_2 Z_i(X_i - c) + \\varepsilon_i$.\n",
    "\n",
    "With the same bandwidth, kernel and controls in both stages, $\\hat\\tau$ equals the ratio of the two local linear jumps. Bandwidths are chosen for the ratio (or for the reduced form), and RBC inference extends to the ratio.\n",
    "\n",
    "### Practical points\n",
    "\n",
    "Always plot the first stage. A small jump in take-up is a weak instrument (Day 65): report the reduced form and weak-instrument-robust intervals.\n",
    "\n",
    "## Part 1 · Warm-up"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1 · A ratio of jumps\n",
    "\n",
    "The outcome jumps by 6 at the cutoff and the treatment probability by 0.4. Estimate the fuzzy RD effect.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 6/0.4 = 15$.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2 · Types at the cutoff\n",
    "\n",
    "At a scholarship cutoff, take-up approaches 0.15 from below and 0.70 from above. Under monotonicity, what are the shares of always-takers, never-takers and compliers among students at the cutoff?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Always-takers (funded anyway below the cutoff): 0.15.\n",
    "\n",
    "**Step 2.** Never-takers (not taking it even when eligible): $1 - 0.70 = 0.30$.\n",
    "\n",
    "**Step 3.** Compliers: $0.70 - 0.15 = 0.55$.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3 · Sharp as a special case\n",
    "\n",
    "Show that if $P(D = 1 \\mid X)$ jumps from 0 to 1, the fuzzy estimand equals the sharp one.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The denominator is $1 - 0 = 1$.\n",
    "\n",
    "**Step 2.** The ratio equals the outcome jump, the sharp RD estimand.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4 · The reduced form\n",
    "\n",
    "In Exercise 1, what does the outcome jump of 6 estimate by itself?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The effect of *eligibility* (crossing the cutoff) on the outcome, averaged over all units at the cutoff: an intention-to-treat effect.\n",
    "\n",
    "**Answer:** 6 is the ITT; dividing by take-up gives the effect of treatment for compliers.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5 · A weak jump\n",
    "\n",
    "Take-up jumps by 0.05 at the cutoff. What problems does this create?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The denominator is small and estimated with noise: the ratio is imprecise, biased towards OLS, and its usual CI unreliable (Day 65).\n",
    "\n",
    "**Answer:** report the reduced form, the first stage with its F, and an Anderson–Rubin-type interval.\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 2 · Proofs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 6 · Identification of the complier effect\n",
    "\n",
    "Assume that, near the cutoff, $Z = \\mathbf 1[X \\ge c]$ acts as a randomly assigned instrument in the limit: type shares and the conditional means of $Y(1), Y(0)$ given type are continuous in $x$ at $c$. Under monotonicity and exclusion, prove $\\tau_{FRD} = E[Y(1) - Y(0) \\mid \\text{complier}, X = c]$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Just above $c$, treated units are compliers and always-takers; just below, always-takers only.\n",
    "\n",
    "**Step 2.** Outcome jump: by continuity, always-takers' and never-takers' contributions are the same on both sides and cancel; compliers contribute $\\pi_c(c)\\,E[Y(1) - Y(0) \\mid c, X = c]$.\n",
    "\n",
    "**Step 3.** Take-up jump: $\\pi_c(c)$.\n",
    "\n",
    "**Step 4.** Divide (the LATE theorem at the cutoff). $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 7 · 2SLS equals the ratio of jumps\n",
    "\n",
    "Show that, with a uniform kernel and the same window and controls $(1, X - c, Z(X - c))$ in both stages, 2SLS gives $\\hat\\tau = \\hat\\rho/\\hat\\pi$, the ratio of the reduced-form and first-stage jumps.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The model is just identified, with $Z$ the excluded instrument and the same controls $\\mathbf W$ in both stages.\n",
    "\n",
    "**Step 2.** By FWL, partial $\\mathbf W$ out of $Y$, $D$ and $Z$: $\\hat\\tau = \\tilde Z^\\top\\tilde Y/\\tilde Z^\\top\\tilde D$.\n",
    "\n",
    "**Step 3.** The reduced-form coefficient on $Z$ is $\\tilde Z^\\top\\tilde Y/\\tilde Z^\\top\\tilde Z$ and the first-stage one $\\tilde Z^\\top\\tilde D/\\tilde Z^\\top\\tilde Z$; their ratio is the same expression. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 8 · A delta-method standard error\n",
    "\n",
    "With reduced-form jump $\\hat\\rho$, first-stage jump $\\hat\\pi$ and covariance matrix of the two, write the delta-method variance of $\\hat\\tau$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** As in Day 62, Exercise 7:\n",
    "\n",
    "$$\n",
    "\\operatorname{Var}(\\hat\\tau) \\approx \\frac{\\operatorname{Var}(\\hat\\rho) + \\tau^2\\operatorname{Var}(\\hat\\pi) - 2\\tau\\operatorname{Cov}(\\hat\\rho, \\hat\\pi)}{\\pi^2}. \\quad \\blacksquare\n",
    "$$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 9 · One-sided fuzziness\n",
    "\n",
    "If nobody below the cutoff can be treated, show the fuzzy RD estimand is the average effect on treated units at the cutoff.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** No always-takers: all treated units just above the cutoff are compliers.\n",
    "\n",
    "**Step 2.** By Exercise 6 the estimand is the complier effect at $c$, i.e. the effect on the treated at $c$ (Day 62, Exercise 8). $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 10 · A direct effect of crossing the cutoff\n",
    "\n",
    "If crossing the cutoff affects $Y$ directly by $\\delta$ (exclusion fails), what does $\\tau_{FRD}$ estimate?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The outcome jump becomes $\\pi\\tau + \\delta$.\n",
    "\n",
    "**Step 2.** $\\tau_{FRD} = \\tau + \\delta/\\pi$.\n",
    "\n",
    "**Answer:** biased, more so with a weak first stage; for instance an age-65 cutoff that also triggers retirement benefits. $\\blacksquare$\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 3 · Applied"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 11 · Maimonides' rule and class size\n",
    "\n",
    "When enrolment passes 40, the rule splits a cohort into two classes. At the cutoff, average class size drops by 8 pupils and reading scores rise by 2 points. Estimate the effect of one extra pupil per class.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** First stage: $-8$ pupils. Reduced form: $+2$ points.\n",
    "\n",
    "**Step 2.** $\\hat\\tau = 2/(-8) = -0.25$ points per extra pupil.\n",
    "\n",
    "**Answer:** reducing class size by 10 raises scores by about 2.5 points, for classes at the 40-pupil threshold.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 12 · Insurance at 65\n",
    "\n",
    "At age 65, insurance coverage rises by 9 points and hospital admissions per 100 people per year rise from 10.0 to 10.8. Estimate the effect of insurance on admissions for those who gain coverage at 65.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Reduced form: $+0.8$ admissions per 100 people.\n",
    "\n",
    "**Step 2.** First stage: $0.09$.\n",
    "\n",
    "**Step 3.** $\\hat\\tau = 0.8/0.09 \\approx 8.9$ admissions per 100 newly insured people per year.\n",
    "\n",
    "**Answer:** about 0.09 extra admissions per newly insured person, under exclusion (other changes at 65, such as retirement, would bias this).\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 13 · Scholarship take-up\n",
    "\n",
    "Eligibility raises scholarship take-up by 0.5 at the cutoff and college enrolment by 0.04. Estimate the effect of receiving the scholarship.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\hat\\tau = 0.04/0.5 = 0.08$.\n",
    "\n",
    "**Answer:** receiving the scholarship raises enrolment by 8 points for compliers at the cutoff.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 14 · A weak first stage\n",
    "\n",
    "A guideline recommends a drug for patients with a risk score above 10; prescribing jumps by only 0.05 (SE 0.03) and the outcome by 0.01 (SE 0.008). What would you report?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** First-stage $t \\approx 1.7$, $F \\approx 2.8$: very weak.\n",
    "\n",
    "**Step 2.** The ratio $0.01/0.05 = 0.2$ is uninformative; its AR set is unbounded (Day 65, Exercise 8).\n",
    "\n",
    "**Answer:** report the reduced form (the effect of the guideline itself, 0.01 with SE 0.008) and state that the drug's effect is not identified with useful precision at this cutoff.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 15 · Same bandwidth in both stages\n",
    "\n",
    "Why must the first stage and reduced form use the same bandwidth, kernel and polynomial order?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** The ratio estimates the complier effect only if both jumps are measured on the same units with the same weights.\n",
    "\n",
    "**Step 2.** Different windows would compare different populations (and different bias), so the ratio would not have the LATE interpretation.\n",
    "\n",
    "**Answer:** use the 2SLS implementation within a common window, or a bandwidth selected for the ratio.\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",
    "print(\"Ex 1:\", 6 / .4, \" Ex 2 types:\", (.15, round(1 - .70, 2), round(.70 - .15, 2)), \" Ex 11:\", 2 / -8, \" Ex 12:\", round(.8 / .09, 2), \" Ex 13:\", .04 / .5)\n",
    "\n",
    "# Simulated fuzzy RD with heterogeneous effects\n",
    "rng = np.random.default_rng(76); n = 200_000\n",
    "x = rng.uniform(-1, 1, n); z = (x >= 0).astype(float)\n",
    "typ = rng.choice([\"c\", \"a\", \"n\"], n, p=[.55, .15, .30])\n",
    "d = ((typ == \"a\") | ((typ == \"c\") & (z == 1))).astype(float)\n",
    "gain = np.select([typ == \"c\", typ == \"a\", typ == \"n\"], [3.0, 1.0, 0.5]) + 2 * x        # effects vary with type and x\n",
    "y = 10 + 4 * x + 2 * (typ == \"a\") + d * gain + rng.normal(0, 2, n)\n",
    "h = .2; m = np.abs(x) <= h\n",
    "W = np.column_stack([np.ones(m.sum()), x[m], z[m] * x[m]])\n",
    "def coef_on(v, target):\n",
    "    X = np.column_stack([W, v]); return np.linalg.lstsq(X, target, rcond=None)[0][-1]\n",
    "rho, pi = coef_on(z[m], y[m]), coef_on(z[m], d[m])\n",
    "Xs = np.column_stack([W, d[m]]); Zs = np.column_stack([W, z[m]])\n",
    "Xh = Zs @ np.linalg.lstsq(Zs, Xs, rcond=None)[0]\n",
    "tsls = np.linalg.lstsq(Xh, y[m], rcond=None)[0][-1]\n",
    "print(f\"reduced form {rho:.3f}, first stage {pi:.3f}, ratio {rho / pi:.3f}, 2SLS {tsls:.3f}  (complier effect at cutoff 3.0)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Key takeaways\n",
    "\n",
    "- Fuzzy RD divides the outcome jump by the take-up jump; it is IV with the cutoff indicator as instrument.\n",
    "- It identifies the average effect for compliers at the cutoff, under continuity, monotonicity and exclusion.\n",
    "- Estimate by 2SLS with a common window and controls; plot the first stage and guard against weak jumps."
   ]
  }
 ]
}