*! version 1.0.1 24aug2026

Title

ardldml postestimation -- postestimation tools for ardldml

Syntax

estat absorption, drop(varlist)
[breps(#) seed(#) level(#) mzalt(string) notable]

estat penalty
[, rules(string) projections(string)
lagsgrid(numlist) breps(#) seed(#)]

estat classical
[, order(#) nsim(#) seed(#) levels(numlist)]

estat blocks [, graph name(string) twoway_options]

estat null [, name(string) nograph twoway_options]

predict [type] newvar [if] [in] [, xb | residuals | ec]

All subcommands leave your e() results untouched: the ones that refit
internally hold and restore them.

estat absorption

This is the most important thing in the package to run, and the easiest to
skip.

Residualisation is valid only when the controls remove nuisance stochastic
trends, not the equilibrium relation being tested. If a control is itself part
of the equilibrium system, partialling it out absorbs the very trend the test is
meant to detect, driving the effective integrated count toward zero and
destroying the relation rather than cleaning it. The estimand changes: a
non-rejection then reflects over-absorption, not the absence of a long-run
relationship. That requirement (the paper's Assumption 5, that the nuisance
space does not span the cointegrating relation of interest) cannot be verified
directly. This is the practical substitute.

estat absorption runs the four fits of Definition 2 -- full and reduced
control sets, crossed with the adaptive and the comparison m_Z projection -- and
reports the two gaps

Delta_m = p_plain - p_adaptive

Delta_W = p_full - p_reduced

read together with the stability of the long-run coefficient across the four
fits.

drop(varlist) names the controls omitted from the reduced set.
Required, and the choice is economic: pick the controls most likely to be
cointegrated with the tested relation itself. In the paper's pass-through
application these are money and the oil price.

breps(#) sets the replications per fit; four bootstraps are run, so cost
is roughly four times a single fit. Defaults to whatever the fitted model used.

seed(#) seeds the first fit; the others are offset so the four bootstraps
are independent.

mzalt(string) chooses the comparison arm: plain (default, vanilla
L1) or ols (unpenalised). See point 6 of
ardldml methods for why the default is plain.

How to read it (the paper's Remark 9). A large positive Delta_W -- a
verdict that rejects under the reduced set but not under the full set --
together with a long-run coefficient that is more sharply estimated under the
reduced fit, is evidence that the nuisance space is absorbing part of the tested
relation. Assumption 5 is then locally violated and the reduced-set verdict
is the more credible one. Concordant verdicts across the four fits indicate the
conclusion is not an artefact of over-absorption.

It is a hypothesis-generating device, not a formal test. It has no size and
no power. It tells you where to look.

estat penalty

Sweeps the penalty rule, the m_Z projection and the lag order -- the robustness
grid of the paper's Section 7.5. The paper's own tables show a verdict that
rejects at one penalty and not at another. Reporting a single cell from this
grid is specification search; reporting the grid is the method.

rules(string) penalty rules to try; default low medium high.

projections(string) projections to try; default
adaptive plain ols.

lagsgrid(numlist) short-run lag orders; defaults to the fitted value.

breps(#) draws per cell. Omitted by default, which skips the bootstrap and
makes the sweep fast; supply it when you want a p-value in every cell.

The column to watch is n selected Z, the number of control levels the
m_Z projection retained. It is the empirical counterpart of the effective
integrated count: 0 means nothing was absorbed, so the test sits at the
classical corner and orthogonalisation did nothing; a large value means heavy
absorption. A long-run coefficient that changes sign across this grid is a
warning that the conditioning set, not the data, is driving the answer, and the
command says so explicitly.

estat classical

Runs the classical Pesaran, Shin and Smith (2001) bounds test on the same
sample, as a benchmark that conditions on nothing. All three steps are reported,
because rejecting the joint F alone is not evidence of a level relationship: two
degenerate cases survive it, so the t test on the speed of adjustment and the
Wald test on the long-run coefficients are shown alongside.

The bracket is simulated from the Pesaran-Shin-Smith Table CI
data-generating process at your sample size, not read from a table
calibrated at T = 1000. That is what makes it comparable: for short samples the
published asymptotic bounds are the wrong reference, which is the same finite-
sample concern that motivates the whole method.

order(#) short-run order of the differenced focal regressor; default 1
(contemporaneous term only).

nsim(#) replications for the bracket; default 20000. Tail quantiles settle
slowly, so reduce this only for exploratory work.

levels(numlist) significance levels; default 0.10 0.05 0.01.

Expect the two tests to disagree sometimes. That is the point: a statistic
comfortably above 5.73 may sit below the DML-Bounds critical value once the
integrated nuisance is accounted for.

estat blocks

Reports the h-block cross-fitting partition: each evaluation window, its extent,
and how much sample was left for training after the buffer was removed. The
buffer is what buys the decoupling, but it costs sample -- at most h(K-1)
observations from each training set -- and this makes the trade-off visible
rather than implicit. Add graph to draw it.

Use it before committing to a configuration on a short sample. With no
buffer the training share is 1 - 1/K; each unit of h removes roughly 2h/n more.

estat null

Summarises the stored bootstrap null distribution -- its mean, spread and upper
percentiles against the observed statistic and the critical value -- and plots
it. This is the honest way to see how far the realised null sits from the
tabulated 4.94/5.73 values that do not apply.

nograph suppresses the plot and reports the table only.

predict

predict recomputes the first stage and returns an orthogonalised series.

xb (the default) gives the fitted value of the orthogonalised level
regression.

residuals gives its residual, that is, the part of the residualised
differenced outcome that the residualised levels do not explain.

ec gives the residualised equilibrium error, L.depvar minus theta
times L.focalvar, both taken after the controls are partialled out.
This is the series to plot when you want to look at the estimated long-run
relation -- but only once the test has actually rejected. Under a non-rejection
it is a picture of a relation the data do not support.

All are missing for the first p+1 observations of the estimation sample, which
the design consumes.

Stored results

estat absorption stores in r():

r(delta_m), r(delta_W) the two gaps of Definition 2

r(theta_spread) range of theta across the four fits

r(table) 4 x 8 matrix, one row per fit

r(dropped), r(mzalt) what was dropped, which comparison arm

estat penalty stores in r():

r(table) one row per cell

r(theta_min), r(theta_max) range of theta over the grid

r(sign_flip) 1 if theta changes sign across the grid

estat classical stores in r():

r(F), r(t) the step-1 and step-2 statistics

r(wald), r(wald_p) the step-3 Wald test on theta

r(alpha), r(theta) speed of adjustment, long-run coefficients

r(bounds) simulated bracket, one row per level

r(N), r(k) sample and number of forcing regressors

estat blocks stores r(table); estat null stores
r(p50), r(p95), r(crit) and r(p).

Author

Dr Merwan Roudane

merwanroudane920@gmail.com

https://github.com/merwanroudane