SDID Estimator - Unit and Time Weights
Summary
SDID is computed in four steps (Algorithm 1): (1) set a ridge penalty from the scale of one-period outcome changes; (2) solve a penalised, intercept-augmented synthetic-control problem for unit weights on the simplex; (3) solve the transposed problem — regress each control unit’s post-period average on its pre-period outcomes — for time weights on the simplex; (4) run TWFE DiD weighted by . Equivalently, is a weighted double difference of the four blocks of . The intercepts are what distinguish SDID weights from SC weights: they only need to make trends parallel, not identical, because the fixed effects absorb level gaps.
Overview
Partition the outcome matrix by control/treated rows and pre/post columns:
SC uses to learn how to combine rows (units) to mimic the treated rows. SDID does that and uses to learn how to combine columns (pre-periods) to mimic the post-period columns. The symmetry is the key idea: unit weights are a “vertical regression”, time weights are a “horizontal regression”, and both are fit only on cells that are never treated.
Main Content
Unit weights (eq. 2.1) ^def-sdid-unit-weights
Two differences from Abadie–Diamond–Hainmueller weights: (a) the intercept — the weighted controls need only be parallel to the treated average, since in the final regression absorbs constant gaps; (b) the ridge penalty, following Doudchenko & Imbens (2016), which disperses the weights and makes them unique. With and , (2.1) is exactly an ADH weight choice for .
Regularisation parameter (eq. 2.2) ^def-sdid-zeta
is the standard deviation of first differences among controls in the pre-period — “the size of a typical one-period outcome change” — and is a theoretically motivated scaling (Theorem 1 requires ). No cross-validation is involved.
Time weights (eq. 2.3) ^def-sdid-time-weights
No ridge penalty here (only a numerical for uniqueness, fn. 3). The asymmetry “reflects the fact we allow for correlated observations within time periods for the same unit, but not across units within a time period” beyond the factor structure (p. 7). Interpretation: the weighted average of a control unit’s history should predict its post-period average up to a constant .
Algorithm 1 — SDID ^alg-sdid
Input: , . Output: .
- Compute via (2.2).
- Compute unit weights via (2.1).
- Compute time weights via (2.3).
- Solve the weighted TWFE regression
Covariates (fn. 4): apply SDID to residuals from a regression of on time-varying exogenous .
Weighted double-differencing representation (eqs. 2.4-2.5, 4.3) ^thm-sdid-double-diff
For any , define
Then and . Equivalently, every estimator in the family is
with unit-level “adjusted outcomes”
So the final regression never has to be run as a regression: SDID is four weighted block means.
What the intercepts and fixed effects buy: invariance
Because of , and the two-way fixed effects, is unchanged if for any (§4, p. 20). DiD shares this invariance; SC is invariant to shifts only (fn. 8). This is why SDID does not require the treated unit to lie in the convex hull of control levels — a classic SC failure mode discussed in Synthetic Control Requirements.
What the time weights do
Contrast three conventions for the pre-period baseline (p. 9):
- DiD: all pre-periods equally, .
- Event studies: only the last pre-period (), since coefficients are normalised to — see Event Study Designs and Dynamic Treatment Effects.
- SDID: data-driven. Periods are chosen so that “the weighted average of historical outcomes predict average treatment period outcomes for control units, up to a constant.”
With serially correlated noise, the oracle time weights shrink not toward zero but toward the autoregression vector (eq. 4.9) — the population coefficient from regressing the post-period average error on pre-period errors. This is why SDID can be more precise than DiD even when TWFE is correctly specified: it differences out the predictable part of the post-period noise.
Staggered adoption (Appendix §8)
“With staggered adoption the weighted DID regression approach in SDID does not work directly.” The paper’s fix: for each adoption date , form a block-assignment sub-panel of the never-treated units plus the cohort adopting at ; run SDID on each; average the estimates with weights equal to each sub-panel’s share of treated unit-period cells. (Alternatively split by time periods.) This mirrors the cohort-by-cohort logic of Group-Time Average Treatment Effects.
Examples
The California weights (Appendix §7.2). Time weights put all mass on the last three pre-years:
| Year | DID | SDID |
|---|---|---|
| 1988 | 0.053 | 0.427 |
| 1987 | 0.053 | 0.206 |
| 1986 | 0.053 | 0.366 |
| 1970–1985 | 0.053 each | 0.000 |
Unit weights: SC is sparse — Utah 0.396, Montana 0.232, Nevada 0.204, Connecticut 0.104, New Hampshire 0.045, Colorado 0.013, Delaware 0.004, everything else 0. SDID spreads mass across roughly 30 of 38 states (largest: Nevada 0.124, New Hampshire 0.105, Connecticut 0.078, Delaware 0.070), a consequence of the ridge penalty and the intercept. Figure 1 shows that under DiD and SC a single state (New Hampshire) has very high influence , whereas “SDID does not give any state particularly high influence.”
Code sketch (NumPy/CVXPY; the double-difference form avoids fitting the regression):
import numpy as np, cvxpy as cp
def sdid(Y, N0, T0):
N, T = Y.shape; N1, T1 = N - N0, T - T0
d = np.diff(Y[:N0, :T0], axis=1)
sigma = d.std() # eq. (2.2): divisor N_co (T_pre - 1)
zeta = (N1 * T1) ** 0.25 * sigma
# unit weights: rows = pre-periods, cols = control units
w, w0 = cp.Variable(N0, nonneg=True), cp.Variable()
target = Y[N0:, :T0].mean(axis=0)
cp.Problem(cp.Minimize(cp.sum_squares(w0 + Y[:N0, :T0].T @ w - target)
+ zeta**2 * T0 * cp.sum_squares(w)),
[cp.sum(w) == 1]).solve()
# time weights: rows = control units, cols = pre-periods
l, l0 = cp.Variable(T0, nonneg=True), cp.Variable()
target_t = Y[:N0, T0:].mean(axis=1)
cp.Problem(cp.Minimize(cp.sum_squares(l0 + Y[:N0, :T0] @ l - target_t)
+ (1e-6 * sigma)**2 * N0 * cp.sum_squares(l)),
[cp.sum(l) == 1]).solve()
omega = np.r_[-w.value, np.ones(N1) / N1] # signed unit contrast
lam = np.r_[-l.value, np.ones(T1) / T1] # signed time contrast
return omega @ Y @ lam, w.value, l.value # eq. (4.3)Connections
- Synthetic Control — the special case of the unit-weight problem.
- Synthetic Control Requirements — convex-hull and fit requirements that the intercept relaxes.
- Synthetic Control Extensions — penalised SC and augmented SC; with a linear outcome model constrained to the simplex, augmented SC equals SDID-without-intercept (§6, eq. 6.1).
- Fixed-Effects Model — step 4 is a weighted TWFE regression.
- Covariate Balance and Matching Diagnostics — SDID weights are balancing weights, but for unobserved factors rather than observed covariates (§6, p. 34).