*!version 1.1 Helmut Farbmacher (July 2018) * *********************************************** prog sivreg, eclass version 10 syntax varlist [if] [in], endog(varlist) exog(varlist) [adaptive c(real 0.1)] marksample touse markout `touse' `exog' `endog' gettoken lhs varlist : varlist qui sum `lhs' if `touse' tempname obs sca `obs'=r(N) //remove collinearity local coll `s(collinear)' _rmcoll `varlist' if `touse', /// `constan' `coll' local varlist `r(varlist)' local coll `s(collinear)' _rmcoll `exog' if `touse', /// `constan' `coll' local exog `r(varlist)' local coll `s(collinear)' _rmcoll `endog' if `touse', /// `constan' `coll' local endog `r(varlist)' //Not more than one endogenous x is allowed tempname nu_endog scalar `nu_endog'=`:word count `endog'' if `nu_endog'>1 { dis in red "Only one endogenous regressor is allowed." exit 103 } //User must state for all variable whether they are endogenous or exogenous loc all: list varlist | exog tempname nu_all nu_endog nu_exog scalar `nu_all'=`:word count `all'' scalar `nu_endog'=`:word count `endog'' scalar `nu_exog'=`:word count `exog'' if (`nu_endog'+`nu_exog')!=`nu_all' { dis in red "Each variable in `varlist' must be either in option endog() or exog()" exit 499 } loc exog_xs: list varlist & exog loc all_exog: list all-endog //remove collinearity local coll `s(collinear)' _rmcoll `all_exog' if `touse', /// `constan' `coll' local all_exog `r(varlist)' loc ivs: list all_exog-exog_xs //remove collinearity local coll `s(collinear)' _rmcoll `ivs' if `touse', /// `constan' `coll' local ivs `r(varlist)' mat b=J(1,`:word count `ivs'',0) matname b `ivs',c(.) tempname nu_moments nu_ivs nu_rhs scalar `nu_moments'=`:word count `all_exog'' scalar `nu_ivs'=`:word count `ivs'' scalar `nu_rhs'=`:word count `varlist'' //Model is not identified if `nu_rhs'>`nu_moments' { dis in red "There are more parameters than potential instruments. Model is not at all identified." exit 481 } mat c_cons123=`c' //hybrid mat adaptive123=0 if "`adaptive'"!="" { mat adaptive123=1 } //FWL to get rid of exog_xs tempvar lhs_fwl endog_fwl qui reg `lhs' `exog_xs' qui predict `lhs_fwl', resid qui reg `endog' `exog_xs' qui predict `endog_fwl', resid foreach var of varlist `ivs' { tempvar `var'_fwl qui reg `var' `exog_xs' qui predict ``var'_fwl', resid local ivs_fwl `"`ivs_fwl' ``var'_fwl'"' } tempname nuoverid scalar `nuoverid'=`nu_ivs'-1 //stop if Hansen test does not reject in the first stage qui ivregress gmm `lhs_fwl' (`endog_fwl'=`ivs_fwl') qui scalar tau=1-`c'/ln(`obs') if e(J)invchi2(mR-1,tau)) { cmu=Zt'(yabc-mu)/n if (kx<2) { c=colmaxabs(cmu) threshold=c/1000 ss=(abs(round(cmu,threshold)):==round(c,threshold))' A=ss j=select((1..cols(ss)), (abs(ss) :== max(abs(ss)))) Aset=j } else { c=colmaxabs(select(cmu,ssval')) threshold=c/1000 cmax=c*J(m,1,1) ss=(abs(reldif(cmax,abs(cmu))):1) { gam=alpha[max((kx-1,1)),.]:/(Dhat') drops = gam:<0 if (drops!=J(1,m,0)) { gammatilde=rowmin(abs(select(gam,drops))) //jump at most to where the first variable crosses zero (this is minimum absolue value of the negative numbers in length) if (gammatilde!=.) { gamtildej=select((1..m), (abs(gam) :== gammatilde)) //drop minj from selected set A } } } //get gammatilde ccm=((c:-cmu):/(B:-b)) ccp=((c:+cmu):/(B:+b)) ssval=J(1,cols(A),1)-A ccm=select(ccm',ssval)' ccp=select(ccp',ssval)' ccm=abs(ccm)+(ccm:<0)*1000000 ccp=abs(ccp)+(ccp:<0)*1000000 ccm=ccm+(ccm:==0)*1000000 ccp=ccp+(ccp:==0)*1000000 gammahat=rowmin(colmin((ccm,ccp))) //decision rule b/w gammahat and gammatilde if (gammatilde