📄 reg3.ado
字号:
*! version 6.3.6 24jan2005
program define reg3, eclass byable(recall)
version 6.0, missing
if replay() {
if "`e(cmd)'" != "reg3" & /*
*/ !("`e(cmd)'" == "sureg" & "`e(method)'" == "sure") {
error 301
}
if _by() {
error 190
}
syntax [ , noFOoter noHeader noTable Level(cilevel) ]
}
else {
/* Parse (y1 x1 x2) (y2 y1 x2 x3) structure.
* Pick up full varlist (flist), y-array (y`i'), indendent
* variables (ind`i') left-hand sides (lhslist),
* equation names (eqnm`i')
*/
local neq = 0
/* Parse the equations ([eqname:] y1 [y2 y3 =] x1 x2 x3)
* and fill in the structures required for estimation */
gettoken fulleq 0 : 0, parse(" ,[") match(paren)
IsStop `fulleq'
while `s(stop)' == 0 {
if "`paren'" != "(" { /* must be eq */
eq ?? `fulleq'
local fulleq "`r(eqname)': `r(eq)'"
}
parseEqn `fulleq'
/* Set-up equation bookeeping structures */
local flist `flist' `depvars' `indvars'
tokenize `depvars'
local i 1
while "``i''" != "" {
local neq = `neq' + 1
local y`neq' ``i''
local lhslist `lhslist' ``i''
local ind`neq' `indvars'
local cons`neq' = ("`constan'" == "")
nameEq "`eqname'" "``i''" "`eqlist'" `neq'
local eqnm`neq' = "`s(eqname)'"
local eqlist `eqlist' `s(eqname)'
local i = `i' + 1
}
gettoken fulleq 0 : 0, parse(" ,[") match(paren)
IsStop `fulleq'
}
local 0 `"`fulleq' `0'"'
if `neq' < 1 {
di in red "equation(s) required"
exit 198
}
/* process options */
/* kludge to pull nodfk and nosmall */
syntax [if] [in] [aw fw] [, noDFK noSMall * ]
local nodfk `dfk'
local nosmall `small'
syntax [if] [in] [aw fw] [, 2sls 3sls Allexog noConstant /*
*/ Constraints(string) CORr(string) DFK DFK2 /*
*/ EXog(varlist) First noFOoter ENdog(varlist) /*
*/ noHeader INst(varlist) ITerate(int `c(maxiter)') /*
*/ IReg3 Level(cilevel) Mvreg noLOg Ols SMall /*
*/ SUre noTable TOLerance(real 1e-6) TRace ]
/* Process the estimation method options */
local method `2sls' `3sls' `ols' `sure' `mvreg'
local i : word count `method'
if ( `i' > 1 ) {
disp in red "cannot specify more that one estimation method: `method'"
exit 198
}
if "`method'" == "" {
local method = "3sls"
}
if "`method'" == "ols" | "`method'" == "mvreg" | /*
*/ "`method'" == "2sls" {
if "`dfk2'" == "" {
local dfk dfk
}
local small small
if "`method'" == "ols" | "`method'" == "2sls" {
local corr independent
}
}
if "`method'" == "ols" | "`method'" == "mvreg" | /*
*/ "`method'" == "sure" {
local allexog allexog
}
if "`dfk'" != "" & "`dfk2'" != "" {
di in red "cannot specify both dfk and dfk2"
exit 198
}
/* Process some options and implied settings */
if `iterate' != `c(maxiter)' {
local ireg3 ireg3
}
setCorr corr : "`corr'"
/* allow over-ride for some default re-settings */
if "`nodfk'" != "" {
local dfk ""
}
if "`nosmall'" != "" {
local small ""
}
/* Errors in command */
if "`inst'" != "" & ("`endog'" != "" | "`exog'" != "") {
di in red "cannot specify an instrument list with an " /*
*/ "exogenous or endogenous list."
exit 198
}
/* Process exog list and endog lists. Full endogenous list
may exceed number of left-hand sides. */
DropDup flist : "`flist'"
if "`allexog'" != "" {
local exlist "`flist'"
}
else {
if "`inst'" == "" {
Subtract extendg : "`endog'" "`flist'"
if "`extendg'" != "" {
di in blue /*
*/ "note: additional endogenous variables not in the system have no effect"
DispVars " and are ignored: " "`extendg'" 13 78 blue
}
/* Allow an exogenous over-ride of
* endogenous variables */
Subtract enlist : "`lhslist'" "`exog'"
local enlist `enlist' `endog'
DropDup enlist : "`enlist'"
Matches both : "`exog'" "`enlist'"
if "`both'" != "" {
DispVars "cannot specify variables as both endogenous and exogenous: " /*
*/ "`both'" 10 78 red
exit 198
}
local flist `flist' `exog'
DropDup flist : "`flist'"
/* No endog-exog matches, safe to assume
* all non-endog are exog */
Subtract exlist : "`flist'" "`enlist'"
}
else {
DropDup exlist : "`inst'"
Subtract enlist : "`flist'" "`exlist'"
}
}
/* Set obs to use */
marksample touse, novarlist
markout `touse' `enlist' `exlist'
tempvar one /* used later too */
g byte `one' = 1
sum `one' [`weight'`exp'] if `touse', meanonly
local t = r(N)
qui count if `touse'
local covpat = r(N)
local nex : word count `exlist'
local nex = `nex' + ("`constan'" == "")
if `covpat' <= `nex' & /*
*/ ("`method'" == "3sls" | "`method'" == "2sls") {
noi error 2001
}
/* Process information about equations. Set up temporary
* storage. */
tempname DF
mat `DF' = I(`neq')
local i 1
while `i' <= `neq' {
local k`i' : word count `ind`i''
local k`i' = `k`i'' + `cons`i''
local k_tot = `k_tot' + `k`i''
if `k`i'' > `covpat' {
noi error 2001
}
testIdnt "`ind`i''" "`exlist'" `eqnm`i'' `y`i''
/* Residual vars and list disturbance cov */
tempvar res`i'
local reslist `reslist' `res`i''
/* Build matrix column and equation name lists */
local matcols `matcols' `ind`i''
if `cons`i'' {
local matcols "`matcols' _cons"
}
local j 1
while `j' <= `k`i'' {
local coleq `coleq' `eqnm`i''
local j = `j' + 1
}
/* Matrix of denominators for residual covariance */
if "`dfk'" == "dfk" {
local j 1
while `j' <= `i' {
mat `DF'[`i',`j'] = 1 / /*
*/ sqrt((`t' - `k`i'') * (`t' - `k`j''))
if `i' != `j' {
mat `DF'[`j', `i'] = /*
*/ `DF'[`i', `j']
}
local j = `j' + 1
}
}
local i = `i' + 1
}
if "`dfk2'" != "" {
GetDFK2adjust , /*
*/ k(`k_tot') /*
*/ keq(`neq') /*
*/ colnames(`matcols') /*
*/ coleqs(`coleq') /*
*/ clist(`constra') /*
*/
local df_adj = 1 / (`t' - r(adj))
}
else {
local df_adj = 1 / `t'
}
/* Perform OLS to get the instrumental estimates of the Y's
* (for all non-exogenous terms). Build a list of instrument
* names (it is aligned with enlist. */
if "`first'" != "" {
di in gr _newline "First-stage regressions"
di in gr "-----------------------"
local show1 = "noi"
}
tokenize `enlist'
local i 1
while "``i''" != "" {
cap `show1' reg ``i'' `exlist' if `touse' /*
*/ [`weight'`exp'], `constan'
if _rc != 0 {
di in red "1st stage failure."
DispVars " Equation: ``i'' " "`exlist'" /*
*/ 10 78 red
exit _rc
}
tempvar iv`i'
local inlist `inlist' `iv`i''
qui _predict double `iv`i'' if `touse'
local i = `i' + 1
}
/* Form the indep variable lists with the instrumental
* variables in place of the endogenous variables.
*/
local i 1
while `i' <= `neq' {
Subst indi`i' : "`ind`i''" "`enlist'" "`inlist'"
if `cons`i'' {
local indi`i' `indi`i'' `one'
}
local i = `i' + 1
}
/* <<========== */
/*
* Disturbance matrix ==> (B, VCE) ==> Disturbance matrix loop
* Acts like a do ... while
*/
tempname EpE EpEi EpEiB V b bhold errll
tempname sZpZ Zpy sZpy ZpZ ZpyS sigma
local iterate = max(1, `iterate')
mat `EpE' = I(`neq') /* prime for first-pass cov est */
local done 0
local itcnt 0
while !`done' {
/* Get the inverse covariance matrix of errors. On first pass,
* just let the 2SLS/OLS cov. matrix result */
if `itcnt' != 0 {
qui mat accum `EpE' = `reslist' if `touse' /*
*/ [`weight'`exp'], nocons
}
cap drop `reslist'
if "`dfk'" != "" { /* this is not common, will be slow */
mElMult "`EpE'" "`DF'"
}
else {
mat `EpE' = `EpE' * `df_adj'
}
mat `EpEi' = syminv(`EpE')
if "`corr'" == "independent" {
mat `EpEiB' = syminv(diag(vecdiag(`EpE')))
}
else {
mat `EpEiB' = `EpEi'
}
chkDiag "`EpEiB'"
/* Get the Covariance matrix of the 3SLS estimator. We build it
* in pieces extracting only portions of the Z_1'Z_2 accumulated
* matrices for each equation pair. Get the (EpEi (X) I) y too.
* The latter is built separately looping over the full row and
* column combinations to avoid extra storage and bookeeping.
* Could make this a bit faster by using the Z_1'Z_1 and Z_n'Z_n
* computed with the 2nd and next to last accums.
*/
local ktot : word count `matcols'
mat `sZpZ' = J(`ktot', `ktot', 0)
cap {
mat drop `sZpy'
}
local at_i 1
local i 1
while `i' <= `neq' {
local frm = `k`i'' + 1
mat `ZpyS' = J(1, `k`i'', 0)
local at_j 1
local j 1
while `j' <= `neq' {
scalar `sigma' = `EpEiB'[`i',`j']
/* Get Cov. matrix. */
if `j' <= `i' {
qui mat accum `ZpZ' = `indi`i'' `indi`j'' /*
*/ if `touse' [`weight'`exp'], /*
*/ noconstant
mat `sZpZ'[`at_i',`at_j'] = /*
*/ `ZpZ'[1..`k`i'',`frm'...]*`sigma'
if `i' != `j' {
mat `sZpZ'[`at_j',`at_i'] = /*
*/ `ZpZ'[1..`k`i'',`frm'...]'*`sigma'
}
}
/* Get sum(sigma Z_i y_j) */
mat vecaccum `Zpy' = `y`j'' `indi`i'' if `touse' /*
*/ [`weight'`exp'], noconstant
mat `ZpyS' = `ZpyS' + `Zpy'*`sigma'
local at_j = `at_j' + `k`j''
local j = `j' + 1
}
/* Build (EpEiB (X) I) y */
mat `sZpy' = nullmat(`sZpy') \ `ZpyS''
local at_i = `at_i' + `k`i''
local i = `i' + 1
}
/* Get variance-covariance matrix and vector of
* coefficents. Post results.
*/
mat `V' = syminv(`sZpZ')
mat `b' = `sZpy'' * `V''
mat rownames `V' = `matcols'
mat roweq `V' = `coleq'
mat colnames `V' = `matcols'
mat coleq `V' = `coleq'
mat colnames `b' = `matcols'
mat coleq `b' = `coleq'
if "`small'" == "small" {
local tdof = `t'*`neq' - `k_tot'
estimates post `b' `V', dof(`tdof') esample(`touse')
}
else {
local tdof = `t'
estimates post `b' `V', obs(`t') esample(`touse')
}
gen byte `touse' = e(sample)
/* Apply constraints */
if "`constra'" != "" {
Constrn "`constra'" "`small'" `tdof'
}
mat `b' = get(_b)
if `itcnt' == 0 {
mat `bhold' = 2 * `b'
}
local rdiff = mreldif(`b', `bhold')
mat `bhold' = `b'
/* Evaluate stopping conditions */
if ("`ireg3'" != "ireg3" & `itcnt' != 0) | `itcnt' >= `iterate' | /*
*/ `rdiff' < `toleran' {
local done 1
}
else {
/* Get new residual vectors for error covariance matrix */
local i 1
while `i' <=`neq' {
qui _predict double `res`i'', eq(`eqnm`i''), if `touse'
qui replace `res`i'' = `y`i'' - `res`i''
local i = `i' + 1
}
}
if "`ireg3'" == "ireg3" & "`log'" != "nolog" {
if `itcnt' > 0 {
disp in gr "Iteration `itcnt': " /*
*/ "tolerance = " in ye %10.7g `rdiff'
if "`trace'" == "trace" {
mat list `b'
}
}
else di
}
local itcnt = `itcnt' + 1
} /* end while -- iteration loop */
if `iterate' != 1 & `itcnt'-1 == `iterate' {
di in blu "convergence not achieved"
}
/* Equation summary statistics and retained globals */
est local eqnames
tempvar errs
local i 1
while `i' <= `neq' {
est scalar cons_`i' = `cons`i''
if `k`i'' > 1 | !`cons`i'' {
qui test [`eqnm`i'']
}
else {
qui test [`eqnm`i'']_cons
}
if "`small'" == "small" {
est scalar F_`i' = r(F)
est scalar p_`i' = r(p)
}
else {
est scalar chi2_`i' = r(chi2)
est scalar p_`i' = r(p)
}
est scalar df_m`i' = r(df)
qui _predict double `res`i'', eq(`eqnm`i''), if `touse'
qui replace `res`i'' = `y`i'' - `res`i'' /* for ll */
qui gen double `errs' = `res`i''^2
sum `errs' [`weight'`exp'] if `touse', meanonly
drop `errs'
local mse = r(mean)
est scalar rss_`i' = r(sum)
est scalar rmse_`i' = sqrt(r(mean))
if "`small'" == "small" {
est scalar rmse_`i' = /*
*/ sqrt(r(mean)*r(N) / (`t' - `k`i''))
}
if `cons`i'' {
qui sum `y`i'' [`weight'`exp'] if `touse'
est scalar mss_`i' = /*
*/ (r(sum_w)-1)*r(Var) - e(rss_`i')
est scalar r2_`i' = /*
*/ 1 - `mse' / (r(Var) * (`t'-1) / `t')
}
else {
tempvar ysqr
qui gen double `ysqr' = `y`i''^2 if `touse'
sum `ysqr' [`weight'`exp'], meanonly
est scalar mss_`i' = r(sum) - e(rss_`i')
est scalar r2_`i' = /*
*/ 1 - `mse' / r(mean)
drop `ysqr'
}
est local eqnames `e(eqnames)' `eqnm`i''
local i = `i' + 1
}
est scalar k_eform = `neq'
est scalar k = `ktot'
est scalar ic = `itcnt' - 1
if "`ireg3'" == "" {
est scalar ic = 0
}
est scalar N = `t'
if "`small'" != "" {
est scalar df_r = `tdof'
}
est scalar k_eq = `neq'
est scalar dfk2_adj = 1/`df_adj'
mat rowname `EpE' = `eqlist'
mat colnames `EpE' = `eqlist'
est mat Sigma `EpE'
qui mat accum `EpE'=`reslist' if `touse' [`weight'`exp'], nocons
if "`corr'" == "independent" {
mat `EpE'=diag(vecdiag(`EpE'))
}
setLL `EpE'
est local wtype `weight'
est local wexp "`exp'"
est local depvar `lhslist'
est local exog `exlist'
est local endog `enlist'
est local dfk "`dfk'`dfk2'"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -