*
* @RobustLMTest
* # list of test variables
*
* Performs a heteroscedasticity-consistent LM test for the orthogonality
* between the residuals from the most recent regression and the input
* test variables. See, for instance, Wooldridge, "Econometric Analysis
* of Cross Section and Panel Data", MIT Press, 2002, page 60.
*
* Options:
*   TITLE=' title for test statistic output '
*
* Revision Schedule
*  07/2005 Written by Tom Doan, Estima
*
procedure RobustLMTest
*
option string title
*
local vect[int] testlist
local integer n ntest
local rect sweepblock weights
local vect zu
local symm cvmat
*
* Get the list of test variables
*
enter(varying) testlist
*
* Compute the cross product matrix including both the regressors X and
* the test variables V.
*
compute n=%eqnsize(0)
cmom %regstart() %regend()
# %reglist() testlist
compute ntest=%ncmom-n
*
* Sweep on the regressors to get the regression coefficients of the test
* variables on the regressors
*
compute sweepblock=%sweeptop(%cmom,n)
*
* Compute the Z'uu'Z matrix with u=%resids and Z=X|V. The final
* components of Z'u (that is, V'u) measure the orthogonality of the test
* variables with u. The rest of the calculations are to compute a robust
* covariance matrix for that.
*
mcov(meanvector=zu) / %resids
# %reglist() testlist
*
* The covariance matrix of the V'u are formed by (V-BX)'uu'(V-BX) where
* B are the projection coefficients of the V's onto the X's. The B
* matrix is the top corner of the swept cross product matrix from above,
* so this can by pre and post-multiplying Z'uu'Z by [-B I] blocks
* matrices.
*
compute weights=%blockglue(||-1.0*%xsubmat(sweepblock,1,n,n+1,n+ntest)|%identity(ntest)||)
compute cvmat=%mqform(%cmom,weights)
*
* Compute the chi-squared statistic. Because zu is computed as the mean,
* we need to scale it up by %nobs.
*
compute %cdstat=%qform(inv(cvmat),%nobs*%xsubvec(zu,n+1,n+ntest))
cdf(title=title) chisqr %cdstat ntest
end

