Untitled diff
81 removals
745 lines
77 additions
738 lines
*! ivreghdfe 1.0.0 07jul2018
*! this just adds absorb() to this code:
*! ivreg2 4.1.10 9Feb2016
*! ivreg2 4.1.10 9Feb2016
*! authors cfb & mes
*! authors cfb & mes
*! see end of file for version comments
*! see end of file for version comments
* Variable naming:
* Variable naming:
* lhs = LHS endogenous
* lhs = LHS endogenous
* endo = X1, RHS endogenous (instrumented) = #K1
* endo = X1, RHS endogenous (instrumented) = #K1
* inexog = X2 = Z2 = included exogenous (instruments) = #K2 = #L2
* inexog = X2 = Z2 = included exogenous (instruments) = #K2 = #L2
* exexog = Z1 = excluded exogenous (instruments) = #L1
* exexog = Z1 = excluded exogenous (instruments) = #L1
* iv = {inexog exexog} = all instruments
* iv = {inexog exexog} = all instruments
* rhs = {endo inexog} = RHS regressors
* rhs = {endo inexog} = RHS regressors
* no 0 or 1 at end of varlist means original varlist but after expansion of FV and TS vars
* no 0 or 1 at end of varlist means original varlist but after expansion of FV and TS vars
* 0 at the end of the name means the varlist after duplicates removed and collinearities/omitteds marked
* 0 at the end of the name means the varlist after duplicates removed and collinearities/omitteds marked
* 1 means the same as 0 but after omitted vars dropped and extraneous FV operators "o", "b" and "n" removed.
* 1 means the same as 0 but after omitted vars dropped and extraneous FV operators "o", "b" and "n" removed.
* 0, 1 etc. also apply to _ct variables that are counts of these varlists
* 0, 1 etc. also apply to _ct variables that are counts of these varlists
* dofminus is large-sample adjustment (e.g., #fixed effects)
* dofminus is large-sample adjustment (e.g., #fixed effects)
* sdofminus is small-sample adjustment (e.g., #partialled-out regressors)
* sdofminus is small-sample adjustment (e.g., #partialled-out regressors)
if c(version) < 12 & c(version) >= 9 {
if c(version) < 12 & c(version) >= 9 {
* livreg2 Mata library.
* livreg2 Mata library.
* Ensure Mata library is indexed if new install.
* Ensure Mata library is indexed if new install.
* Not needed for Stata 12+ since ssc.ado does this when installing.
* Not needed for Stata 12+ since ssc.ado does this when installing.
capture mata: mata drop m_calckw()
capture mata: mata drop m_calckw()
capture mata: mata drop m_omega()
capture mata: mata drop m_omega()
capture mata: mata drop ms_vcvorthog()
capture mata: mata drop ms_vcvorthog()
capture mata: mata drop s_vkernel()
capture mata: mata drop s_vkernel()
capture mata: mata drop s_cdsy()
capture mata: mata drop s_cdsy()
mata: mata mlib index
mata: mata mlib index
}
}
*********************************************************************************
*********************************************************************************
***************************** PARENT IVREG2 *************************************
***************************** PARENT IVREG2 *************************************
****************** FORKS TO EXTERNAL IVREG2S IF CALLER < 11 *********************
****************** FORKS TO EXTERNAL IVREG2S IF CALLER < 11 *********************
*********************************************************************************
*********************************************************************************
* Parent program, forks to versions as appropriate after version call
* Parent program, forks to versions as appropriate after version call
* Requires byable(onecall)
* Requires byable(onecall)
program define ivreg2, eclass byable(onecall) /* properties(svyj) */ sortpreserve
program define ivreghdfe, eclass byable(onecall) /* properties(svyj) */ sortpreserve
local lversion 04.1.10
local lversion 04.1.10
* Minimum of version 8 required for parent program (earliest ivreg2 is ivreg28)
* Minimum of version 8 required for parent program (earliest ivreg2 is ivreg28)
version 8
version 8
* Replay = no arguments before comma
* Replay = no arguments before comma
if replay() {
if replay() {
* Call to ivreg2 will either be for version, in which case there should be no other arguments,
* Call to ivreg2 will either be for version, in which case there should be no other arguments,
* or a postestimation call, in which case control should pass to main program.
* or a postestimation call, in which case control should pass to main program.
syntax [, VERsion * ]
syntax [, VERsion * ]
if "`version'"~="" & "`options'"=="" {
if "`version'"~="" & "`options'"=="" {
* Call to ivreg2 is for version
* Call to ivreg2 is for version
di in gr "`lversion'"
di in gr "`lversion'"
ereturn clear
ereturn clear
ereturn local version `lversion'
ereturn local version `lversion'
exit
exit
}
}
else if "`version'"~="" & "`options'"~="" {
else if "`version'"~="" & "`options'"~="" {
* Improper use of version option
* Improper use of version option
di as err "invalid syntax - cannot combine version with other options"
di as err "invalid syntax - cannot combine version with other options"
exit 198
exit 198
}
}
else {
else {
* Postestimation call, so put `options' macro (i.e. *) back into `0' macro with preceding comma
* Postestimation call, so put `options' macro (i.e. *) back into `0' macro with preceding comma
local 0 `", `options'"'
local 0 `", `options'"'
}
}
}
}
* replay can't be combined with by
* replay can't be combined with by
if replay() & _by() {
if replay() & _by() {
di as err "invalid syntax - cannot use by with replay"
di as err "invalid syntax - cannot use by with replay"
exit 601
exit 601
}
}
* Handling of by. ivreg2x programs are byable(recall), so must set prefix for them.
* Handling of by. ivreg2x programs are byable(recall), so must set prefix for them.
if _by() {
if _by() {
local BY `"by `_byvars'`_byrc0':"'
local BY `"by `_byvars'`_byrc0':"'
}
}
* If calling version is < 11, pass control to earlier version
* If calling version is < 11, pass control to earlier version
* Note that this means calls from version 11.0 will not go to legacy version
* Note that this means calls from version 11.0 will not go to legacy version
* but will fail requirement of version 11.2 in main code.
* but will fail requirement of version 11.2 in main code.
if _caller() < 11 {
if _caller() < 11 {
local ver = round(_caller())
local ver = round(_caller())
local ivreg2cmd ivreg2`ver'
local ivreg2cmd ivreg2`ver'
* If replay, change e(cmd) macro to name of legacy ivreg2 before calling it, then change back
* If replay, change e(cmd) macro to name of legacy ivreg2 before calling it, then change back
* Note by not allowed with replay; caught above so prefix not needed here.
* Note by not allowed with replay; caught above so prefix not needed here.
if replay() {
if replay() {
ereturn local cmd "`ivreg2cmd'"
ereturn local cmd "`ivreg2cmd'"
`ivreg2cmd' `0'
`ivreg2cmd' `0'
ereturn local cmd "ivreg2"
ereturn local cmd "ivreg2"
}
}
else {
else {
* If not replay, call legacy ivreg2 and then add macros
* If not replay, call legacy ivreg2 and then add macros
`BY' `ivreg2cmd' `0'
`BY' `ivreg2cmd' `0'
ereturn local cmd "ivreg2"
ereturn local cmd "ivreghdfe"
ereturn local ivreg2cmd "`ivreg2cmd'"
ereturn local ivreg2cmd "`ivreg2cmd'"
ereturn local version `lversion'
ereturn local version `lversion'
ereturn local predict ivreg2_p
ereturn local predict ivreg2_p
}
}
exit
exit
}
}
// Version is 11 or above.
// Version is 11 or above.
// Pass control to current estimation program ivreg211.
// Pass control to current estimation program ivreg211.
if replay() {
if replay() {
ivreg211 `0'
ivreg211 `0'
}
}
// If not replay, call ivreg211 and then add macros
// If not replay, call ivreg211 and then add macros
else {
else {
`BY' ivreg211 `0'
`BY' ivreg211 `0'
ereturn local cmd "ivreg2"
cap mata: mata drop HDFE // prefix ivreg211 call with capture?
ereturn local ivreg2cmd "ivreg2"
cap mata: mata drop hdfe_residuals
ereturn local cmd "ivreghdfe"
ereturn local ivreg2cmd "ivreghdfe"
ereturn local version `lversion'
ereturn local version `lversion'
ereturn local predict ivreg2_p
ereturn local predict ivreg2_p
if (e(N_hdfe)!= .) ereturn local predict reghdfe_p
}
}
end
end
*********************************************************************************
*********************************************************************************
*************************** END PARENT IVREG2 ***********************************
*************************** END PARENT IVREG2 ***********************************
*********************************************************************************
*********************************************************************************
********************* EXIT IF STATA VERSION < 11 ********************************
********************* EXIT IF STATA VERSION < 11 ********************************
* When do file is loaded, exit here if Stata version calling program is < 11.
* When do file is loaded, exit here if Stata version calling program is < 11.
* Prevents loading of rest of program file (could cause earlier Statas to crash).
* Prevents loading of rest of program file (could cause earlier Statas to crash).
if c(stata_version) < 11 {
if c(stata_version) < 11 {
exit
exit
}
}
******************** END EXIT IF STATA VERSION < 11 *****************************
******************** END EXIT IF STATA VERSION < 11 *****************************
*********************************************************************************
*********************************************************************************
***************** BEGIN MAIN IVREG2 ESTIMATION CODE *****************************
***************** BEGIN MAIN IVREG2 ESTIMATION CODE *****************************
*********************************************************************************
*********************************************************************************
* Main estimation program
* Main estimation program
program define ivreg211, eclass byable(recall) sortpreserve
program define ivreg211, eclass byable(recall) sortpreserve
version 11.2
version 11.2
local ranktestversion 01.3.02
local ranktestversion 01.3.02
local ivreg2cmd "ivreg211" // actual command name
local ivreg2cmd "ivreg211" // actual command name
local ivreg2name "ivreg2" // name used in command line and for default naming of equations etc.
local ivreg2name "ivreg2" // name used in command line and for default naming of equations etc.
local ranktestcmd "ranktest"
local ranktestcmd "ranktest"
if replay() {
if replay() {
syntax [, ///
syntax [, ///
FIRST FFIRST RF SFIRST ///
FIRST FFIRST RF SFIRST ///
dropfirst droprf dropsfirst ///
dropfirst droprf dropsfirst ///
Level(integer $S_level) ///
Level(integer $S_level) ///
NOHEader NOFOoter ///
NOHEader NOFOoter ///
EForm(string) PLUS ///
EForm(string) PLUS ///
NOOMITTED vsquish noemptycells ///
NOOMITTED vsquish noemptycells ///
baselevels allbaselevels ///
baselevels allbaselevels ///
VERsion ///
VERsion ///
]
]
if "`version'" != "" & "`first'`ffirst'`rf'`noheader'`nofooter'`dropfirst'`droprf'`eform'`plus'" != "" {
if "`version'" != "" & "`first'`ffirst'`rf'`noheader'`nofooter'`dropfirst'`droprf'`eform'`plus'" != "" {
di as err "option version not allowed"
di as err "option version not allowed"
error 198
error 198
}
}
if "`version'" != "" {
if "`version'" != "" {
di in gr "`lversion'"
di in gr "`lversion'"
ereturn clear
ereturn clear
ereturn local version `lversion'
ereturn local version `lversion'
exit
exit
}
}
if `"`e(cmd)'"' != "ivreg2" {
if `"`e(cmd)'"' != "ivreghdfe" {
error 301
error 301
}
}
// Set display options
// Set display options
local dispopt eform(`eform') `noomitted' `vsquish' `noemptycells' `baselevels' `allbaselevels'
local dispopt eform(`eform') `noomitted' `vsquish' `noemptycells' `baselevels' `allbaselevels'
// On replay, set flag so saved eqns aren't dropped
// On replay, set flag so saved eqns aren't dropped
if "`e(firsteqs)'" != "" & "`dropfirst'" == "" {
if "`e(firsteqs)'" != "" & "`dropfirst'" == "" {
local savefirst "savefirst"
local savefirst "savefirst"
}
}
if "`e(rfeq)'" != "" & "`droprf'" == "" {
if "`e(rfeq)'" != "" & "`droprf'" == "" {
local saverf "saverf"
local saverf "saverf"
}
}
if "`e(sfirsteq)'" != "" & "`dropsfirst'" == "" {
if "`e(sfirsteq)'" != "" & "`dropsfirst'" == "" {
local savesfirst "savesfirst"
local savesfirst "savesfirst"
}
}
// On replay, re-display collinearities and duplicates messages
// On replay, re-display collinearities and duplicates messages
DispCollinDups
DispCollinDups
}
}
else {
else {
// MAIN CODE BLOCK
// MAIN CODE BLOCK
local cmdline `ivreg2name' `0' // `0' rather than `*' in case of any "s in string
local cmdline `ivreg2name' `0' // `0' rather than `*' in case of any "s in string
// Confirm ranktest is installed (necessary component).
// Confirm ranktest is installed (necessary component).
checkversion_ranktest `ranktestcmd' `ranktestversion'
checkversion_ranktest `ranktestcmd' `ranktestversion'
// Start parsing
// Start parsing
syntax [anything(name=0)] [if] [in] [aw fw pw iw/] [, ///
syntax [anything(name=0)] [if] [in] [aw fw pw iw/] [, ///
NOID NOCOLLIN ///
NOID NOCOLLIN ///
FIRST FFIRST SAVEFIRST SAVEFPrefix(name) ///
FIRST FFIRST SAVEFIRST SAVEFPrefix(name) ///
RF SAVERF SAVERFPrefix(name) ///
RF SAVERF SAVERFPrefix(name) ///
SFIRST SAVESFIRST SAVESFPrefix(name) ///
SFIRST SAVESFIRST SAVESFPrefix(name) ///
SMall NOConstant ///
SMall NOConstant ///
Robust CLuster(varlist) kiefer dkraay(integer 0) ///
Robust CLuster(varlist) kiefer dkraay(integer 0) ///
BW(string) kernel(string) center ///
BW(string) kernel(string) center ///
GMM GMM2s CUE ///
GMM GMM2s CUE ///
LIML COVIV FULLER(real 0) Kclass(real 0) ///
LIML COVIV FULLER(real 0) Kclass(real 0) ///
ORTHOG(string) ENDOGtest(string) REDundant(string) ///
ORTHOG(string) ENDOGtest(string) REDundant(string) ///
PARTIAL(string) FWL(string) ///
PARTIAL(string) FWL(string) ///
Absorb(string) ///
Level(integer $S_level) ///
Level(integer $S_level) ///
NOHEader NOFOoter NOOUTput ///
NOHEader NOFOoter NOOUTput ///
bvclean NOOMITTED omitted vsquish noemptycells ///
bvclean NOOMITTED omitted vsquish noemptycells ///
baselevels allbaselevels ///
baselevels allbaselevels ///
title(string) subtitle(string) ///
title(string) subtitle(string) ///
DEPname(string) EForm(string) PLUS ///
DEPname(string) EForm(string) PLUS ///
Tvar(varname) Ivar(varname) ///
Tvar(varname) Ivar(varname) ///
B0(string) SMATRIX(string) WMATRIX(string) ///
B0(string) SMATRIX(string) WMATRIX(string) ///
sw psd0 psda useqr ///
sw psd0 psda useqr ///
dofminus(integer 0) sdofminus(integer 0) ///
dofminus(integer 0) sdofminus(integer 0) ///
NOPARTIALSMALL ///
NOPARTIALSMALL ///
fvall fvsep ///
fvall fvsep ///
]
]
if (`"`absorb'"' != "") {
// ensure reghdfe is installed
capture which reghdfe
if c(rc) {
di as err "Error: must have reghdfe installed"
di as err "To install, from within Stata type " _c
//di in smcl "{stata ssc install reghdfe :ssc install reghdfe}"
loc url "https://github.com/sergiocorreia/reghdfe/raw/version-4/src/"
di in smcl `"{stata `"net install reghdfe, from(`url')"':net install reghdfe, from(`url')}"'
exit 601
}
cap reghdfe, requirements // ensure ftools, moresyntax, etc. are installed
if (c(rc)) reghdfe, requirements
reghdfe, check // ensure the .mlib exists
// absorb implies...
local small small
local noconstant noconstant
local nopartialsmall
}
// Parse after clearing any sreturn macros (can be left behind in Stata 11)
// Parse after clearing any sreturn macros (can be left behind in Stata 11)
sreturn clear
sreturn clear
ivparse `0', ivreg2name(`ivreg2name') /// needed for some options
ivparse `0', ivreg2name(`ivreg2name') /// needed for some options
partial(`partial') ///
partial(`partial') ///
fwl(`fwl') /// legacy option
fwl(`fwl') /// legacy option
orthog(`orthog') ///
orthog(`orthog') ///
endogtest(`endogtest') ///
endogtest(`endogtest') ///
redundant(`redundant') ///
redundant(`redundant') ///
depname(`depname') ///
depname(`depname') ///
`robust' ///
`robust' ///
cluster(`cluster') ///
cluster(`cluster') ///
bw(`bw') ///
bw(`bw') ///
kernel(`kernel') ///
kernel(`kernel') ///
dkraay(`dkraay') ///
dkraay(`dkraay') ///
`center' ///
`center' ///
`kiefer' ///
`kiefer' ///
`sw' ///
`sw' ///
`noconstant' ///
`noconstant' ///
tvar(`tvar') ///
tvar(`tvar') ///
ivar(`ivar') ///
ivar(`ivar') ///
`gmm2s' ///
`gmm2s' ///
`gmm' /// legacy option, produces error message
`gmm' /// legacy option, produces error message
`cue' ///
`cue' ///
`liml' ///
`liml' ///
fuller(`fuller') ///
fuller(`fuller') ///
kclass(`kclass') ///
kclass(`kclass') ///
b0(`b0') ///
b0(`b0') ///
wmatrix(`wmatrix') ///
wmatrix(`wmatrix') ///
`noid' ///
`noid' ///
`savefirst' ///
`savefirst' ///
savefprefix(`savefprefix') ///
savefprefix(`savefprefix') ///
`saverf' ///
`saverf' ///
saverfprefix(`saverfprefix') ///
saverfprefix(`saverfprefix') ///
`savesfirst' ///
`savesfirst' ///
savesfprefix(`savesfprefix') ///
savesfprefix(`savesfprefix') ///
dofminus(`dofminus') ///
dofminus(`dofminus') ///
`psd0' ///
`psd0' ///
`psda' ///
`psda' ///
`nocollin' ///
`nocollin' ///
`useqr' ///
`useqr' ///
`bvclean' ///
`bvclean' ///
eform(`eform') ///
eform(`eform') ///
`noomitted' ///
`noomitted' ///
`vsquish' ///
`vsquish' ///
`noemptycells' ///
`noemptycells' ///
`baselevels' ///
`baselevels' ///
`allbaselevels'
`allbaselevels'
// varlists are unexpanded; may be empty
// varlists are unexpanded; may be empty
local lhs `s(lhs)'
local lhs `s(lhs)'
local depname `s(depname)'
local depname `s(depname)'
local endo `s(endo)'
local endo `s(endo)'
local inexog `s(inexog)'
local inexog `s(inexog)'
local exexog `s(exexog)'
local exexog `s(exexog)'
local partial `s(partial)'
local partial `s(partial)'
local cons =s(cons)
local cons =s(cons)
local partialcons =s(partialcons)
local partialcons =s(partialcons)
local tvar `s(tvar)'
local tvar `s(tvar)'
local ivar `s(ivar)'
local ivar `s(ivar)'
local tdelta `s(tdelta)'
local tdelta `s(tdelta)'
local tsops =s(tsops)
local tsops =s(tsops)
local fvops =s(fvops)
local fvops =s(fvops)
local robust `s(robust)'
local robust `s(robust)'
local cluster `s(cluster)'
local cluster `s(cluster)'
local bw =`s(bw)' // arrives as string but return now as number
local bw =`s(bw)' // arrives as string but return now as number
local bwopt `s(bwopt)'
local bwopt `s(bwopt)'
local kernel `s(kernel)' // also used as flag for HAC estimation
local kernel `s(kernel)' // also used as flag for HAC estimation
local center =`s(center)' // arrives as string but now boolean
local center =`s(center)' // arrives as string but now boolean
local kclassopt `s(kclassopt)'
local kclassopt `s(kclassopt)'
local fulleropt `s(fulleropt)'
local fulleropt `s(fulleropt)'
local liml `s(liml)'
local liml `s(liml)'
local noid `s(noid)' // can also be triggered by b0(.) option
local noid `s(noid)' // can also be triggered by b0(.) option
local useqr =`s(useqr)' // arrives as string but now boolean; nocollin=>useqr
local useqr =`s(useqr)' // arrives as string but now boolean; nocollin=>useqr
local savefirst `s(savefirst)'
local savefirst `s(savefirst)'
local savefprefix `s(savefprefix)'
local savefprefix `s(savefprefix)'
local saverf `s(saverf)'
local saverf `s(saverf)'
local saverfprefix `s(saverfprefix)'
local saverfprefix `s(saverfprefix)'
local savesfirst `s(savesfirst)'
local savesfirst `s(savesfirst)'
local savesfprefix `s(savesfprefix)'
local savesfprefix `s(savesfprefix)'
local psd `s(psd)' // triggered by psd0 or psda
local psd `s(psd)' // triggered by psd0 or psda
local dofmopt `s(dofmopt)'
local dofmopt `s(dofmopt)'
local bvclean =`s(bvclean)' // arrives as string but return now as boolean
local bvclean =`s(bvclean)' // arrives as string but return now as boolean
local dispopt `s(dispopt)'
local dispopt `s(dispopt)'
// Can now tsset; sortpreserve will restore sort after exit
// Can now tsset; sortpreserve will restore sort after exit
if `tsops' | "`kernel'"~="" {
if `tsops' | "`kernel'"~="" {
cap tsset // restores sort if tsset or xtset but sort disrupted
cap tsset // restores sort if tsset or xtset but sort disrupted
if _rc>0 {
if _rc>0 {
tsset `ivar' `tvar'
tsset `ivar' `tvar'
}
}
}
}
***********************************************************
***********************************************************
// Weights
// Weights
// fweight and aweight accepted as is
// fweight and aweight accepted as is
// iweight not allowed with robust or gmm and requires a trap below when used with summarize
// iweight not allowed with robust or gmm and requires a trap below when used with summarize
// pweight is equivalent to aweight + robust
// pweight is equivalent to aweight + robust
// Since we subsequently work with wvar, tsrevar of weight vars in weight `exp' not needed.
// Since we subsequently work with wvar, tsrevar of weight vars in weight `exp' not needed.
tempvar wvar
tempvar wvar
if "`weight'" == "fweight" | "`weight'"=="aweight" {
if "`weight'" == "fweight" | "`weight'"=="aweight" {
local wtexp `"[`weight'=`exp']"'
local wtexp `"[`weight'=`exp']"'
qui gen double `wvar'=`exp'
qui gen double `wvar'=`exp'
}
}
if "`weight'" == "fweight" & "`kernel'" !="" {
if "`weight'" == "fweight" & "`kernel'" !="" {
di in red "fweights not allowed (data are -tsset-)"
di in red "fweights not allowed (data are -tsset-)"
exit 101
exit 101
}
}
if "`weight'" == "fweight" & "`sw'" != "" {
if "`weight'" == "fweight" & "`sw'" != "" {
di in red "fweights currently not supported with -sw- option"
di in red "fweights currently not supported with -sw- option"
exit 101
exit 101
}
}
if "`weight'" == "iweight" {
if "`weight'" == "iweight" {
if "`robust'`cluster'`gmm2s'`kernel'" !="" {
if "`robust'`cluster'`gmm2s'`kernel'" !="" {
di in red "iweights not allowed with robust or gmm"
di in red "iweights not allowed with robust or gmm"
exit 101
exit 101
}
}
else {
else {
local wtexp `"[`weight'=`exp']"'
local wtexp `"[`weight'=`exp']"'
qui gen double `wvar'=`exp'
qui gen double `wvar'=`exp'
}
}
}
}
if "`weight'" == "pweight" {
if "`weight'" == "pweight" {
local wtexp `"[aweight=`exp']"'
local wtexp `"[aweight=`exp']"'
qui gen double `wvar'=`exp'
qui gen double `wvar'=`exp'
local robust "robust"
local robust "robust"
}
}
if "`weight'" == "" {
if "`weight'" == "" {
* If no weights, define neutral weight variable
* If no weights, define neutral weight variable
qui gen byte `wvar'=1
qui gen byte `wvar'=1
}
}
********************************************************************************
********************************************************************************
// markout sample
// markout sample
// include `tvar' to limit sample to where tvar is available, but only if TS operators used
// include `tvar' to limit sample to where tvar is available, but only if TS operators used
marksample touse
marksample touse
if `tsops' {
if `tsops' {
markout `touse' `lhs' `inexog' `exexog' `endo' `cluster' `tvar', strok
markout `touse' `lhs' `inexog' `exexog' `endo' `cluster' `tvar', strok
}
}
else {
else {
markout `touse' `lhs' `inexog' `exexog' `endo' `cluster', strok
markout `touse' `lhs' `inexog' `exexog' `endo' `cluster', strok
}
}
* Create HDFE object and update touse
if (`"`absorb'"' != "") {
* fixed_effects(absvars | , touse, wtype, wtvar, dropsing, verbose)
mata: HDFE = fixed_effects("`absorb'", "`touse'", "`weight'", "`wvar'")
_assert ("`s(options)'"==""), msg("unsupported options in {bf:absorb()}: `s(options)'")
mata: HDFE.clustervars = HDFE.base_clustervars = tokens("`cluster'")
mata: HDFE.num_clusters = length(HDFE.clustervars)
mata: HDFE.estimate_dof() // compute degrees-of-freedom
mata: HDFE.save_touse("`touse'", 1) // 1 = overwrite
}
********************************************************************************
********************************************************************************
// weight factor and sample size
// weight factor and sample size
// Every time a weight is used, must multiply by scalar wf ("weight factor")
// Every time a weight is used, must multiply by scalar wf ("weight factor")
// wf=1 for no weights, fw and iw, wf = scalar that normalizes sum to be N if aw or pw
// wf=1 for no weights, fw and iw, wf = scalar that normalizes sum to be N if aw or pw
sum `wvar' if `touse' `wtexp', meanonly
sum `wvar' if `touse' `wtexp', meanonly
// Weight statement
// Weight statement
if "`weight'" ~= "" {
if "`weight'" ~= "" {
di in gr "(sum of wgt is " %14.4e `r(sum_w)' ")"
di in gr "(sum of wgt is " %14.4e `r(sum_w)' ")"
}
}
if "`weight'"=="" | "`weight'"=="fweight" | "`weight'"=="iweight" {
if "`weight'"=="" | "`weight'"=="fweight" | "`weight'"=="iweight" {
// Effective number of observations is sum of weight variable.
// Effective number of observations is sum of weight variable.
// If weight is "", weight var must be column of ones and N is number of rows
// If weight is "", weight var must be column of ones and N is number of rows
local wf=1
local wf=1
local N=r(sum_w)
local N=r(sum_w)
}
}
else if "`weight'"=="aweight" | "`weight'"=="pweight" {
else if "`weight'"=="aweight" | "`weight'"=="pweight" {
local wf=r(N)/r(sum_w)
local wf=r(N)/r(sum_w)
local N=r(N)
local N=r(N)
}
}
else {
else {
// Should never reach here
// Should never reach here
di as err "ivreg2 error - misspecified weights"
di as err "ivreg2 error - misspecified weights"
exit 198
exit 198
}
}
if `N'==0 {
if `N'==0 {
di as err "no observations"
di as err "no observations"
exit 2000
exit 2000
}
}
***************************************************************
***************************************************************
// Time-series data
// Time-series data
// tindex used by Mata code so that ts operators work correctly
// tindex used by Mata code so that ts operators work correctly
tempvar tindex
tempvar tindex
qui gen `tindex'=1 if `touse'
qui gen `tindex'=1 if `touse'
qui replace `tindex'=sum(`tindex') if `touse'
qui replace `tindex'=sum(`tindex') if `touse'
if `tsops' | "`kernel'"~="" {
if `tsops' | "`kernel'"~="" {
// Report gaps in data
// Report gaps in data
tsreport if `touse', panel
tsreport if `touse', panel
if `r(N_gaps)' != 0 {
if `r(N_gaps)' != 0 {
di as text "Warning: time variable " as res "`tvar'" as text " has " ///
di as text "Warning: time variable " as res "`tvar'" as text " has " ///
as res "`r(N_gaps)'" as text " gap(s) in relevant range"
as res "`r(N_gaps)'" as text " gap(s) in relevant range"
}
}
// Set local macro T and check that bw < (T-1)
// Set local macro T and check that bw < (T-1)
sum `tvar' if `touse', meanonly
sum `tvar' if `touse', meanonly
local T = r(max)-r(min) + 1
local T = r(max)-r(min) + 1
local T1 = `T' - 1
local T1 = `T' - 1
if (`bw' > (`T1'/`tdelta')) {
if (`bw' > (`T1'/`tdelta')) {
di as err "invalid bandwidth in option bw() - cannot exceed timespan of data"
di as err "invalid bandwidth in option bw() - cannot exceed timespan of data"
exit 198
exit 198
}
}
}
}
// kiefer VCV = kernel(tru) bw(T) and no robust with tsset data
// kiefer VCV = kernel(tru) bw(T) and no robust with tsset data
if "`kiefer'" ~= "" {
if "`kiefer'" ~= "" {
local bw =`T'
local bw =`T'
}
}
*********** Column of ones for constant set up here **************
*********** Column of ones for constant set up here **************
if "`noconstant'"=="" {
if "`noconstant'"=="" {
// If macro not created, automatically omitted.
// If macro not created, automatically omitted.
tempvar ones
tempvar ones
qui gen byte `ones' = 1 if `touse'
qui gen byte `ones' = 1 if `touse'
}
}
************* Varlists, FV varlists, duplicates *****************
************* Varlists, FV varlists, duplicates *****************
// Varlists come in 4 versions, e.g., for inexog:
// Varlists come in 4 versions, e.g., for inexog:
// (a) inexog = full list of original expanded vnames; may have duplicates
// (a) inexog = full list of original expanded vnames; may have duplicates
// (b) inexog0 = as with inexog with duplicates removed but RETAINING base/omitted/etc. varnames
// (b) inexog0 = as with inexog with duplicates removed but RETAINING base/omitted/etc. varnames
// (c) inexog1 = as with inexog0 but WITHOUT base/omitted/etc.
// (c) inexog1 = as with inexog0 but WITHOUT base/omitted/etc.
// (d) fv_inexog1 = corresponding list with temp vars minus base/omitted/etc., duplicates, collinearities etc.
// (d) fv_inexog1 = corresponding list with temp vars minus base/omitted/etc., duplicates, collinearities etc.
// Varlists (c) and (d) are definitive, i.e., have the variables actually used in the estimation.
// Varlists (c) and (d) are definitive, i.e., have the variables actually used in the estimation.
// Create consistent expanded varlists.
// Create consistent expanded varlists.
// "Consistent" means base vars for FVs must be consistent
// "Consistent" means base vars for FVs must be consistent
// hence default rhs=endo+inexog is expanded as one.
// hence default rhs=endo+inexog is expanded as one.
// fvall: overrides, endo+inexog+exexog expanded as one
// fvall: overrides, endo+inexog+exexog expanded as one
// fvsep: overrides, endo, inexog and exexog expanded separately
// fvsep: overrides, endo, inexog and exexog expanded separately
// NB: expanding endo+inexog+exexog is dangerous because
// NB: expanding endo+inexog+exexog is dangerous because
// fvexpand can zap a list in case of overlap
// fvexpand can zap a list in case of overlap
// e.g. fvexpand mpg + i(1/4).rep78 + i5.rep78
// e.g. fvexpand mpg + i(1/4).rep78 + i5.rep78
// => mpg 1b.rep78 2.rep78 3.rep78 4.rep78 5.rep78
// => mpg 1b.rep78 2.rep78 3.rep78 4.rep78 5.rep78
// but fvexpand mpg + i.rep78 + i5.rep78
// but fvexpand mpg + i.rep78 + i5.rep78
// => mpg 5.rep78
// => mpg 5.rep78
CheckDupsCollin, ///
CheckDupsCollin, ///
lhs(`lhs') ///
lhs(`lhs') ///
endo(`endo') ///
endo(`endo') ///
inexog(`inexog') ///
inexog(`inexog') ///
exexog(`exexog') ///
exexog(`exexog') ///
partial(`partial') ///
partial(`partial') ///
orthog(`orthog') ///
orthog(`orthog') ///
endogtest(`endogtest') ///
endogtest(`endogtest') ///
redundant(`redundant') ///
redundant(`redundant') ///
touse(`touse') ///
touse(`touse') ///
wvar(`wvar') ///
wvar(`wvar') ///
wf(`wf') ///
wf(`wf') ///
`noconstant' ///
`noconstant' ///
`nocollin' ///
`nocollin' ///
`fvall' ///
`fvall' ///
`fvsep'
`fvsep'
// Replace basic varlists and create "0" versions of varlists
// Replace basic varlists and create "0" versions of varlists
foreach vl in lhs endo inexog exexog partial orthog endogtest redundant {
foreach vl in lhs endo inexog exexog partial orthog endogtest redundant {
local `vl' `s(`vl')'
local `vl' `s(`vl')'
local `vl'0 `s(`vl'0)'
local `vl'0 `s(`vl'0)'
}
}
local dups `s(dups)'
local dups `s(dups)'
local collin `s(collin)'
local collin `s(collin)'
local ecollin `s(ecollin)'
local ecollin `s(ecollin)'
// Create "1" and fv versions of varlists
// Create "1" and fv versions of varlists
foreach vl in lhs endo inexog exexog partial orthog endogtest redundant {
foreach vl in lhs endo inexog exexog partial orthog endogtest redundant {
foreach var of local `vl'0 { // var-by-var so that fvrevar doesn't decide on base etc.
foreach var of local `vl'0 { // var-by-var so that fvrevar doesn't decide on base etc.
_ms_parse_parts `var'
_ms_parse_parts `var'
if ~`r(omit)' { // create temp var only if not omitted
if ~`r(omit)' { // create temp var only if not omitted
fvrevar `var' if `touse'
fvrevar `var' if `touse'
local `vl'1 ``vl'1' `var'
local `vl'1 ``vl'1' `var'
local fv_`vl'1 `fv_`vl'1' `r(varlist)'
local fv_`vl'1 `fv_`vl'1' `r(varlist)'
}
}
}
}
local `vl'1 : list retokenize `vl'1
local `vl'1 : list retokenize `vl'1
local fv_`vl'1 : list retokenize fv_`vl'1
local fv_`vl'1 : list retokenize fv_`vl'1
}
}
// Check that LHS expanded to a single variable
// Check that LHS expanded to a single variable
local wrongvars_ct : word count `lhs'
local wrongvars_ct : word count `lhs'
if `wrongvars_ct' > 1 {
if `wrongvars_ct' > 1 {
di as err "multiple dependent variables specified: `lhs'"
di as err "multiple dependent variables specified: `lhs'"
error 198
error 198
}
}
// Check that option varlists are compatible with main varlists
// Check that option varlists are compatible with main varlists
// orthog()
// orthog()
local wrongvars : list orthog1 - inexog1
local wrongvars : list orthog1 - inexog1
local wrongvars : list wrongvars - exexog1
local wrongvars : list wrongvars - exexog1
local wrongvars_ct : word count `wrongvars'
local wrongvars_ct : word count `wrongvars'
if `wrongvars_ct' {
if `wrongvars_ct' {
di as err "Error: `wrongvars' listed in orthog() but does not appear as exogenous."
di as err "Error: `wrongvars' listed in orthog() but does not appear as exogenous."
error 198
error 198
}
}
// endog()
// endog()
local wrongvars : list endogtest1 - endo1
local wrongvars : list endogtest1 - endo1
local wrongvars_ct : word count `wrongvars'
local wrongvars_ct : word count `wrongvars'
if `wrongvars_ct' {
if `wrongvars_ct' {
di as err "Error: `wrongvars' listed in endog() but does not appear as endogenous."
di as err "Error: `wrongvars' listed in endog() but does not appear as endogenous."
error 198
error 198
}
}
// redundant()
// redundant()
local wrongvars : list redundant1 - exexog1
local wrongvars : list redundant1 - exexog1
local wrongvars_ct : word count `wrongvars'
local wrongvars_ct : word count `wrongvars'
if `wrongvars_ct' {
if `wrongvars_ct' {
di as err "Error: `wrongvars' listed in redundant() but does not appear as exogenous."
di as err "Error: `wrongvars' listed in redundant() but does not appear as exogenous."
error 198
error 198
}
}
// And create allnames macros
// And create allnames macros
local allnames `lhs' `endo' `inexog' `exexog'
local allnames `lhs' `endo' `inexog' `exexog'
local allnames0 `lhs0' `endo0' `inexog0' `exexog0'
local allnames0 `lhs0' `endo0' `inexog0' `exexog0'
local allnames1 `lhs1' `endo1' `inexog1' `exexog1'
local allnames1 `lhs1' `endo1' `inexog1' `exexog1'
local fv_allnames1 `fv_lhs1' `fv_endo1' `fv_inexog1' `fv_exexog1'
local fv_allnames1 `fv_lhs1' `fv_endo1' `fv_inexog1' `fv_exexog1'
// *************** Partial-out block ************** //
// *************** Partial-out block ************** //
// `partial' has all to be partialled out except for constant
// `partial' has all to be partialled out except for constant
if "`partial1'" != "" | `partialcons'==1 {
if "`partial1'" != "" | `partialcons'==1 | "`absorb'" != "" {
preserve
preserve
// Remove partial0 from inexog0.
// Remove partial0 from inexog0.
// Remove partial1 from inexog1.
// Remove partial1 from inexog1.
local inexog0 : list inexog0 - partial0
local inexog0 : list inexog0 - partial0
local inexog1 : list inexog1 - partial1
local inexog1 : list inexog1 - partial1
local fv_inexog1 : list fv_inexog1 - fv_partial1
local fv_inexog1 : list fv_inexog1 - fv_partial1
// Check that cluster, weight, tvar or ivar variables won't be transformed
// Check that cluster, weight, tvar or ivar variables won't be transformed
// Use allnames1 (expanded varlist)
// Use allnames1 (expanded varlist)
if "`cluster'"~="" {
if "`cluster'"~="" {
local pvarcheck : list cluster in allnames1
local pvarcheck : list cluster in allnames1
if `pvarcheck' {
if `pvarcheck' {
di in r "Error: cannot use cluster variable `cluster' as dependent variable, regressor or IV"
di in r "Error: cannot use cluster variable `cluster' as dependent variable, regressor or IV"
di in r " in combination with -partial- option."
di in r " in combination with -partial- option."
error 198
error 198
}
}
}
}
if "`tvar'"~="" {
if "`tvar'"~="" {
local pvarcheck : list tvar in allnames1
local pvarcheck : list tvar in allnames1
if `pvarcheck' {
if `pvarcheck' {
di in r "Error: cannot use time variable `tvar' as dependent variable, regressor or IV"
di in r "Error: cannot use time variable `tvar' as dependent variable, regressor or IV"
di in r " in combination with -partial- option."
di in r " in combination with -partial- option."
error 198
error 198
}
}
}
}
if "`ivar'"~="" {
if "`ivar'"~="" {
local pvarcheck : list ivar in allnames1
local pvarcheck : list ivar in allnames1
if `pvarcheck' {
if `pvarcheck' {
di in r "Error: cannot use panel variable `ivar' as dependent variable, regressor or IV"
di in r "Error: cannot use panel variable `ivar' as dependent variable, regressor or IV"
di in r " in combination with -partial- option."
di in r " in combination with -partial- option."
error 198
error 198
}
}
}
}
if "`wtexp'"~="" {
if "`wtexp'"~="" {
tokenize `exp', parse("*/()+-^&|~")
tokenize `exp', parse("*/()+-^&|~")
local wvartokens `*'
local wvartokens `*'
local nwvarnames : list allnames1 - wvartokens
local nwvarnames : list allnames1 - wvartokens
local wvarnames : list allnames1 - nwvarnames
local wvarnames : list allnames1 - nwvarnames
if "`wvarnames'"~="" {
if "`wvarnames'"~="" {
di in r "Error: cannot use weight variables as dependent variable, regressor or IV"
di in r "Error: cannot use weight variables as dependent variable, regressor or IV"
di in r " in combination with -partial- option."
di in r " in combination with -partial- option."
error 198
error 198
}
}
}
}
// Partial out
// Partial out
// But first replace everything with doubles
// But first replace everything with doubles
recast double `fv_lhs1' `fv_endo1' `fv_inexog1' `fv_exexog1' `fv_partial1'
recast double `fv_lhs1' `fv_endo1' `fv_inexog1' `fv_exexog1' `fv_partial1'
mata: s_partial ("`fv_lhs1'", ///
"`fv_endo1'", ///
"`fv_inexog1'", ///
"`fv_exexog1'", ///
"`fv_partial1'", ///
"`touse'", ///
"`weight'", ///
"`wvar'", ///
`wf', ///
`N', ///
`cons')
local partial_ct : word count `partial1'
if ("`absorb'" != "") {
local hdfe_varlist `fv_lhs1' `fv_endo1' `fv_inexog1' `fv_exexog1' `fv_partial1'
mata: st_store(HDFE.sample, tokens("`hdfe_varlist'"), HDFE.partial_out(tokens("`hdfe_varlist'")))
mata: st_local("absorb_ct", strofreal(HDFE.df_a))
assert `absorb_ct'`' != .
if (`absorb_ct'==0) local absorb_ct 1 // adjustment to match ivreg2 and old reghdfe (happens if absvar is nested in cluster)
local partial_ct 0
local partialcons `absorb_ct'
}
if ("`partial1'" != "" | `partialcons'==1) {
mata: s_partial ("`fv_lhs1'", ///
"`fv_endo1'", ///
"`fv_inexog1'", ///
"`fv_exexog1'", ///
"`fv_partial1'", ///
"`touse'", ///
"`weight'", ///
"`wvar'", ///
`wf', ///
`N', ///
`cons')
local partial_ct : word count `partial1'
}
// Constant is partialled out, unless nocons already specified in the first place
// Constant is partialled out, unless nocons already specified in the first place
capture drop `ones'
capture drop `ones'
local ones ""
local ones ""
if "`noconstant'" == "" {
if "`noconstant'" == "" {
// partial_ct used for small-sample adjustment to regression F-stat
// partial_ct used for small-sample adjustment to regression F-stat
local partial_ct = `partial_ct' + 1
local partial_ct = `partial_ct' + 1
local noconstant "noconstant"
local noconstant "noconstant"
local cons 0
local cons 0
}
}
if ("`absorb'" != "") {
local partial_ct = `partial_ct' + `absorb_ct'
}
}
}
else {
else {
// Set count of partial vars to zero if option not used
// Set count of partial vars to zero if option not used
local partial_ct 0
local partial_ct 0
local partialcons 0
local partialcons 0
}
}
// Add partial_ct to small dof adjustment sdofminus
// Add partial_ct to small dof adjustment sdofminus
if "`nopartialsmall'"=="" {
if "`nopartialsmall'"=="" {
local sdofminus = `sdofminus'+`partial_ct'
local sdofminus = `sdofminus'+`partial_ct'
}
}
*********************************************
*********************************************
local rhs0 `endo0' `inexog0' // needed for display of omitted/base/etc.
local rhs0 `endo0' `inexog0' // needed for display of omitted/base/etc.
local rhs1 `endo1' `inexog1'
local rhs1 `endo1' `inexog1'
local insts1 `exexog1' `inexog1'
local insts1 `exexog1' `inexog1'
local fv_insts1 `fv_exexog1' `fv_inexog1'
local fv_insts1 `fv_exexog1' `fv_inexog1'
local fv_rhs1 `fv_endo1' `fv_inexog1'
local fv_rhs1 `fv_endo1' `fv_inexog1'
local rhs0_ct : word count `rhs0' // needed for display of omitted/base/etc.
local rhs0_ct : word count `rhs0' // needed for display of omitted/base/etc.
local rhs1_ct : word count `fv_rhs1'
local rhs1_ct : word count `fv_rhs1'
local iv1_ct : word count `fv_insts1'
local iv1_ct : word count `fv_insts1'
local endo1_ct : word count `fv_endo1'
local endo1_ct : word count `fv_endo1'
local exex1_ct : word count `fv_exexog1'
local exex1_ct : word count `fv_exexog1'
local endoexex1_c : word count `fv_endo1' `fv_exexog1'
local endoexex1_c : word count `fv_endo1' `fv_exexog1'
local inexog1_ct : word count `fv_inexog1'
local inexog1_ct : word count `fv_inexog1'
// Counts modified to include constant if appropriate
// Counts modified to include constant if appropriate
local rhs1_ct = `rhs1_ct' + `cons'
local rhs1_ct = `rhs1_ct' + `cons'
local rhs0_ct = `rhs0_ct' + `cons' // needed for display of omitted/base/etc.
local rhs0_ct = `rhs0_ct' + `cons' // needed for display of omitted/base/etc.
local iv1_ct = `iv1_ct' + `cons'
local iv1_ct = `iv1_ct' + `cons'
// Column/row names for matrices b, V, S, etc.
// Column/row names for matrices b, V, S, etc.
local cnb0 `endo0' `inexog0' // including omitted
local cnb0 `endo0' `inexog0' // including omitted
local cnb1 `endo1' `inexog1' // excluding omitted
local cnb1 `endo1' `inexog1' // excluding omitted
local cnZ0 `exexog0' `inexog0' // excluding omitted
local cnZ0 `exexog0' `inexog0' // excluding omitted
local cnZ1 `exexog1' `inexog1' // excluding omitted
local cnZ1 `exexog1' `inexog1' // excluding omitted
if `cons' {
if `cons' {
local cnb0 "`cnb0' _cons"
local cnb0 "`cnb0' _cons"
local cnb1 "`cnb1' _cons"
local cnb1 "`cnb1' _cons"
local cnZ0 "`cnZ0' _cons"
local cnZ0 "`cnZ0' _cons"
local cnZ1 "`cnZ1' _cons"
local cnZ1 "`cnZ1' _cons"
}
}
*********************************************
*********************************************
// Remaining checks: variable counts, col/row names of b0, smatrix, wmatrix
// Remaining checks: variable counts, col/row names of b0, smatrix, wmatrix
CheckMisc, ///
CheckMisc, ///
rhs1_ct(`rhs1_ct') ///
rhs1_ct(`rhs1_ct') ///
iv1_ct(`iv1_ct') ///
iv1_ct(`iv1_ct') ///
bvector(`b0') ///
bvector(`b0') ///
smatrix(`smatrix') ///
smatrix(`smatrix') ///
wmatrix(`wmatrix') ///
wmatrix(`wmatrix') ///
cnb1(`cnb1') ///
cnb1(`cnb1') ///
cnZ1(`cnZ1')
cnZ1(`cnZ1')
if "`b0'"~="" {
if "`b0'"~="" {
tempname b0 // so we can overwrite without changing original user matrix
tempname b0 // so we can overwrite without changing original user matrix
mat `b0' = r(b0)
mat `b0' = r(b0)
}
}
if "`smatrix'"~="" {
if "`smatrix'"~="" {
tempname S0
tempname S0
mat `S0' = r(S0)
mat `S0' = r(S0)
}
}
if "`wmatrix'"~="" {
if "`wmatrix'"~="" {
tempname wmatrix // so we can overwrite without changing original user matrix
tempname wmatrix // so we can overwrite without changing original user matrix
mat `wmatrix' = r(W0)
mat `wmatrix' = r(W0)
}
}
*************** Commonly used matrices ****************
*************** Commonly used matrices ****************
tempname YY yy yyc
tempname YY yy yyc
tempname XX X1X1 X2X2 X1Z X1Z1 XZ Xy
tempname XX X1X1 X2X2 X1Z X1Z1 XZ Xy
tempname ZZ Z1Z1 Z2Z2 Z1Z2 Z1X2 Zy ZY Z2y Z2Y
tempname ZZ Z1Z1 Z2Z2 Z1Z2 Z1X2 Zy ZY Z2y Z2Y
tempname XXinv X2X2inv ZZinv XPZXinv
tempname XXinv X2X2inv ZZinv XPZXinv
tempname rankxx rankzz condxx condzz
tempname rankxx rankzz condxx condzz
// use fv_ varlists
// use fv_ varlists
mata: s_crossprods ("`fv_lhs1'", ///
mata: s_crossprods ("`fv_lhs1'", ///
"`fv_endo1'", ///
"`fv_inexog1' `ones'", ///
"`fv_exexog1'", ///
"`touse'", ///
"`weight'", ///
"`wvar'", ///
`wf', ///
`N')
mat `XX' =r(XX)
mat `X1X1' =r(X1X1)
mat `X1Z' =r(X1Z)
mat `ZZ' =r(ZZ)
mat `Z2Z2' =r(Z2Z2)
mat `Z1Z2' =r(Z1Z2)
mat `XZ' =r(XZ)
mat `Xy' =r(Xy)
mat `Zy' =r(Zy)
mat `YY' =r(YY)
scalar `yy' =r(yy)
scalar `yyc' =r(yyc)
mat `ZY' =r(ZY)
mat `Z2y' =r(Z2y)
mat `Z2Y' =r(Z2Y)
mat `XXinv' =r(XXinv)
mat `ZZinv' =r(ZZinv)
mat `XPZXinv' =r(XPZXinv)
scalar `condxx' =r(condxx)
scalar `condzz' =r(condzz)
scalar `rankzz' = rowsof(`ZZinv') - diag0cnt(`ZZinv')
scalar `rankxx' = rowsof(`XXinv') - diag0cnt(`XXinv')
local overid = `rankzz' - `rankxx'
********** CLUSTER SETUP **********************************************
* Mata code requires data are sorted on (1) the first var cluster if there
* is only one cluster var; (2) on the 3rd and then 1st if two-way clustering,
* unless (3) two-way clustering is combined with kernel option, in which case
* the data are tsset and sorted on panel id (first cluster variable) and time
* id (second cluster variable).
* Second cluster var is optional and requires an identifier numbered 1..N_clust2,
* unless combined with kernel option, in which case it's the time variable.
* Third cluster var is the intersection of 1 and 2, unless combined with kernel
* opt, in which case it's unnecessary.
* Sorting on "cluster3 cluster1" means that in Mata, panelsetup works for
* both, since cluster1 nests cluster3.
* Note that it is possible to cluster on time but not panel, in which case
* cluster1 is time, cluster2 is empty and data are sorted on panel-time.
* Note also that if data are sorted here but happen to be tsset, will need
* to be re-tsset after estimation code concludes.
// No cluster options or only 1-way clustering
// but for Mata and other purposes, set N_clust vars =0
local N_clust=0
local N_clust1=0
local N_clust2=0
if "`cluster'"!="" {
local clopt "cluster(`cluster')"
tokenize `cluster'
local cluster1 "`1'"
local cluster2 "`2'"
if "`kernel'"~="" {
* kernel requires