*! Version 1.11 6/11/09 David Roodman droodman@cgdev.org * * Version 1.11: Made nocons work for first stage too. Thanks to James Feyrer for spotting. * Version 1.10: For instrumented regressions fixed serious problem where X was used instead of Z in calculating * the inner part of the Newey-West sandwich. * Version 1.01: Changed "Noconstant" in syntax command to "noCONStant". * * This is based on ivreg version 5.0.9 and newey version 1.2.9. It can work with * panel data and time series. It can work with or without instruments. In the panel * case, in computing the Newey-West sum, * it zeroes out interaction terms involving different groups. It handles missing * data differently in the cases of panels and of time series. If panels are * unbalanced, FORCE causes interaction terms in the Newey-West sum involving * missing observations to be zeroed out. But in the case of pure time series ivnewey * imitates newey: FORCE causes ivnewey to treat available observations as a * complete, evenly spaced series. program define newey2, eclass sortpreserve version 7.0 local version 05.00.9 if !replay() { local n 0 gettoken lhs 0 : 0, parse(" ,[") match(paren) IsStop `lhs' if `s(stop)' { error 198 } while `s(stop)'==0 { if "`paren'"=="(" { local n = `n' + 1 if `n'>1 { capture noi error 198 di in red `"syntax is "(all instrumented variables = instrument variables)""' exit 198 } gettoken p lhs : lhs, parse(" =") while "`p'"!="=" { if "`p'"=="" { capture noi error 198 di in red `"syntax is "(all instrumented variables = instrument variables)""' di in red `"the equal sign "=" is required"' exit 198 } local end`n' `end`n'' `p' gettoken p lhs : lhs, parse(" =") } tsunab end`n' : `end`n'' tsunab exog`n' : `lhs' } else { local exog `exog' `lhs' } gettoken lhs 0 : 0, parse(" ,[") match(paren) IsStop `lhs' } local 0 `"`lhs' `0'"' tsunab exog : `exog' tokenize `exog' local lhs "`1'" local 1 " " local exog `*' syntax [if] [in] [aw/], LAG(integer) [FIRST hc2 hc3 noCONstant T(string) I(string) FORCE Level(integer $S_level)] if `lag'<0 { di in red `"lag(`lag') invalid"' exit 198 } if "`hc2'`hc3'" != "" { if "`hc2'"!="" { di in red "option `hc2' invalid" } else di in red "option `hc3' invalid" exit 198 } marksample touse quietly { xt_tis `t' local tvar `"`s(timevar)'"' capture xt_iis `i' local ists = (_rc==198) if `ists' { noi display "No panel variable found. Time series assumed." markout `touse' `tvar' `lhs' `exog' `exog1' `end1' Checkt `tvar' `touse' } else { local ivar `"`s(ivar)'"' markout `touse' `tvar' `ivar' `lhs' `exog' `exog1' `end1' xt_Checkt `tvar' `ivar' `touse' } if r(tflag)==2 { noi di in red /* */ `"`tvar' has duplicate values"' exit 198 } if r(tflag)==1 & `lag' > 0 & `"`force'"' == "" { noi di in red /* */ `"`tvar' is not regularly spaced -- use the force option to override"' exit 198 } local depv `lhs' local indv `end1' `exog' if `"`constant'"'==`""' { tempvar CONS gen byte `CONS' = 1 local carg `""' } else { local CONS `""' local carg `"nocons"' if `"`indv'"'==`""' { di in red /* */ `"may not specify noconstant without regressors"' exit 198 } } local indc `"`indv' `CONS'"' tempvar wvar if `"`exp'"'==`""' { gen byte `wvar'=1 local weight `"fweight"' } else { gen double `wvar' = `exp' summ `wvar' if `touse' replace `wvar' = `wvar'/r(mean) if `touse' } local wtexp `"[`weight'=`wvar']"' } Subtract newexog : "`exog1'" "`exog'" /* now check for perfect collinearity in instrument list */ _rmcoll `newexog' local newexog "`r(varlist)'" local endo_ct : word count `end1' local ex_ct : word count `newexog' if `endo_ct' > `ex_ct' { di in red "equation not identified; must have at " /* */ "least as many instruments not in" di in red "the regression as there are " /* */ "instrumented variables" exit 481 } if "`first'"!="" { di in gr _newline "First-stage regressions" di in smcl in gr "{hline 23}" } preserve tokenize `end1' forvalues i = 1/`endo_ct' { if "`first'"!="" { regress ``i'' `exog' `newexog' `wtexp' if `touse', `constant' } else { quietly regress ``i'' `exog' `newexog' `wtexp' if `touse', `constant' } tempvar `i'b ren ``i'' ``i'b' quietly predict double ``i'' if `touse' } display quietly { reg `depv' `indv' if `touse' `wtexp', `carg' if e(N)==0 | e(N)==. { di in red `"no observations"' exit 2000 } local nobs=e(N) local mdf=e(df_m) local tdf=e(df_r) *local rmse=e(rmse) global S_4 `"`indv'"' noi fixnames local xv `"$S_1"' local indc `"$S_2 `CONS'"' local nx $S_3 tempname beta /* scale */ mat `beta' = e(b) forvalues i = 1/`endo_ct' { tempvar `i'i ren ``i'' ``i'i' ren ``i'b' ``i'' } tempvar e predict double `e' if `touse', resid forvalues i = 1/`endo_ct' { ren ``i'' ``i'b' ren ``i'i' ``i'' } * scalar `scale' = sqrt(`rmse') tempvar vt1 vt2 gen double `vt1' = . gen double `vt2' = . tempname ztz tt tx tx2 xtix tp2 tx3 xtiy if `"`weight'"'=="aweight" { local ow `"`wvar'"' } else local ow 1 if !`ists' { tsfill, full sort `ivar' `tvar' tempvar lagflag gen `lagflag' = . } local zv `exog' `exog1' forvalues j = 0/`lag' { if `ists' { local lagflag 1 } else { replace `lagflag' = (`ivar'==`ivar'[_n-`j'])* `touse'[_n-`j'] } local i 1 foreach z of varlist `zv' `CONS' { replace `vt1' = `z'[_n-`j']*`e'* /* */ `e'[_n-`j']*`wvar'[_n-`j']* /* */ `ow' * `lagflag' if `touse' mat vecaccum `tx' = `vt1' `zv' if `touse', `carg' mat `tt' = nullmat(`tt') \ `tx' } mat `tt' = (`tt'+`tt'')*(1-`j'/(1+`lag')) if `j' > 0 { mat `ztz' = `ztz' + `tt' } else { mat `ztz' = `tt' * 0.5 } mat drop `tt' } tempname XZ ZZ V tmp foreach z of varlist `zv' `CONS' { mat vecaccum `tmp' = `z' `indv' if `touse' `wtexp', `carg' mat `XZ' = nullmat(`XZ') , `tmp'' mat vecaccum `tmp' = `z' `zv' if `touse' `wtexp', `carg' mat `ZZ' = nullmat(`ZZ') , `tmp'' } mat `ZZ' = syminv((`ZZ' + `ZZ'')/2) mat `V' = `XZ' * `ZZ' * `XZ'' mat `V' = syminv((`V' + `V'')/2) * `XZ' * `ZZ' mat `V' = `V' * `ztz' * `V'' mat `V' = (`V' + `V'')/2 * `nobs'/`tdf' restore est post `beta' `V', dof(`tdf') obs(`nobs') depname(`depv') esample(`touse') if `"`indv'"'==`""' { est scalar df_m = 0 est scalar df_r = `tdf' est scalar F = . } else { qui test `indv', min est scalar df_m = r(df) est scalar df_r = r(df_r) est scalar F = r(F) } /* Double saves */ global S_E_mdf = e(df_m) global S_E_tdf = e(df_r) global S_E_f = e(F) est local depvar `"`depv'"' est scalar N = `nobs' est scalar lag = `lag' if `lag'==0 { est local vcetype `"Robust"' } else { est local vcetype `"Newey-West"' } est local predict newey2_p if "`weight'"!="" { est local wtype "`weight'" est local wexp `"`exp'"' } est local cmd est local version `version' est local instd `end1' if "`end1'" != "" { est local insts `exog' `newexog' est local model iv } else { est local model ols } est local cmd newey2 /* Double saves */ global S_E_depv `"`e(depvar)'"' global S_E_nobs `"`e(N)'"' global S_E_lag `"`e(lag)'"' global S_E_vce `"`e(vcetype)'"' global S_E_cmd `"`e(newey2)'"' } } else { if `"`e(cmd)'"' != "newey2" { error 301 } if _by() { error 190 } syntax [, Level(integer $S_level)] if `level' < 10 { local level = 10 } if `level' > 99 { local level = 99 } } if e(lag)>0 { local errtype ="Newey-West" } else { local errtype = "robust" } if `"`e(instd)'"'=="" { local regtype ="Regression" } else { local regtype ="IV(2SLS) regression" } #delimit ; di _n in gr "`regtype' with `errtype' standard errors" _col(53) `"Number of obs ="' in yel %10.0f e(N) _n in gr `"maximum lag : "' in ye e(lag) _col(53) in gr `"F("' in gr %3.0f e(df_m) in gr `","' in gr %6.0f e(df_r) in gr `")"' _col(68) `"="' in ye %10.2f e(F) _n /* in gr `"coefficients: "' /* */ in ye `"`e(vcetype)' least squares"' */ _col(53) in gr `"Prob > F = "' in ye %6.4f fprob(e(df_m),e(df_r),e(F)) _n ; #delimit cr est display, level(`level') if `"`e(instd)'"'!="" { di in gr "Instrumented: " _c Disp `e(instd)' di in gr "Instruments: " _c Disp `e(insts)' di in smcl in gr "{hline 78}" } end program define IsStop, sclass /* sic, must do tests one-at-a-time, * 0, may be very large */ if `"`0'"' == "[" { sret local stop 1 exit } if `"`0'"' == "," { sret local stop 1 exit } if `"`0'"' == "if" { sret local stop 1 exit } if `"`0'"' == "in" { sret local stop 1 exit } if `"`0'"' == "" { sret local stop 1 exit } else sret local stop 0 end program define Disp local first "" local piece : piece 1 64 of `"`0'"' local i 1 while "`piece'" != "" { di in gr "`first'`piece'" local first " " local i = `i' + 1 local piece : piece `i' 64 of `"`0'"' } if `i'==1 { di } end /* Remove all tokens in dirt from full */ * Returns "cleaned" full list in cleaned */ program define Subtract /* : */ args cleaned /* macro name to hold cleaned list */ colon /* ":" */ full /* list to be cleaned */ dirt /* tokens to be cleaned from full */ tokenize `dirt' local i 1 while "``i''" != "" { local full : subinstr local full "``i''" "", word all local i = `i' + 1 } tokenize `full' /* cleans up extra spaces */ c_local `cleaned' `*' end program define fixnames tempname b v mat `b' = e(b) mat `v' = e(V) local xnam : colnames(`b') local nx : word count `xnam' tokenize `"`xnam'"' local i 1 while `i' <= `nx' { if `b'[1,`i'] == 0 & `v'[`i',`i'] == 0 { local vnam : word `i' of `xnam' /*noi di in gr _n `"`vnam' "' in blue */ /* */ /*`"dropped due to collinearity"' */ local ``i'' `" "' global S_5 = 1 } local i = `i'+1 } local xnam `"`*'"' local nx : word count `xnam' tokenize `"`xnam'"' if `"``nx''"' == `"_cons"' { local `nx' `""' } global S_1 `"`xnam'"' global S_2 `"`*'"' global S_3 = `nx' end program define Checkt, rclass args tvar touse replace `touse'=. if `touse'==0 ret scalar tflag = 0 sort `touse' `tvar' tempvar tt gen `tt' = `tvar'-`tvar'[_n-1] if `touse'!=. summ `tt', meanonly if r(min) != r(max) { ret scalar tflag = 1 } if r(min) == 0 { ret scalar tflag = 2 } replace `touse'=0 if `touse'==. sort `touse' `tvar' end program define xt_Checkt, rclass args tvar ivar touse replace `touse'=. if `touse'==0 ret scalar tflag = 0 sort `touse' `ivar' `tvar' tempvar tt gen `tt' = `tvar'-`tvar'[_n-1] if `touse'!=. & `ivar'==`ivar'[_n-1] summ `tt', meanonly if r(min) != r(max) { ret scalar tflag = 1 } if r(min) == 0 { ret scalar tflag = 2 } replace `touse'=0 if `touse'==. sort `touse' `ivar' `tvar' end exit