*! version 1.0.2 03jul2026

Copyright

Copyright 2026 Xuanyu Cai and Wenli Xu

Title

diddesign_check -- Diagnostic Tests for Parallel Trends Assumption

Syntax

diddesign_check
depvar
[covariates]
[if] [in]
,
treatment(varname)
time(varname)
{id(varname) | post(varname) [rcs]}
[options]

where covariates specifies optional control variables.

Required
treatment(varname) treatment indicator variable

time(varname) time variable

Data Type (one required)
id(varname) unit identifier for panel data

post(varname) post-treatment indicator for RCS data

Design
design(did|sa) design type; default is did

panel panel data format (default if id() specified)

rcs repeated cross-section format; optional when post() already implies RCS

Test Options
lag(numlist) lag periods for placebo tests; default is lag(1)

nboot(#) number of bootstrap iterations (# >= 2); default is nboot(30)

thres(#) SA design threshold; only valid with design(sa)

Inference
cluster(varname) cluster variable for standard errors; required for RCS data

seed(#) random number seed

Display
quiet suppress bootstrap progress display and quiet-gated placebo diagnostic notes

parallel reserved for future use; currently has no effect

depvar is the outcome variable. Control variables can be specified
directly after depvar in the varlist. covariates supports factor-variable
notation; see fvvarlist. For example, diddesign_check y i.region, ...
automatically expands categorical variable region into dummy variables.

Description

diddesign_check performs diagnostic tests for the parallel trends assumption
in difference-in-differences designs. The command implements placebo tests that
estimate treatment effects in pre-treatment periods where no effect should exist
if parallel trends holds.

The command computes:

1. Placebo estimates: DID estimates using pre-treatment periods only

2. Standardized estimates: Placebo estimates standardized by the control
group outcome standard deviation at the baseline period for comparability

3. Bootstrap standard errors: Standard errors via block bootstrap

4. Equivalence confidence intervals (EqCI): 95% CIs for equivalence testing

Interpreting results:

If the parallel trends assumption holds, placebo estimates should be close to zero.
The equivalence CI provides a way to assess how small the pre-trends are:

- Smaller EqCI bounds provide stronger evidence for parallel trends

- The paper does not impose a universal EqCI cutoff; researchers should use
substantive domain knowledge to judge whether the reported interval is narrow
enough for the application at hand

For standard DID designs (design(did)), placebo tests are computed
directly from pre-treatment periods.

For staggered adoption designs (design(sa)), placebo tests account
for multiple treatment timing groups and compute time-weighted averages.

Options

Required

treatment(varname) specifies the binary treatment indicator variable.
Units with treatment equal to 1 are in the treatment group; units with
treatment equal to 0 are in the control group.

time(varname) specifies the time period variable. This variable may be
numeric or string. String time labels are automatically encoded to numeric
period indices only when that encoding preserves the observed order of
distinct labels in the estimation sample. If labels such as t1,
t2, and t10 would be silently reordered lexicographically or by
their numeric suffixes during encoding, diddesign_check stops with an
error and asks users to recode time() to a numeric or lexically
ordered variable first.

Data Type

One of id() or post() must be specified to indicate the data type:

id(varname) specifies the variable identifying units (individuals,
firms, states, etc.). Required for panel data. When id() is specified,
the command assumes panel data format unless rcs is also specified.
String unit identifiers are automatically encoded to numeric using
egen group().

post(varname) specifies the binary post-treatment indicator variable (0/1).
Required for repeated cross-section (RCS) data. In RCS data, different
individuals are sampled at each time period, so there is no unit tracking.
The treatment() variable serves as the group indicator (treatment group
vs control group), while post() indicates pre- vs post-treatment periods.
Values within the 1e-6 tolerance band around 0 or 1 are canonicalized to the
exact binary values before validation and placebo estimation.
When panel and rcs are both omitted, specifying post()
already makes the command auto-detect the RCS data type; rcs is optional
and only makes that choice explicit.

Design

design(did|sa) specifies the design type. did (default) is for
standard DID with a single treatment time. sa is for staggered adoption
designs with multiple treatment times across units.
Note: SA design only supports panel data; specifying design(sa) with
rcs will result in an error. The current design(sa) implementation
also requires complete and unique id() x time() cells, that is, a
balanced panel with exactly one observation per unit-period, and at least
three distinct time periods so the SA DID/sDID estimators can use the
window.

panel indicates panel data format. This is automatically assumed when
id() is specified without rcs. For SA design, panel is required.

rcs indicates repeated cross-section data format. When specified,
post() is required to identify post-treatment periods. When both
panel and rcs are omitted, post() already implies RCS, so
rcs is optional. The panel and rcs options are mutually
exclusive.

Test Options

lag(numlist) specifies the lag periods for placebo tests. Default is
lag(1), testing parallel trends between periods t-1 and t-2. Multiple
lags can be specified (e.g., lag(1 2 3)) to test multiple pre-treatment
periods. Lag values must be non-negative integers less than the maximum available
pre-treatment periods. Lag values that exceed this limit are automatically
filtered out and a warning is displayed. lag(0) is allowed but compares
the treatment period to the immediately preceding period, so it is reported with
a warning rather than treated as a true placebo test.

nboot(#) specifies the number of bootstrap iterations for standard error
estimation. # must be an integer greater than or equal to 2. Default is
nboot(30). For publication-quality placebo inference, consider using
around 2000 bootstrap iterations to match the empirical applications in
Egami and Yamauchi (2023).

thres(#) specifies the minimum number of treated units required per
period for SA design. Default is thres(2). This option is only allowed
with design(sa); design(did) will reject it.

Inference

cluster(varname) specifies the variable for cluster-robust bootstrap.
If not specified for panel data, clustering defaults to the unit level. For
RCS data, cluster() is required and should identify the
treatment-assignment bootstrap block; the command now rejects RCS runs that
omit cluster().

seed(#) sets the random number seed for reproducibility.

Display

quiet suppresses the bootstrap progress display and the
display-stage placebo diagnostic notes emitted by diddesign_check
that explicitly follow the quiet contract. This is useful when
running the command in batch mode, in loops, or when embedding
diddesign_check in programs. Suppressed warnings include the
interpretive note for lag(0) and warnings about dropped or raw-only
lags. Note that progress display is only shown for SA design
(design(sa)); standard DID does not display progress. Input-validation
or preprocessing notices that occur before this diagnostic display stage
may still appear, including duplicate covariates being removed.

parallel is reserved for future use; currently has no effect.

Stored results

diddesign_check stores the following in e():

Scalars

e(N) number of observations in the posted diagnostic sample represented by e(placebo) and e(sample)

e(n_lags) number of identified lag periods

e(n_boot) number of bootstrap iterations

e(n_boot_valid) number of valid bootstrap iterations

e(n_clusters) number of clusters in the posted union diagnostic sample

e(n_lags_posted) number of placebo lag values posted in e(b) and e(V)

e(level) confidence level used for placebo confidence intervals (90)

e(is_panel) 1 if panel data, 0 if RCS data

Macros

e(cmd) diddesign_check

e(cmdline) command as typed

e(design) design type (did or sa)

e(datatype) data type (panel or rcs)

e(depvar) name of dependent variable

e(treatment) name of treatment variable

e(id) name of unit identifier variable for panel results; empty for RCS results

e(time) name of time variable used to index diagnostic periods

e(post) name of post-treatment indicator variable for RCS results; empty for panel results

e(clustvar) name of cluster variable

e(sample_ifin) stored if/in sample restriction for the diagnostic object; used to verify compatibility with matching estimation results

e(covariates) names of covariate variables using the original model syntax

e(covars) alias of e(covariates) for cross-command compatibility

e(identified_lags) lag values retained in e(placebo) after support checks (including raw-only rows)

e(posted_lags) lag values with standardized placebo estimates posted in e(b) and e(V)

e(raw_only_lags) lag values retained in e(placebo) with raw placebo results only; standardized columns are missing

e(unidentified_lags) requested lag values dropped because placebo inference is not identifiable on either standardized or raw scales

e(properties) b V when e(n_lags_posted) > 0; empty when no standardized placebo lag is posted

Matrices

e(b) posted standardized placebo coefficient vector when e(n_lags_posted) > 0; when e(n_lags_posted)=0, Stata still retains a 1x1 internal placeholder matrix named __no_posted_standardized_lags__ to preserve eclass compatibility, but it is not part of the public inference contract

e(V) variance-covariance matrix of posted standardized placebo estimates when e(n_lags_posted) > 0; when e(n_lags_posted)=0, Stata still retains a 1x1 internal placeholder matrix named __no_posted_standardized_lags__ to preserve eclass compatibility, but it is not part of the public inference contract

e(placebo) placebo test results matrix with columns:

lag: lag value

estimate: standardized placebo estimate

std_error: bootstrap standard error (standardized)

estimate_orig: original (unstandardized) estimate

std_error_orig: bootstrap standard error (original)

EqCI95_LB: 95% equivalence CI lower bound

EqCI95_UB: 95% equivalence CI upper bound

e(trends) trends data matrix for plotting

e(n_boot_valid_lag) lag-specific bootstrap support matrix with columns n_boot_valid_std and n_boot_valid_raw

e(n_clusters_lag) lag-specific cluster support matrix with one column n_clusters (standard DID only)

e(Gmat) treatment timing matrix (SA design only)

Functions

e(sample) marks the posted diagnostic sample backing e(placebo); this is the union of retained placebo support rows, not the full raw command sample

Methods and formulas

Placebo estimation

For lag k, the placebo estimate is computed as:

tau_placebo(k) = DID(t-k, t-k-1)

where DID(t1, t2) is the difference-in-differences estimator comparing periods
t1 and t2. Under parallel trends, tau_placebo(k) should equal zero.

Standardization

The command always computes both standardized and unstandardized placebo
estimates.

Estimates are standardized by the control group outcome standard deviation
at the baseline period (pre-treatment control observations):

tau_std = tau / sd(Y_control_baseline)

where Y_control_baseline is the outcome for control units (Gi=0) at the
baseline time period (It=0). This standardization allows comparison across
different lag periods and outcome variables, providing effect sizes in
standard deviation units (similar to Cohen's d).

Equivalence confidence intervals

The equivalence CI is computed using the TOST (Two One-Sided Tests) method:

90% CI = estimate +/- 1.645 * SE

EqCI95 = (-nu, nu) where nu = max(|90% CI upper|, |90% CI lower|)

This interval reports the smallest symmetric equivalence range supported at the
5% significance level. Researchers should decide whether that range is
substantively negligible for their application.

Bootstrap variance

Standard errors are computed via block bootstrap at the cluster level:

1. Resample clusters with replacement

2. Recompute placebo estimates on bootstrap sample

3. Repeat n_boot times

4. SE = sd(bootstrap estimates)

References

Egami, N. and S. Yamauchi. 2023.
Using Multiple Pretreatment Periods to Improve Difference-in-Differences
and Staggered Adoption Designs.
Political Analysis 31(2): 195-212.
https://doi.org/10.1017/pan.2022.8

Author

Xuanyu Cai

City University of Macau

xuanyuCAI@outlook.com

Wenli Xu

City University of Macau

wlxu@cityu.edu.mo

Also see

Online: diddesign, diddesign_check, diddesign_plot, diddesign_intro