* Version 2.7 - 03 Mar 2023 * By J.M.C. Santos Silva * Please email jmcss@surrey.ac.uk for help and support * The software is provided as is, without warranty of any kind, express or implied, including * but not limited to the warranties of merchantability, fitness for a particular purpose and * noninfringement. In no event shall the author be liable for any claim, damages or other * liability, whether in an action of contract, tort or otherwise, arising from, out of or in * connection with the software or the use or other dealings in the software. program define ivqreg2, eclass version 14.0 if replay() { _prefix_display exit } syntax varlist(numeric min=1) [if] [in], [INSTruments(string) Quantile(numlist) ls /// TECHnique(string) conv_maxiter(integer 5000) conv_ptol(real 1e-6) conv_vtol(real 1e-6) /// conv_nrtol(real 1e-6) tracelevel(string) quickd from(string) MUsigma /// winitial(string) ONEstep TWOstep] marksample touse markout `touse' `instruments' tempname _y _rhs bb vold _u b g fsd s_hat CC C X fsd1 ones G O fsdu fsdg fsdv g31 g32 _u2 _uv _v U fiu fiv A AA V bpost V_location V_scale Q OM _uf _uvf gettoken _y _rhs: varlist unab _rhs : `_rhs' _rmcoll `_rhs' if `touse', forcedrop local _rhs "`r(varlist)'" local insts=1 if ("`instruments'"=="") { local instruments `_rhs' local insts=0 di as text "Note: no instruments were specified; restricted quantile regression will be performed" } unab instruments : `instruments' _rmcoll `instruments' if `touse', forcedrop local instruments "`r(varlist)'" local wq : word count `instruments' local wx : word count `_rhs' if `wq'<`wx' { di as error "The model is not identified" exit } if ("`quantile'"=="") { local quantile=0.5 } foreach x in `quantile'{ if (`x'>=1)|(`x'<=0) { di as error "quantiles must be between 0 and 1" exit } } di di di if ("`winitial'"=="") local winitial="identity" if ("`from'"=="") { if ("`musigma'"=="") { qui ivreg `_y' (`_rhs' = `instruments') if `touse' qui mat `b'=e(b) qui predict double `_uf' if `touse', res qui mat `AA'=`b'[1,1..`wx'] local names : colfullnames `AA' local _rhs `names' qui g double `_uvf'=abs(`_uf') qui ivreg `_uvf' (`_rhs' = `instruments') if `touse' mat `g'=e(b) mat `A'=`b',`g' local from="`A'" } else { qui su `_y' if `touse' local sd=r(sd) local mu=r(mean) local from="b0 `mu' g0 `sd'" } } if "`technique'"=="nr" qui gmm (main: (`_y' - {xb: `_rhs'}-{b0})/({xg: `_rhs'}+{g0})) /// (abs((`_y' - {xb:}-{b0})/({xg:}+{g0}))-1) if `touse', /// instruments(main 2: `instruments') winitial(`winitial') from(`from') `quickd' /// technique(`technique') tracelevel(`tracelevel') conv_maxiter(`conv_maxiter') /// conv_ptol(`conv_ptol') conv_vtol(`conv_vtol') conv_nrtol(`conv_nrtol') `onestep' `twostep' /// deriv(main/xb = -1/( {xg: }+{g0}) ) /// deriv(main/b0 = -1/( {xg: }+{g0}) ) /// deriv(2/xb = -sign(`_y' - {xb: }-{b0})/( {xg: }+{g0}) ) /// deriv(2/b0 = -sign(`_y' - {xb: }-{b0})/( {xg: }+{g0}) ) /// deriv(main/xg = -(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(main/g0 = -(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(2/xg = -abs(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(2/g0 = -abs(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) else qui gmm (main: (`_y' - {xb: `_rhs'}-{b0})/({xg: `_rhs'}+{g0})) /// (abs((`_y' - {xb:}-{b0})/({xg:}+{g0}))-1) if `touse', /// instruments(main 2: `instruments') winitial(`winitial') from(`from') `quickd' /// technique(`technique') tracelevel(`tracelevel') conv_maxiter(`conv_maxiter') /// conv_ptol(`conv_ptol') conv_vtol(`conv_vtol') `onestep' `twostep' /// deriv(main/xb = -1/( {xg: }+{g0}) ) /// deriv(main/b0 = -1/( {xg: }+{g0}) ) /// deriv(2/xb = -sign(`_y' - {xb: }-{b0})/( {xg: }+{g0}) ) /// deriv(2/b0 = -sign(`_y' - {xb: }-{b0})/( {xg: }+{g0}) ) /// deriv(main/xg = -(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(main/g0 = -(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(2/xg = -abs(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) /// deriv(2/g0 = -abs(`_y' - {xb: }-{b0})/(({xg: }+{g0})^2)) qui predict double `_u' if `touse', residuals equation(main) local objf=e(Q) local conv=e(converged) matrix `bb'=e(b) matrix `V'=e(V) local k=e(k)+1 local k1=(`k'-1)/2 local enne=e(N) matrix `b'=`bb'[1,1..`k1'] matrix `g'=`bb'[1,`k1'+1..`k'-1] mat `V_location'=`V'[1..`k1',1..`k1'] mat `V_scale'=`V'[`k1'+1..`k'-1,`k1'+1..`k'-1] di as text " MM-QR regression results" di di as txt "Number of obs = " _continue di as result `enne' di as txt "GMM criterion Q(b) = " _continue di as result e(Q) if (e(J_df)>0) { di as txt "J-test = " _continue di as result e(J) _continue di as txt ", df = " _continue di as result e(J_df) _continue di as txt ", p-value " _continue di as result chi2tail(e(J_df),e(J)) } if ("`ls'"!="") { mat `G'=`b' mat `O'=`V_location' ereturn post `G' `O', depname("`_y'") di as input " Location parameters" ereturn display, first di mat `G'=`g' mat `O'=`V_scale' ereturn post `G' `O', depname("`_y'") di as input " Scale parameters" ereturn display, first di } qui mat score double `fsd' = `g' if `touse' qui replace `fsd' = `fsd'+`bb'[1,`k'-1] qui g `s_hat' = (`fsd')<=0 if `touse' su `s_hat' if `touse', meanonly if r(max)==1 di as error "WARNING: " 100*r(mean) "% of the fitted values of the scale function are not positive" qui g `ones'=1 mata st_view(`C'=.,.,"`instruments' `ones'","`touse'") mata st_view(`X'=.,.,"`_rhs' `ones'","`touse'") matrix `G'=J(2*(`wq'+1)+1,`k',0) qui g double `fsd1'=1/`fsd' if `touse' mata `fsd1'=st_data(.,"`fsd1'","`touse'") mata st_matrix("`OM'", ((`X')')*((J(1,`wq'+1,1)#(`fsd1')):*(`C'))) mat `G'[1,1]=(`OM')' qui g double `fsdu'=`_u'/`fsd' if `touse' mata `fsdu'=st_data(.,"`fsdu'","`touse'") mata st_matrix("`OM'", ((`X')')*(((J(1,`wq'+1,1)#(`fsdu'))):*(`C'))) matrix `G'[1,`k1'+1]=(`OM')' qui g double `fsdg'=sign(`_u')/`fsd' if `touse' mata `fsdg'=st_data(.,"`fsdg'","`touse'") mata st_matrix("`OM'", ((`X')')*(((J(1,`wq'+1,1)#(`fsdg')):*(`C')))) mat `G'[`wq'+2,1]=(`OM')' qui g double `fsdv'=abs(`_u')/`fsd' if `touse' mata `fsdv'=st_data(.,"`fsdv'","`touse'") mata st_matrix("`OM'", ((`X')')*(((J(1,`wq'+1,1)#(`fsdv')):*(`C')))) matrix `G'[`wq'+2,`k1'+1]=(`OM')' matrix `G'[2*(`wq'+1)+1,`k']=`enne' matrix vecaccum `g31' = `fsd1' `_rhs' if `touse' matrix vecaccum `g32' = `fsdu' `_rhs' if `touse' matrix `G'[2*`wq'+3,1]=`g31' matrix `G'[2*`wq'+3,`k1'+1]=`g32' mat `O'=J(2*(`wq'+1)+1,2*(`wq'+1)+1,0) qui matrix accum `CC' = `instruments' if `touse' qui g double `_u2'=(`_u')^2 if `touse' su `_u2' if `touse', meanonly matrix `O'[1,1]=r(mean)*`CC' qui g double `_uv'=(`_u')*(abs(`_u')-1) if `touse' su `_uv' if `touse', meanonly matrix `O'[1,(`wq'+1)+1]=r(mean)*`CC' matrix `O'[(`wq'+1)+1,1]=r(mean)*`CC' qui g double `_v'=(abs(`_u')-1)^2 if `touse' su `_v' if `touse', meanonly matrix `O'[(`wq'+1)+1,(`wq'+1)+1]=r(mean)*(`CC') matrix vecaccum `CC' = `ones' `instruments' if `touse' qui g double `fiu'=. qui g double `fiv'=. foreach qu in `quantile' { qui qreg `_u' if `touse', q(`qu') vce(iid) local fu= sqrt(`qu'*(1-`qu'))/(_se[_cons]*sqrt(e(N))) matrix `Q'=e(b) qui replace `fiu'=`_u'*(`qu'-(`_u'<=_b[_cons])) if `touse' su `fiu' if `touse', meanonly matrix `O'[1,2*(`wq'+1)+1]=((`CC')')*r(mean)/(`fu') matrix `O'[2*(`wq'+1)+1,1]=(`CC')*r(mean)/(`fu') qui replace `fiv'=(abs(`_u')-1)*(`qu'-(`_u'<=_b[_cons])) if `touse' su `fiv' if `touse', meanonly matrix `O'[2*(`wq'+1)+1,`wq'+2]=(`CC')*r(mean)/(`fu') matrix `O'[`wq'+2,2*(`wq'+1)+1]=((`CC')')*r(mean)/(`fu') matrix `O'[2*(`wq'+1)+1,2*(`wq'+1)+1]= (`enne')*(`qu')*(1-`qu')/(`fu')^2 mat `A'=I(`k1'),_b[_cons]*I(`k1'),(`g')' mat `V'=(`A')*inv(((`G')')*inv(`O')*(`G'))*(`A')' matrix `bpost'=`b'+`g'*_b[_cons] matrix colnames `bpost' = `_rhs' _cons matrix colnames `V' = `_rhs' _cons matrix rownames `V' = `_rhs' _cons mat coleq `bpost' = eq1 mat coleq `V' = eq1 mat roweq `V' = eq1 local __b_q=ustrtoname("__b`qu'") matrix `__b_q' = `bpost' local __V_q=ustrtoname("__V`qu'") matrix `__V_q' = `V' local __Q_q=ustrtoname("__Q`qu'") matrix `__Q_q' = `Q' ereturn post `bpost' `V', obs(`enne') depname("`_y'") if `insts'==1 di as txt `qu' " Structural quantile function" else di as txt `qu' " Restricted quantile regression" ereturn display, first } if `insts'==1 di as txt "Instruments used: `instruments'" ereturn repost , esample(`touse') ereturn scalar converged = `conv' ereturn scalar Q = `objf' ereturn local cmd ivqreg2 ereturn local cmdline ivqreg2 `0' ereturn local depvar = "`_y'" ereturn matrix b_location = `b' ereturn matrix b_scale = `g' ereturn matrix V_location = `V_location' ereturn matrix V_scale = `V_scale' ereturn matrix q = `Q' local wq : word count `quantile' if `wq' > 1 foreach qu in `quantile' { local __b_q=ustrtoname("__b`qu'") local b_q=ustrtoname("b`qu'") ereturn matrix `b_q' = `__b_q' local __V_q=ustrtoname("__V`qu'") local V_q=ustrtoname("V`qu'") ereturn matrix `V_q' = `__V_q' local __Q_q=ustrtoname("__Q`qu'") local _Q_q=ustrtoname("q`qu'") ereturn matrix `_Q_q' = `__Q_q' } end