*! version 0.5.0 02jun2026

Title

xtdyntest -- Specification tests after dynamic panel-data GMM estimation

Contents

Syntax | Description | Options | Stored results | Examples | References | Author

Jump to a subcommand:
csd |
syr |
break |
lee

Syntax

xtdyntest subcommand [, options]

subcommand

csd cross-sectional dependence battery on residuals

syr Sarafidis-Yamagata-Robertson (2009) error-CSD Sargan-difference test

break De Wachter-Tzavalis (2012) structural-break test (known or unknown breakpoint)

lee Lee (2014) generalized-spectral linearity / functional-form test

csd -- cross-sectional dependence tests:

xtdyntest csd [, csd_options]

csd_options

residuals(varname) use varname as the residual series instead of
reconstructing from e(b)

graph draw a heatmap of the pairwise residual correlation matrix
(requires heatplot from SSC)

graphname(string) name for the saved graph (default xtd_csd_heat)

notable suppress the results table

savecorr(name) save the N×N pairwise correlation matrix in name

xtdyntest csd is run after a dynamic panel estimator (see Description).

syr -- Sarafidis-Yamagata-Robertson (2009) test:

xtdyntest syr [, notable]

Run xtdyntest syr after xtdpdgmm or xtabond2.
It re-fits the model with the lagged-dependent-variable GMM instruments removed
and reports the Sargan/Hansen difference statistic (D_DIF2 after difference GMM,
D_SYS2 after system GMM). See Description: syr.

break -- De Wachter-Tzavalis (2012) structural-break test:

xtdyntest break depvar [if] [in] [, at(#)
ar(#) reduced full reps(#) seed(#) trim(#) notable]

break_options

at(#) candidate breakpoint, given as an observed value of the panel
time variable. If omitted, the unknown-breakpoint sup-test is run
instead (sweep over all admissible candidate dates)

ar(#) autoregressive order p of the dynamic model (default ar(1))

full test a break in both the slope coefficients and the fixed
effects (default)

reduced test a break in the fixed effects only

reps(#) number of simulation draws for the sup-test null
distribution (default reps(499), minimum 99; ignored when at() is given)

seed(#) random-number seed for reproducible sup-test p-values
(ignored when at() is given)

trim(#) symmetric trimming fraction of the candidate window for the
sup-test, in [0,0.5) (default trim(0.15); ignored when at() is given)

notable suppress the results table

xtdyntest break is self-contained: it fits its own Arellano-Bond
difference-GMM models (it does not require a prior estimation command). The data
must be xtset. It estimates a pure dynamic AR(p) panel by difference GMM
with standard non-collapsed (GMM-style) level instruments, and reports the
likelihood-ratio-type statistic N(Q2 - Qtau), where Q2 is the
no-break two-step GMM objective (the standard Arellano-Bond Hansen J) and
Qtau is the objective of the model with a break at at(). Qtau drops
the moment conditions of the contaminated differenced equation at the break and
reuses the no-break moment-covariance submatrix as its weight (a shared-weight
Hansen difference / C statistic). Under H0 of no break the statistic is
chi-squared with degrees of freedom equal to the number of omitted moment
conditions plus the number of extra break parameters. See
Description: break.

lee -- Lee (2014) generalized-spectral linearity test:

xtdyntest lee depvar [indepvars] [if] [in] [, residuals(varname)
ar(#) effects(string) pbar(#) lags(#) ngrid(#) notable]

lee_options

residuals(varname) use varname as the residual series (skips
estimation entirely)

ar(#) autoregressive order p of the self-contained linear fit
(default ar(1); used only when residuals are obtained internally)

effects(string) within transform of the residuals: twoway
(default), individual, time, or none

pbar(#) preliminary bandwidth used to compute the data-driven
plug-in (default pbar(4), minimum 2)

lags(#) fix the bandwidth (lag truncation p) at #;
lags(0) (default) requests the data-driven plug-in p0 = c0 T^(1/3)

ngrid(#) number of points in the integration grid on [-3,3]
(default ngrid(31), odd, minimum 11)

notable suppress the results table

xtdyntest lee obtains residuals in one of three ways: from residuals()
if supplied; otherwise from the host estimator via predict when an
estimation is in memory and no indepvars are given (post-estimation default);
otherwise from a self-contained linear dynamic fixed-effects fit of depvar
on its first p lags and any indepvars. See
Description: lee.

Description

xtdyntest provides post-estimation specification tests intended to be run
after dynamic panel-data GMM estimators, including
xtdpdgmm (Kripfganz),
xtabond2 (Roodman), and the official
xtabond/xtdpd/xtdpdsys.

The csd subcommand reports a battery of cross-sectional dependence (CSD)
tests computed on the estimation residuals:

o Pesaran (2004) CD test - valid for large N;

o Friedman (1937) rank test FR;

o Frees (1995) test FRE (normal approximation);

o Breusch & Pagan (1980) LM test - valid for fixed N, large T.

The null hypothesis in every case is that the errors are cross-sectionally
independent. By default the residuals are reconstructed from the stored
coefficient vector as depvar - xb, where xb is built with
matrix score over e(sample). Supply your own residual series with
residuals() (for example, first-difference residuals or a transformed
equation) when the level-equation reconstruction is not what you want.

The statistics are computed natively (in Mata) so the command does not depend on
any other CSD package being installed. Where a bias-corrected CD* is wanted, use
xtcd2 (Ditzen) directly; xtdyntest will call it opportunistically
if it is installed.

syr -- The syr subcommand implements the Sarafidis, Yamagata and
Robertson (2009) test for error cross-sectional dependence in short dynamic panels
estimated by GMM. The idea is that, under a multi-factor error structure, the
instruments based on lagged levels (or lagged differences) of the dependent
variable become invalid, whereas instruments based on the regressors remain
valid. The test is therefore a Sargan/Hansen difference (overidentification)
statistic comparing the full instrument set with the set that excludes the
lagged-dependent-variable instruments:

o D_DIF2 after difference GMM (Arellano-Bond);

o D_SYS2 after system GMM (Blundell-Bond).

Run it after xtdpdgmm or xtabond2.
xtdyntest syr reads e(cmdline), identifies the GMM/IV instrument blocks
that reference the dependent variable (the y-instruments), re-estimates the model
with those blocks dropped, and differences the two overidentification statistics:
D = S(full) - S(restricted), with degrees of freedom equal to the number of
y-instruments removed. Two versions are reported: one based on the two-step
(robust/Hansen) J and one based on the unadjusted Sargan J. The null is
homogeneous error cross-sectional dependence (equivalently, validity of the
lagged-dependent-variable instruments).

Each overidentification statistic is re-optimized on its own instrument set,
following SYR (their Eqs. 27-28). Consequently the value can differ from a host
command's built-in difference-in-Hansen (which reuses the full-model weighting
matrix as a shared-weight C statistic) and, like any such difference, may be
negative in finite samples; a negative difference is truncated at zero for the
reported p-value. The syr subcommand requires xtdpdgmm or xtabond2
because it relies on their GMM machinery and stored e(cmdline); standard
gmm()/iv() instrument syntax is assumed.

break -- The break subcommand implements the De Wachter and
Tzavalis (2012) procedure for detecting a structural break in a linear dynamic
panel data model. Under the null hypothesis the model is a stable AR(p) panel
with individual fixed effects; under the alternative, at a candidate time at()
the slope coefficients and/or the fixed effects shift. Because the individual
intercepts and their changes cannot be estimated consistently with T fixed,
detection is carried out in the Arellano-Bond GMM framework on the first-differenced
equations.

For the no-break model all standard moment conditions E[y_is × Deps_it]=0
(levels as instruments for the differenced equations) are used, giving the two-step
GMM objective Q2, which is exactly the Arellano-Bond Hansen J. For a break
at tau the fixed-effect break introduces a one-time spike in the differenced
equation at t=tau; the moment conditions belonging to that equation are
therefore dropped, and (with full) slope-break interaction regressors are
added. The break objective Qtau reuses the no-break moment-covariance
submatrix as its weighting matrix, so the difference

N(Q2 - Qtau) ~ chi-squared,
df = #(omitted moments) + (dim theta_tau - dim theta_2),

is a shared-weight Hansen difference (C) statistic and is non-negative
asymptotically (De Wachter-Tzavalis Theorem 1). With reduced only a
fixed-effect break is tested (no extra parameters, so df = #omitted moments); with
full a joint slope-and-fixed-effect break is tested (df adds p slope-break
parameters).

The engine is self-contained and uses non-collapsed (GMM-style) level instruments
with minimum lag 2, matching a textbook Arellano-Bond fit; as a check, r(Q2)
and r(df2) reproduce the two-step Hansen J and its df from
xtdpdgmm's difference-GMM estimator on the same series.

Unknown breakpoint (sup-test). When at() is omitted, break
performs the De Wachter-Tzavalis sup-type test for a break at an unknown date.
It computes the pointwise statistic V(tau) = N(Q2 - Qtau) at every
admissible candidate tau in the (symmetrically trimmed) interior of the time
window, and reports the supremum

Vmax = max_tau S(tau)×V(tau)

where S(tau) is the distributional rescaling of eq.(11) that maps each
candidate's marginal chi-squared(df_tau) onto a common reference, so the
maximum is not mechanically dominated by the candidates with the most degrees of
freedom. The estimated break date is the argmax. Because the candidate
statistics are correlated and the components have different df, the sup statistic is
not chi-squared; its null distribution is the limit of DWT Theorem 2,

Vmax ~ max_k S(k)×v'G_k v, v ~ N(0,I),

where the G_k are the idempotent matrices of eq.(25). break forms the
G_k analytically from the no-break moment-covariance matrix and obtains the
p-value by Monte-Carlo simulation of this limit (reps() draws, made
reproducible with seed()). Equivalently the comparison is carried out in
CDF (probability) space, which is invariant to the arbitrary reference
chi-squared used by S(.). The full candidate profile V(tau) is
printed and returned in r(profile).

lee -- The lee subcommand implements the Lee (2014)
individual-specific generalized-spectral derivative test of a linear dynamic
panel data model against unspecified nonlinear alternatives. It tests whether the
errors of the fitted linear model form a martingale difference sequence (m.d.s.) -
equivalently, whether the conditional mean is correctly specified with no neglected
nonlinearity. The test is consistent against a wide class of nonlinear departures
(e.g. threshold, smooth-transition, and Markov-switching dynamics).

Let e_it be the (two-way demeaned) residuals. The test is built from the
empirical-characteristic-function building blocks
sigma_ij(0,v) = (1/(Ti-j)) _t e_it psi_(v), where
psi_it(v) = exp(i×v×e_it) - phi_i(v) and phi_i(v) is the
empirical c.f. of unit i. These measure the dependence between e_it and
nonlinear functions of its own past, summed across lags j with a Bartlett
kernel k(j/p) and integrated over v against the N(0,1) weight on [-3,3].

lee reports all four statistics of Lee (2014), each
->d N(0,1) under H0 and upper-tailed (large positive values reject):
M^a and M^b use the heteroskedasticity-robust centering/scaling
(pooled and unit-averaged forms, eqs 2.11-2.12); M0^a and M0^b use the
i.i.d.-error centering (eqs 2.13-2.14). Lee recommends the robust M^a; the
i.i.d. versions over-reject under conditional heteroskedasticity. The bandwidth
(lag truncation p) is chosen by the data-driven plug-in p0 = c0 T^(1/3)
(eq 5.4) using a preliminary pbar(), or fixed at lags(). Parameter-
estimation uncertainty has no asymptotic impact, so any root-NT-consistent
beta-hat (host residuals, supplied residuals, or the self-contained FE fit)
is valid.

Options

residuals(varname) supplies the residual series directly. When omitted,
xtdyntest reconstructs level-equation residuals from e(b) and
e(depvar) over e(sample).

graph draws a diverging-color heatmap of the N×N pairwise correlation
matrix. Requires heatplot (ssc install heatplot); if it is not
installed the graph is skipped with a note.

graphname(string) sets the name of the saved graph. Default is
xtd_csd_heat.

notable suppresses the printed results table (the stored results in
r() are still set).

savecorr(name) stores the pairwise correlation matrix as a Stata matrix
named name.

break-specific options:

at(#) gives the candidate breakpoint as an observed value of the panel
time variable (e.g. at(1981)). The known-breakpoint Theorem-1 test is
run. If at() is omitted, the unknown-breakpoint sup-test of Theorem
2 is run instead, sweeping over all admissible candidate dates.

ar(#) sets the autoregressive order p of the dynamic model. Default is
ar(1).

full tests a joint break in both the slope coefficients and the fixed
effects (the default). reduced tests a break in the fixed effects only; these
two options are mutually exclusive.

reps(#) sets the number of Monte-Carlo draws used to simulate the sup-test
null distribution (DWT Theorem 2). Default is reps(499); the minimum is 99.
Ignored when at() is supplied.

seed(#) sets the random-number seed so that the simulated sup-test p-value is
reproducible. Ignored when at() is supplied.

trim(#) sets the symmetric fraction of the candidate window trimmed from each
end before taking the supremum (standard practice for sup-type break tests, which
have no power at the sample extremes). Must lie in [0,0.5); default trim(0.15).
Ignored when at() is supplied.

lee-specific options:

residuals(varname) supplies the residual series directly, bypassing
estimation. When omitted, residuals come from the host estimator (via
predict) if one is in memory and no indepvars are given, otherwise from
a self-contained fixed-effects fit of depvar on its first p lags and any
indepvars.

ar(#) sets the autoregressive order p of the self-contained linear fit.
Default is ar(1). Used only when residuals are obtained internally.

effects(string) chooses the within transform applied to the residuals before
testing: twoway (remove unit and time means; the default), individual
(unit means only), time (time means only), or none.

pbar(#) sets the preliminary bandwidth used by the data-driven plug-in for the
final lag truncation. Default is pbar(4) (Lee uses 2, 4, 6); the minimum is 2.

lags(#) fixes the bandwidth (lag truncation p) at #. The default
lags(0) requests the data-driven plug-in p0 = c0 T^(1/3). If the plug-in
inputs are ill-conditioned the bandwidth safely falls back to pbar().

ngrid(#) sets the number of points in the uniform numerical-integration grid
on [-3,3]. Must be odd (so the grid is symmetric about 0) and at least 11.
Default is ngrid(31).

Stored results

xtdyntest csd stores the following in r():

Scalars

r(N) number of cross-sectional units used

r(Tmin), r(Tmax) min/max time periods per unit

r(avgrho) average pairwise correlation

r(avgabsrho) average absolute pairwise correlation

r(CD), r(p_CD) Pesaran CD statistic and p-value

r(FR), r(FR_df), r(p_FR) Friedman statistic, df, p-value

r(FRE), r(FRE_z), r(p_FRE) Frees statistic, z, p-value

r(LM), r(LM_df), r(p_LM) Breusch-Pagan LM, df, p-value

Matrices

r(corr) N×N pairwise residual correlation matrix

Macros

r(host) host estimation command detected

r(cmd) xtdyntest csd

xtdyntest syr stores the following in r():

Scalars

r(D) SYR difference statistic (two-step/Hansen)

r(D_df) degrees of freedom of the difference test

r(p_D) p-value of r(D)

r(D_sargan), r(p_D_sargan) Sargan (unadjusted) difference and p-value

r(S_full), r(S_rest) full / restricted two-step J

r(S_full_u), r(S_rest_u) full / restricted Sargan J

r(df_full), r(df_rest) full / restricted overid df

Macros

r(type) DIF or SYS

r(host) host estimation command

r(rcmd) the restricted (x-only) command that was run

r(cmd) xtdyntest syr

xtdyntest break with at() (known breakpoint) stores the following in
r():

Scalars

r(stat) break statistic N(Q2 - Qtau)

r(df) degrees of freedom of the break test

r(p) p-value of r(stat)

r(Q2), r(df2) no-break GMM objective (Hansen J) and its df

r(Qtau), r(df_tau) break-model objective and its df

r(tau), r(ktau) break time value and its grid position

r(N), r(T) units and number of time periods on the grid

r(M), r(M_tau) moment counts, no-break / break model

r(ar) autoregressive order used

Macros

r(test) pointwise (known break)

r(model) full or reduced

r(host) (self-contained)

r(cmd) xtdyntest break

xtdyntest break without at() (unknown-breakpoint sup-test) stores
the following in r():

Scalars

r(stat) sup statistic Vmax (on the reference chi-squared(1) scale)

r(p) simulated p-value of the sup statistic

r(tau), r(ktau) estimated break time value and its grid position

r(stat_b), r(df_b) pointwise V and df at the estimated break

r(Q2), r(df2) no-break GMM objective (Hansen J) and its df

r(ntau) number of candidate breakpoints swept

r(reps) number of simulation draws used

r(N), r(T) units and number of time periods on the grid

r(M) no-break moment count

r(ar) autoregressive order used

Matrices

r(profile) ntau×5 candidate profile: position, time, V(tau), df, scaled V

Macros

r(test) sup (unknown break)

r(model) full or reduced

r(host) (self-contained)

r(cmd) xtdyntest break

xtdyntest lee stores the following in r():

Scalars

r(Ma), r(p_Ma) robust pooled statistic M^a and its (upper-tailed) p-value

r(Mb), r(p_Mb) robust unit-averaged statistic M^b and p-value

r(M0a), r(p_M0a) i.i.d. pooled statistic M0^a and p-value

r(M0b), r(p_M0b) i.i.d. unit-averaged statistic M0^b and p-value

r(stat), r(p) aliases for the recommended M^a and its p-value

r(p0) bandwidth (lag truncation p) actually used

r(pbar) preliminary bandwidth used by the plug-in

r(N), r(T) units and maximum time periods per unit

r(M) number of integration-grid points

r(ar) autoregressive order of the self-contained fit

Matrices

r(stats) 4×2 matrix (rows Ma Mb M0a M0b; cols stat p)

Macros

r(test) generalized-spectral (linearity)

r(bw) plug-in or fixed

r(effects) within transform used (twoway/individual/time/none)

r(host) residual source / host estimator

r(cmd) xtdyntest lee

Examples

Arellano-Bond data, system GMM with xtdpdgmm:

. webuse abdata

. xtdpdgmm L(0/1).n w k, gmm(n, lag(2 4) collapse) model(diff) two vce(r)

. xtdyntest csd

. xtdyntest csd, graph savecorr(C)

After xtabond2:

. xtabond2 n L.n w k, gmm(L.n, collapse) iv(w k) twostep robust noleveleq

. xtdyntest csd

Using your own residual series:

. xtdyntest csd, residuals(myres)

SYR error-CSD test after difference GMM (D_DIF2):

. xtdpdgmm L(0/1).n w k, gmm(n, lag(2 4) collapse model(diff)) gmm(w k, lag(1 3) collapse model(diff)) two vce(r)

. xtdyntest syr

SYR error-CSD test after system GMM (D_SYS2):

. xtdpdgmm L(0/1).n w k, gmm(n, lag(2 4) collapse model(diff)) gmm(n, lag(1 1) collapse model(level)) gmm(w k, lag(1 3) collapse) gmm(w k, lag(0 0) collapse model(level)) two vce(r)

. xtdyntest syr

De Wachter-Tzavalis structural-break test, fixed-effect break at 1981:

. webuse abdata

. xtset id year

. xtdyntest break n, at(1981) ar(1) reduced

Joint slope-and-fixed-effect break (full), AR(1):

. xtdyntest break n, at(1981) full

Unknown-breakpoint sup-test (omit at()), reduced break, reproducible:

. xtdyntest break n, ar(1) reduced reps(499) seed(12345)

Inspect the candidate profile and the estimated break date:

. matrix list r(profile)

. display "break at " r(tau) ", p = " r(p)

Lee (2014) linearity test, self-contained AR(1) fixed-effects fit:

. webuse abdata

. xtset id year

. xtdyntest lee n, ar(1)

Self-contained fit with extra regressors and AR(2) dynamics:

. xtdyntest lee n w k, ar(2)

Post-estimation: test the residuals of a fitted model directly:

. xtreg n L.n w k, fe

. xtdyntest lee n

Fixed bandwidth and your own residual series:

. xtdyntest lee n, residuals(myres) lags(4)

Read the four statistics from the returned matrix:

. matrix list r(stats)

References

Breusch, T. S., and A. R. Pagan. 1980. The Lagrange multiplier test and its
applications to model specification in econometrics.
Review of Economic Studies 47: 239-253.

De Hoyos, R. E., and V. Sarafidis. 2006. Testing for cross-sectional dependence
in panel-data models. Stata Journal 6: 482-496.

De Wachter, S., and E. Tzavalis. 2012. Detection of structural breaks in linear
dynamic panel data models. Computational Statistics & Data Analysis 56:
3020-3034.

Frees, E. W. 1995. Assessing cross-sectional correlation in panel data.
Journal of Econometrics 69: 393-414.

Friedman, M. 1937. The use of ranks to avoid the assumption of normality implicit
in the analysis of variance. Journal of the American Statistical Association
32: 675-701.

Lee, Y. 2014. Testing a linear dynamic panel data model against nonlinear
alternatives. Journal of Econometrics 178: 146-166.

Pesaran, M. H. 2004. General diagnostic tests for cross section dependence in
panels. Cambridge Working Papers in Economics No. 0435.

Sarafidis, V., T. Yamagata, and D. Robertson. 2009. A test of cross section
dependence for a linear dynamic panel model with regressors.
Journal of Econometrics 148: 149-161.

Author

Dr Merwan Roudane

github.com/merwanroudane