*! version 1.0.0 19aug2026

Title

xttvpivmg postestimation -- Postestimation tools for xttvpivmg

Postestimation commands

The following are available after xttvpivmg:

command

predict fitted values and residuals
using the time-varying mean-group coefficients

xttvpivmg replay the results, optionally at other dates

test, lincom, nlcom operate on the estimates at
e(tref)

estat subcommands, margins and predictnl are not
supported: the model has a different coefficient vector at every date, so the
single e(b) they would use is only one slice of the results.

Syntax for predict

predict [type] newvar [if] [in] [, statistic]

statistic

xb linear prediction using bhat_MG(t) at each observation's own date;
the default

residuals depvar minus the linear prediction

Unlike an ordinary estimation command, the prediction at observation (i,t) uses the
coefficient vector for that date, bhat_MG(t), not a single fixed vector. The
prediction is therefore defined only for dates inside the reported window: rows
outside it, and rows outside e(sample), receive missing values.

Note that this is the mean-group fit. It is not the fit of unit i's own
coefficient path bhat^IV_it, and residuals from it contain the coefficient
heterogeneity e_it as well as the disturbance u_it. That is deliberate: the
heterogeneity is precisely what the standard errors in eq. (17) are built from.

Examples

. xttvpivmg y x1 (x2 = z1 z2), cv

. predict yhat, xb

. predict uhat, residuals

. xtline uhat, overlay legend(off)

Replaying results

Typing xttvpivmg with no arguments redisplays the results without
re-estimating -- useful for looking at other dates or another confidence
level after a slow cross-validated fit.

. xttvpivmg y x1 (x2 = z1 z2), cv // the expensive run

. xttvpivmg, at(1998 2003 2008 2013)

. xttvpivmg, level(90) summary

. xttvpivmg, noheader

at() takes dates in timevar units and each must lie inside the reported
window; summary adds the path-summary table; noheader suppresses the
header block.

Working with the estimated paths

The estimator's real output is three aligned matrices:

e(bmg) nrep x k coefficient paths, columns named after the regressors

e(semg) nrep x k standard errors, same layout

e(tlist) nrep x 1 dates, row-aligned with both of the above

e(bi) (N*nrep) x k per-unit paths, unit-major (only with full)

Row r of e(bmg) is the estimate at date e(tlist)[r,1]. To bring them
into the dataset as variables:

. matrix B = e(bmg)

. matrix S = e(semg)

. matrix D = e(tlist)

. local xn "`e(xnames)'"

. preserve

. clear

. svmat double D, name(date)

. svmat double B, name(b)

. svmat double S, name(se)

. list in 1/5

e(bi) is stacked unit-major: rows 1..nrep are unit 1, rows
nrep+1..2*nrep are unit 2, and so on, with the units in sorted
panelvar order. To pull out unit i's path for regressor j:

. matrix BI = e(bi)

. local nrep = e(nrep)

. local i 3

. matrix path3 = BI[(`=(`i'-1)*`nrep'+1')..(`=`i'*`nrep''), 1...]

Inspecting the per-unit paths is the quickest way to see why a band is wide at
some date: the standard error in eq. (17) is nothing but the dispersion of these N
curves.

test, lincom and nlcom

e(b) and e(V) hold the estimates at a single date, e(tref),
chosen with the tref() option and defaulting to the middle of the reported
window. This exists so that the standard inference commands work:

. xttvpivmg y x1 (x2 = z1 z2), tref(2008)

. test x2 // is the 2008 coefficient zero?

. lincom x1 + x2

. nlcom -_b[x1]/_b[x2]

Two warnings. First, e(V) is diagonal: BMK's eq. (17) does define the
full k x k matrix Sigmahat_e(t), but only its diagonal is used for the reported
standard errors, and only the diagonal is posted here. Tests involving more than
one coefficient at a time therefore ignore their covariance and should be treated
as indicative only.

Second, choosing tref() after seeing the paths is data snooping. If you want
to test a coefficient at a particular date, pick the date for a substantive reason.

Building your own figure

The graph option produces a figure in the style of BMK's Figure 1. To build
your own with full control:

. xttvpivmg y x1 (x2 = z1 z2), cv

. matrix B = e(bmg)

. matrix S = e(semg)

. matrix D = e(tlist)

. local fmt "`e(tsfmt)'"

. preserve

. clear

. svmat double D, name(date)

. svmat double B, name(b)

. svmat double S, name(se)

. format date1 `fmt'

. gen lo = b2 - 1.96*se2

. gen hi = b2 + 1.96*se2

. twoway (rarea lo hi date1, color(navy%20) lwidth(none)) ///

(line b2 date1, lcolor(navy) lwidth(medthick)), ///

yline(0, lcolor(gs8)) legend(off) graphregion(color(white))

. restore

Column j of e(bmg) corresponds to word j of e(xnames); the
constant, when present, is the last column.

Exporting a table

Because the coefficient vector varies by date, the usual
estout/esttab workflow does not apply directly. Export the path
matrices instead:

. matrix R = e(tlist), e(bmg), e(semg)

. preserve

. clear

. svmat double R, name(c)

. export delimited using "tvpaths.csv", replace

. restore

For a journal table at selected dates, xttvpivmg, at(numlist) already
prints exactly that; capture it with log or estout of the replayed
output.

Author

Dr Merwan Roudane

merwanroudane920@gmail.com

https://github.com/merwanroudane

Also see

xttvpivmg, xttvpivmg methods