A Python reproduction of the simulation plots in the slide deck
This report reproduces the data-generating processes and plot structure in ../drafts/slides.pdf. It uses the standalone panel_dgps package in this folder and the AugmentedBalancing estimator in the linked crabbymetrics checkout.
The deck compares five DGP families: strong factors, sparse synthetic-control weights, stationary and integrated time series, weak factors, and mixed factors. Each design has 160 control units, 40 treated units, 40 pre-treatment periods, and 10 post-treatment periods. Treatment effects increase by 0.2 in each post-treatment period.
where contains two scaled trending AR(1) factors. Treated loadings have mean , control loadings have mean , and each loading has unit variance. Thus, gives overlap and gives poor overlap.
Sparse synthetic-control model
Control outcomes follow the same two-factor model. Each treated untreated outcome is an equal-weighted mean of the latent signals from the controls with the largest loading sums, plus independent noise. The active donor share is 10% or 50%.
Time-series model
The stationary design follows
The integrated design applies the same recursion to . The deck sets for controls and for treated units. We use .
Weak and mixed factor models
The weak design uses ten factors and scales the factor signal by 0.2. Five factors trend, and five follow a sine path. The mixed design assigns the trending factors to all treated units and 60 controls. The remaining 100 controls follow the periodic factors.
Raw panel paths
The next plots use the deck dimensions and one fixed draw per design. Gray lines are controls. Blue lines are treated units. The shaded region begins with treatment, and the red line shows the treated-group mean effect.
The augmented estimators need a same-shaped untreated-outcome prediction surface . The report uses four package-compatible nuisance fits:
FE: an additive unit-and-time model fit only on untreated cells;
IFE: iterative rank-two factor imputation that calls InteractiveFixedEffects;
MC: MatrixCompletion with nuclear-norm shrinkage;
H-Ridge: HorizontalPanelRidge, with observed never-treated outcomes retained as the donor surface.
The nuisance fits do not use treated post-treatment outcomes. This rule is essential. The report estimates each surface once per replication, then sends it to each augmented balancing variant.
For residuals , the augmented double-balanced counterfactual is
The heatmap rows correspond to the deck:
unit balancing;
outcome-model imputation;
double balancing;
augmented double balancing with residual-first cohort weights;
augmented double balancing with residual-first individual weights;
augmented double balancing with raw-outcome individual weights;
augmented double balancing with raw-outcome cohort weights.
The simplex losses use scale-aware ridge penalties. If is the control first-difference standard deviation, the report normally sets and . The integrated process with uses and because its high-dimensional individual-target problems otherwise reach the optimizer iteration limit. These fixed rules make the Monte Carlo comparison deterministic. The values are simulation settings, not recommended defaults for applied work.
The document renders with a verification profile by default. It uses the deck dimensions - 160 controls, 40 treated units, 40 pre-treatment periods, and 10 post-treatment periods - with 12 replications. This profile checks every DGP, nuisance model, and estimator combination in a practical render time.
Set AUGBAL_PROFILE=deck before rendering to use the original dimensions and 100 replications:
AUGBAL_PROFILE=deck quarto render balancing-reproduction.qmd
Both profiles use fixed seeds and the same code path.
Each replication sends one panel draw through every outcome model and estimator. RMSE uses the known average treatment effect for that draw. A failed fit remains missing and increments the cell-specific failure count.
Completed Good overlap: a = 0: 12 replications in 3.6 seconds; failed fits=0
Completed Poor overlap: a = 1: 12 replications in 4.3 seconds; failed fits=0
Completed Active controls: 10%: 12 replications in 3.7 seconds; failed fits=0
Completed Active controls: 50%: 12 replications in 3.6 seconds; failed fits=0
Completed Stationary: phi = 0.2: 12 replications in 3.3 seconds; failed fits=0
Completed Stationary: phi = 0.9: 12 replications in 4.8 seconds; failed fits=0
Completed Integrated: phi = 0.2: 12 replications in 5.9 seconds; failed fits=0
Completed Integrated: phi = 0.9: 12 replications in 4.0 seconds; failed fits=0
Completed Good overlap: a = 0: 12 replications in 3.6 seconds; failed fits=0
Completed Poor overlap: a = 1: 12 replications in 3.7 seconds; failed fits=0
Completed Good overlap: a = 0: 12 replications in 3.5 seconds; failed fits=0
Completed Poor overlap: a = 1: 12 replications in 4.0 seconds; failed fits=0
RMSE heatmaps
The cells show RMSE. Blank cells are combinations that the deck does not define. A small F suffix marks the number of failed fits when it is positive. Each family uses one color scale across its panels.
The report is a reproducible implementation of the deck design, not a claim that 12 replications give stable Monte Carlo rankings. Use the deck profile before making numerical comparisons. The verification profile has a narrower purpose: it proves that every DGP, nuisance fit, balancing mode, and plot executes at the original panel dimensions through the public APIs.
The heatmaps also separate two questions that are easy to conflate. balance_on selects the data used to fit weights. The augmentation formula always applies the fitted weights to outcome-model residuals. target selects whether one unit-weight vector matches a cohort mean or whether each treated unit receives its own vector.