DGP Dossier: synth_placebo_heavytail

1. Identity & Status

DGP ID synth_placebo_heavytail
Version 1.3.0
Status experimental
Difficulty (3/5)
Stress Profile  overlap: moderatenoise: heavylinearity: lineareffect: constanttarget: both

2. What This DGP Stresses (Intent)

Intent: The “Infinite Variance Test.” The data generation contains a mixture of Normal and Cauchy noise. Crucially, the Cauchy distribution has no defined mean.

The Scientific Question: “Does the estimator fail when the theoretical expectation \(E[Y]\) is undefined?” This is a lethal stress test for Mean-Based Estimators (OLS, IPW, ATE) which rely on the Central Limit Theorem. Since the mean does not exist, the sample mean will never converge. Only Robust Estimators (e.g., Median/Quantile treatment effects) are theoretically valid here.

3. Identification Assumptions (Explicit)

  • Selection on observables holds.
  • Overlap is moderate (propensity bounded).
  • SUTVA holds.
  • Sharp Null: \(Y_1 \equiv Y_0\).

4. Mathematical Specification

Covariates: \(X_1, X_2, X_3, X_4, X_5 \sim \mathcal{N}(0, 1^2)\) independently.

Outcome (control): \[\mu_0(X) = 1 + X_1 + 0.5 X_2\]

Propensity: \[p(X) = \text{expit}(0.5 X_1 - 0.5 X_2)\]

Treatment effect (sharp null): \[\tau(X) \equiv 0\]

Noise mixture: \[\varepsilon \sim 0.8 \cdot \mathcal{N}(0, 0.5^2) + 0.2 \cdot \text{Cauchy}(0, 1)\]

Mean and variance are undefined due to the Cauchy component.

5. Oracle Truth Definition

  • True ATT is zero by construction.
  • True QST is identically zero on the canonical grid.

6. Visual Diagnostics (n = 5000)

7. Empirical Validation

We validate only the oracle estimator to keep builds fast.

Oracle validation (n=1000, seeds=1:20)
mean_bias rmse
0 0

8. Failure Mode Summary

  • Mean Non-Convergence: Standard estimators (OLS, IPW) will jump erratically as sample size increases, driven by extreme outliers.
  • Finite Sample Breakdown: A single extreme value can pull the estimate arbitrarily far from zero, as the estimator chases a mean that doesn’t exist.

9. Implementation Reference

  • Code: R/dgp-synth-placebo-heavytail.R (v1.3.0)
  • Registry: cs_dgp_registry() entry for synth_placebo_heavytail
  • Oracle: true_att = 0, true_qst = 0

10. Validation Checklist

11. Changelog

  • v1.0 dossier: Initial placebo dossier

Appendix: Implementation

Source code for: dgp_synth_placebo_heavytail_v130

function (n, seed = NULL, include_truth = TRUE, oracle_only = FALSE) 
{
    if (!is.null(seed)) {
        cs_set_rng(seed)
    }
    X1 <- stats::rnorm(n, mean = 0, sd = 1)
    X2 <- stats::rnorm(n, mean = 0, sd = 1)
    X3 <- stats::rnorm(n, mean = 0, sd = 1)
    X4 <- stats::rnorm(n, mean = 0, sd = 1)
    X5 <- stats::rnorm(n, mean = 0, sd = 1)
    mu0 <- 1 + X1 + 0.5 * X2
    tau <- rep(0, n)
    p <- stats::plogis(0.5 * X1 - 0.5 * X2)
    w <- stats::rbinom(n, size = 1L, prob = p)
    mix_ind0 <- stats::rbinom(n, size = 1, prob = 0.8)
    eps <- ifelse(mix_ind0 == 1L, stats::rnorm(n, mean = 0, sd = 0.5), 
        stats::rcauchy(n, location = 0, scale = 1))
    y0 <- mu0 + eps
    y1 <- y0
    if (isTRUE(oracle_only)) {
        return(list(df = tibble::tibble(w = w, y0 = y0, y1 = y1)))
    }
    y <- ifelse(w == 1L, y1, y0)
    true_att <- cs_true_att(structural_te = tau, w = w)
    true_qst <- if (isTRUE(include_truth)) 
        cs_get_oracle_qst("synth_placebo_heavytail", version = "1.3.0")
    else NULL
    out <- list(df = tibble::tibble(y = y, w = w, y0 = y0, y1 = y1, 
        p = p, structural_te = tau, X1 = X1, X2 = X2, X3 = X3, 
        X4 = X4, X5 = X5), true_att = true_att, true_qst = true_qst, 
        meta = list(dgp_id = "synth_placebo_heavytail", version = "1.3.0", 
            type = "synthetic", params = list(n = n, seed = seed), 
            structural_te = tau))
    cs_check_dgp_synthetic(out)
    out
}
<bytecode: 0x5650dab26ec8>
<environment: namespace:CausalStress>