scspill — conceptual spillover network above dark-themed observed-versus-synthetic California and donor spillover plots

scspill — Synthetic control models with spillover effects, in Python

Synthetic control when the treatment leaks: estimate the policy effect and the spillover received by every donor.

scspill is a Python package of synthetic control models with spillover effects. Classical synthetic control assumes the donors are untouched by the treatment; when a policy spills across borders or trade links, that assumption fails and the estimate is biased. Every model here drops it, and every model returns two things classical synthetic control cannot both give you: the effect on the treated unit, purged of contamination, and the spillover effect received by each donor.

One model ships today — sar, the Bayesian spatial-autoregressive method of Sakaguchi & Tagawa (Identification and Bayesian Inference for Synthetic Control Methods with Spillover Effects, The Econometrics Journal), which models the leakage through user-supplied spatial weights, a horseshoe-regularized donor fit, and one estimated spillover intensity \(\rho\). The model catalogue lists it, names the models on the roadmap, and marks plainly which are implemented.

🎯 Estimate

Pick a model, configure once, fit once. Today that model is sar: SCSPILL(config).fit() runs the two-step Bayesian sampler and returns the ATT with credible intervals, the counterfactual path, the posterior of \(\rho\), and a time-by-donor spillover panel.

🔬 Validate

sar ships its article’s appendix machinery as first-class functions: the Geweke joint distribution test of the sampler, prior sensitivity sweeps, and prior predictive checks against nine statistics of the donor panel.

🎲 Simulate

sar’s Monte Carlo engine: plant \(\rho\) and the treatment effect on a lattice, watch classical SCM go wrong under spillovers, and score bias, RMSE, and coverage across estimators.

The models

Model method Reference Status
Bayesian spatial-autoregressive spillover SCM "sar" Sakaguchi & Tagawa (2026), Econometrics Journal Available
SCM with spillover effects "cd" Cao & Dowd (2019, rev. 2026) Planned
Inclusive synthetic control "iscm" Di Stefano & Mellace (2024) Planned
Partial-interference SCG "grossi" Grossi et al. (2025), JRSS-A Planned

The planned rows are a roadmap, not a feature list: they are not implemented and their method names are rejected rather than silently substituted. The model catalogue explains what each would assume, and why having several matters — the assumptions are not nested, so two models bracket the answer.

What a sar fit needs and returns

The treated unit is matched by unconstrained, horseshoe-shrunk synthetic weights \(\alpha\) (donors can be excluded, weighted negatively, or extrapolated — no simplex constraint). Spillovers travel through weights you specify: spatial_w links the treated unit to each donor, spatial_W links donors to each other, and a single scalar \(\rho\) — estimated by random-walk Metropolis inside a Gibbs sampler — scales the whole channel. At \(\rho = 0\) the method collapses exactly to the Bayesian horseshoe synthetic control.

You provide scspill returns
a long panel df (one row per unit-period) att, att_ci — the treatment effect with credible interval
a 0/1 treatment column the counterfactual path with a pointwise credible band
spatial_w, spatial_W — spatial weights by donor label the posterior of \(\rho\) (draws, interval, ESS, acceptance)
optional covariate columns a \((T \times N)\) spillover panel with credible bands per donor
MCMC diagnostics and R-style plot panels

Bundled case studies

  • California Proposition 99 — 39 states, 1970–2000, per-capita cigarette sales, rook-contiguity weights (scspill.data.load_california()): the paper’s tobacco-tax application where the spillover lands on Nevada.
  • The 2011 Sudan secession — 34 African countries, 2000–2015, GDP per capita, bilateral-trade weights (scspill.data.load_sudan()): spillovers travel the trade network to Egypt and Kenya.

Installation

pip install scspill            # NumPy/SciPy backend
pip install "scspill[numba]"   # + JIT-compiled samplers (~10x faster)

At a glance

from scspill import SCSPILL
from scspill.data import load_california

panel = load_california()
result = SCSPILL({**panel.config_kwargs(), "m_iter": 20_000, "burn": 10_000,
                  "seed": 42}).fit()

result.att, result.att_ci          # treatment effect on California
result.rho_hat, result.rho_ci      # spillover intensity
result.spillover_panel["Nevada"]   # the effect received by Nevada
result.plot(kind="panel")          # counterfactual | effect | top spillovers

sar is validated, not just implemented

Every release is cross-validated against the authors’ R replication package (see the validation article and benchmarks/REPORT.md in the repository): the California and Sudan posteriors are matched against the frozen R credible intervals, the Monte Carlo grid against the paper’s Tables 1–2, and the sampler itself passes the Geweke joint distribution test — which also caught, and led us to fix, two internal inconsistencies in the reference implementation’s latent-factor block.

Built on

numpy · scipy · pandas · pydantic · matplotlib · optional numba — and designed to sit beside mlsynth, whose estimator architecture it shares.

Citing

Please cite both the software and the article it implements:

Mendez, C. (2026). Synthetic Control Models with Spillovers in Python (version 0.2.1). https://github.com/quarcs-lab/scspill

Sakaguchi, S., & Tagawa, H. (2026). Identification and Bayesian Inference for Synthetic Control Methods with Spillover Effects. The Econometrics Journal. https://doi.org/10.1093/ectj/utag006

CITATION.cff in the repository carries the same metadata in machine-readable form.

Acknowledgement

The sar model and its original R/C++ implementation are the work of Shosei Sakaguchi and Hayato Tagawa; please cite their article whenever you fit that model. The Python package — an independent port with paper-correct defaults — is written and maintained by Carlos Mendez at the QuaRCS lab.