* Updated Jan 2021: Following the update of rdrobust, changed to a more stable way matrix inverse is taken * Updated Mar 2023: * Added Stata version number * Per Kit Baum's suggestion, changed program from eclass to rclass * These changes do not affect any calculation capture program drop altfrdbwselect program define altfrdbwselect, rclass version 15.0 syntax anything [if] [in] [, c(real 0) deriv(real 0) fuzzy(string) p(real 1) q(real 2) kernel(string) bwselect(string) rho(real 0) vce(string) matches(real 3) scaleregul(real 1) ] local kernel = lower("`kernel'") local bwselect = upper("`bwselect'") local vce = lower("`vce'") marksample touse preserve qui keep if `touse' tokenize "`anything'" ** declaring the y and x variables ** local y `1' local x `2' ** drop missing values ** qui drop if `y'==. | `x'==. | `fuzzy'==. tempvar x_l x_r y_l y_r t_l t_r local b_calc = 0 if (`rho'==0){ local b_calc = 1 local rho = 1 } ** the medians are used in the IK bandwidth ** qui su `x' if `x'<`c', d local medX_l = r(p50) qui su `x' if `x'>=`c', d local medX_r = r(p50) qui gen `x_l' = `x' if `x'<`c' qui gen `x_r' = `x' if `x'>=`c' qui gen `y_l' = `y' if `x'<`c' qui gen `y_r' = `y' if `x'>=`c' qui gen `t_l' = `fuzzy' if `x'<`c' qui gen `t_r' = `fuzzy' if `x'>=`c' qui su `x' local x_min = r(min) local x_max = r(max) qui su `x_l' local N_l = r(N) local range_l = abs(r(max)-r(min)) qui su `x_r' local N_r = r(N) local range_r = abs(r(max)-r(min)) local N = `N_r' + `N_l' local m = `matches' + 1 if ("`deriv'">"0" & "`p'"=="1" & "`q'"=="0"){ local p = `deriv'+1 } if ("`q'"=="0") { local q = `p'+1 } **************************** ERRORS if (`c'<=`x_min' | `c'>=`x_max'){ di "{err}{cmd:c()} should be set within the range of `x'" exit 125 } if (`N_l'<20 | `N_r'<20){ di "{err}Not enough observations to perform calculations" exit 2001 } if ("`p'">"8"){ di "{err}{cmd:p()} should be less or equal than 8 for this version of the software package" exit 125 } if ("`kernel'"~="uni" & "`kernel'"~="uniform" & "`kernel'"~="tri" & "`kernel'"~="triangular" & "`kernel'"~="epa" & "`kernel'"~="epanechnikov" & "`kernel'"~="" ){ di "{err}{cmd:kernel()} incorrectly specified" exit 7 } ** removed CV as an option from CCT ** if ("`bwselect'"~="CCT" & "`bwselect'"~="IK" & "`bwselect'"~=""){ di "{err}{cmd:bwselect()} incorrectly specified" exit 7 } if ("`vce'"~="resid" & "`vce'"~="nn" & "`vce'"~=""){ di "{err}{cmd:vce()} incorrectly specified" exit 7 } if ("`p'"<"0" | "`q'"<="0" | "`deriv'"<"0" | "`matches'"<="0" | `scaleregul'<0){ di "{err}{cmd:p()}, {cmd:q()}, {cmd:deriv()}, {cmd:matches()} and {cmd:scaleregul()} should be positive" exit 411 } if ("`p'">="`q'" & "`q'">"0"){ di "{err}{cmd:q()} should be higher than {cmd:p()}" exit 125 } if ("`deriv'">"`p'" & "`deriv'">"0" ){ di "{err}{cmd:deriv()} can not be higher than {cmd:p()}" exit 125 } if ("`p'">"0" ) { local p_round = round(`p')/`p' local q_round = round(`q')/`q' local d_round = round(`deriv'+1)/(`deriv'+1) local m_round = round(`matches')/`matches' if (`p_round'!=1 | `q_round'!=1 |`d_round'!=1 |`m_round'!=1 ){ di "{err}{cmd:p()}, {cmd:q()}, {cmd:deriv()} and {cmd:matches()} should be integers" exit 126 } } if (`rho'>1 | `rho'<0){ di "{err}{cmd:rho()}should be set between 0 and 1" exit 125 } if ("`exit'">"0") { exit } if ("`kernel'"=="epanechnikov" | "`kernel'"=="epa") { local kernel_type = "Epanechnikov" } else if ("`kernel'"=="uniform" | "`kernel'"=="uni") { local kernel_type = "Uniform" } else { local kernel_type = "Triangular" } disp in yellow "Calculating Preliminary Bandwidths" if ("`bwselect'"=="IK") { qui altrdbwselect `y' `x', c(`c') deriv(`deriv') p(`p') q(`q') bwselect(`bwselect') kernel(`kernel') vce(`vce') precalc scaleregul(`scaleregul') local h = r(h_IK) local b = r(b_IK) local bwselect = "IK" } else { local bwselect = "CCT" qui altrdbwselect `y' `x', c(`c') deriv(`deriv') p(`p') q(`q') matches(`matches') bwselect(`bwselect') kernel(`kernel') vce(`vce') precalc scaleregul(`scaleregul') local h = r(h_CCT) local b = r(b_CCT) } disp in yellow "Obtaining preliminary RD estimates" sort `x', stable mata{ Y = st_data(.,("`y'"), 0) X = st_data(.,("`x'"), 0) T = st_data(.,("`fuzzy'"), 0) Y_l = st_data(.,("`y_l'"), 0) Y_r = st_data(.,("`y_r'"), 0) X_l = st_data(.,("`x_l'"), 0) X_r = st_data(.,("`x_r'"), 0) T_l = st_data(.,("`t_l'"), 0) T_r = st_data(.,("`t_r'"), 0) c = `c' N_l = length(X_l) N_r = length(X_r) c_l = J(N_l, 1, c) c_r = J(N_r, 1, c) p1 = `p' + 1 wh_l = kweight(X_l,`c',`h',"`kernel'"); wh_r = kweight(X_r,`c',`h',"`kernel'") uh_l = (X_l-c_l)/`h'; uh_r = (X_r-c_r)/`h'; uhh_l=select(uh_l,wh_l:> 0); uhh_r=select(uh_r,wh_r:> 0) Yh_l = select(Y_l, wh_l:> 0); Yh_r = select(Y_r, wh_r:> 0) Xh_l = select(X_l, wh_l:> 0); Xh_r = select(X_r, wh_r:> 0) whh_l = select(wh_l, wh_l:> 0); whh_r = select(wh_r, wh_r:> 0) Th_l = select(T_l, wh_l:> 0); Th_r = select(T_r, wh_r:>0) Nh_l = length(Xh_l) Nh_r = length(Xh_r) X_lp = J(N_l,p1,.); X_rp = J(N_r,p1,.) Xh_lp = J(Nh_l,p1,.); Xh_rp = J(Nh_r,p1,.) for (j=1; j<=p1; j++) { X_lp[.,j] = (X_l:-c):^(j-1); X_rp[.,j] = (X_r:-c):^(j-1) Xh_lp[.,j] = (Xh_l:-c):^(j-1); Xh_rp[.,j] = (Xh_r:-c):^(j-1) } st_numscalar("Nh_l", Nh_l[1,1]) st_numscalar("Nh_r", Nh_r[1,1]) if (Nh_l<5 | Nh_r<5){ display("{err}Not enough observations to perform calculations") exit(1) } invGamma_lp = cholinv(quadcross(X_lp,wh_l,X_lp)); invGamma_rp = cholinv(quadcross(X_rp,wh_r,X_rp)) invGammah_lp = cholinv(quadcross(Xh_lp,whh_l,Xh_lp)); invGammah_rp = cholinv(quadcross(Xh_rp,whh_r,Xh_rp)) factor_p = J(p1, 1, .) for (j=1; j<=p1; j++) { factor_p[j] = factorial(j-1) } tau_lp = factor_p:*(invGammah_lp*quadcross(Xh_lp, whh_l, Yh_l)); tau_rp = factor_p:*(invGammah_rp*quadcross(Xh_rp, whh_r, Yh_r)) tau_cl = tau_rp[`deriv'+1,1] - tau_lp[`deriv'+1,1] st_numscalar("tau_cl", tau_cl) tau_T_lp = factor_p:*(invGammah_lp*quadcross(Xh_lp, whh_l, Th_l)) tau_T_rp = factor_p:*(invGammah_rp*quadcross(Xh_rp, whh_r, Th_r)) tau_T_cl = tau_T_rp[`deriv'+1,1] - tau_T_lp[`deriv'+1,1] st_numscalar("tau_T_cl", tau_T_cl) tau_F_cl = tau_cl/tau_T_cl st_numscalar("tau_F_cl", tau_F_cl) } di in yellow "Preliminary RD calculation completed" **frdprelim `y' `x', c(`c') deriv(`deriv') fuzzy(`fuzzy') p(`p') q(`q') h(`h') b(`b') kernel(`kernel') bwselect(`bwselect') local tau_F_prelim = tau_F_cl local tau_T_prelim = tau_T_cl local tau_prelim = tau_cl local h_prelim = `h' local b_prelim = `b' local p1 = `p' + 1 local p2 = `p' + 2 local q1 = `q' + 1 local q2 = `q' + 2 local q3 = `q' + 3 if ("`kernel'"=="epanechnikov" | "`kernel'"=="epa") { local kid=3 local C_pilot=2.34 } else if ("`kernel'"=="uniform" | "`kernel'"=="uni") { local kid=2 local C_pilot=1.84 } else { local kid=1 local C_pilot=2.58 } kconst `p' `deriv' `kid' local C1_h = e(C1) local C2_h = e(C2) kconst `q' `p1' `kid' local C1_b = e(C1) local C2_b = e(C2) kconst `q1' `q1' `kid' local C1_q = e(C1) local C2_q = e(C2) kconst `q' `q' 2 local C1_b_uni = e(C1) local C2_b_uni = e(C2) kconst `q1' `q1' 2 local C1_q_uni = e(C1) local C2_q_uni = e(C2) *********************************************************************** **************************** CCT Approach *********************************************************************** qui su `x', d local h_pilot_CCT = `C_pilot'*min(r(sd),(r(p75)-r(p25))/1.349)*r(N)^(-1/5) mata{ h_pilot_CCT=`h_pilot_CCT' N_l = `N_l' N_r = `N_r' p = `p' q = `q' c = `c' C1_h=`C1_h' C2_h=`C2_h' C1_b=`C1_b' C2_b=`C2_b' C1_q=`C1_q' C2_q=`C2_q' tau_prelim=`tau_prelim' tau_T_prelim=`tau_T_prelim' tau_F_prelim=`tau_F_prelim' deriv = `deriv' p1 = p+1; q1 = q+1; p2 = p+2; q2 = q+2; p3 = p+3; q3 = q+3 /* Y = st_data(.,("`y'"), 0); X = st_data(.,("`x'"), 0); T = st_data(.,("`fuzzy'"),0) X_l = select(X,X:=c) Y_l = select(Y,X:=c) T_l = select(T,X:=c) */ X_lq2 = J(N_l, q+3, .); X_rq2 = J(N_r, q+3, .) for (j=1; j<=q3; j++) { X_lq2[.,j] = (X_l:-c):^(j-1) X_rq2[.,j] = (X_r:-c):^(j-1) } X_lq1 = X_lq2[.,1::q2];X_rq1 = X_rq2[.,1::q2] X_lq = X_lq2[.,1::q1];X_rq = X_rq2[.,1::q1] X_lp = X_lq2[.,1::p1];X_rp = X_rq2[.,1::p1] if ("`bwselect'"=="CCT" | "`bwselect'"=="") { display("Computing Fuzzy CCT Bandwidth Selector.") *** Step 1: q_F_CCT ** Outcome ** mq3_l = cholinv(quadcross(X_lq2,X_lq2))*quadcross(X_lq2,Y_l) mq3_r = cholinv(quadcross(X_rq2,X_rq2))*quadcross(X_rq2,Y_r) m4_l_pilot_CCT = mq3_l[`q3',1]; m4_r_pilot_CCT = mq3_r[`q3',1] w_hpilot_l = kweight(X_l,c,h_pilot_CCT,"`kernel'") w_hpilot_r = kweight(X_r,c,h_pilot_CCT,"`kernel'") sigma_l_pilot = altrdvce(X_l, Y_l, Y_l, `p', `h_pilot_CCT', `matches', "`vce'", "`kernel'") sigma_r_pilot = altrdvce(X_r, Y_r, Y_r, `p', `h_pilot_CCT', `matches', "`vce'", "`kernel'") Gamma_hpilot_lq1 = quadcross(X_lq1, w_hpilot_l, X_lq1) Gamma_hpilot_rq1 = quadcross(X_rq1, w_hpilot_r, X_rq1) Gamma_hpilot_lq = Gamma_hpilot_lq1[1::`q1',1::`q1'] Gamma_hpilot_rq = Gamma_hpilot_rq1[1::`q1',1::`q1'] Gamma_hpilot_lp = Gamma_hpilot_lq1[1::`p1',1::`p1'] Gamma_hpilot_rp = Gamma_hpilot_rq1[1::`p1',1::`p1'] invGamma_hpilot_lq1 = cholinv(Gamma_hpilot_lq1); invGamma_hpilot_rq1 = cholinv(Gamma_hpilot_rq1) invGamma_hpilot_lq = cholinv(Gamma_hpilot_lq); invGamma_hpilot_rq = cholinv(Gamma_hpilot_rq) invGamma_hpilot_lp = cholinv(Gamma_hpilot_lp); invGamma_hpilot_rp = cholinv(Gamma_hpilot_rp) Psi_hpilot_lq1 = quadcross(X_lq1, w_hpilot_l:*sigma_l_pilot:*w_hpilot_l, X_lq1) Psi_hpilot_rq1 = quadcross(X_rq1, w_hpilot_r:*sigma_r_pilot:*w_hpilot_r, X_rq1) Psi_hpilot_lq = Psi_hpilot_lq1[1::`q1',1::`q1'] Psi_hpilot_rq = Psi_hpilot_rq1[1::`q1',1::`q1'] Psi_hpilot_lp = Psi_hpilot_lq1[1::`p1',1::`p1'] Psi_hpilot_rp = Psi_hpilot_rq1[1::`p1',1::`p1'] V_m3_hpilot_CCT = (invGamma_hpilot_lq1*Psi_hpilot_lq1*invGamma_hpilot_lq1)[`q'+2,`q'+2] + (invGamma_hpilot_rq1*Psi_hpilot_rq1*invGamma_hpilot_rq1)[`q'+2,`q'+2] V_m2_hpilot_CCT = (invGamma_hpilot_lq*Psi_hpilot_lq*invGamma_hpilot_lq)[`q'+1,`q'+1] + (invGamma_hpilot_rq*Psi_hpilot_rq*invGamma_hpilot_rq)[`q'+1,`q'+1] V_m0_hpilot_CCT = (invGamma_hpilot_lp*Psi_hpilot_lp*invGamma_hpilot_lp)[`deriv'+1,`deriv'+1] + (invGamma_hpilot_rp*Psi_hpilot_rp*invGamma_hpilot_rp)[`deriv'+1,`deriv'+1] ** First stage ** mq3_T_l = cholinv(quadcross(X_lq2,X_lq2))*quadcross(X_lq2,T_l) mq3_T_r = cholinv(quadcross(X_rq2,X_rq2))*quadcross(X_rq2,T_r) m4_T_l_pilot_CCT = mq3_T_l[`q3',1]; m4_T_r_pilot_CCT = mq3_T_r[`q3',1] sigma_T_l_pilot = altrdvce(X_l, T_l, T_l, `p', `h_pilot_CCT', `matches', "`vce'", "`kernel'") sigma_T_r_pilot = altrdvce(X_r, T_r, T_r, `p', `h_pilot_CCT', `matches', "`vce'", "`kernel'") Psi_hpilot_T_lq1 = quadcross(X_lq1, w_hpilot_l:*sigma_T_l_pilot:*w_hpilot_l, X_lq1) Psi_hpilot_T_rq1 = quadcross(X_rq1, w_hpilot_r:*sigma_T_r_pilot:*w_hpilot_r, X_rq1) Psi_hpilot_T_lq = Psi_hpilot_T_lq1[1::`q1',1::`q1'] Psi_hpilot_T_rq = Psi_hpilot_T_rq1[1::`q1',1::`q1'] Psi_hpilot_T_lp = Psi_hpilot_T_lq1[1::`p1',1::`p1'] Psi_hpilot_T_rp = Psi_hpilot_T_rq1[1::`p1',1::`p1'] V_m3_hpilot_T_CCT = (invGamma_hpilot_lq1*Psi_hpilot_T_lq1*invGamma_hpilot_lq1)[`q'+2,`q'+2] + (invGamma_hpilot_rq1*Psi_hpilot_T_rq1*invGamma_hpilot_rq1)[`q'+2,`q'+2] V_m2_hpilot_T_CCT = (invGamma_hpilot_lq*Psi_hpilot_T_lq*invGamma_hpilot_lq)[`q'+1,`q'+1] + (invGamma_hpilot_rq*Psi_hpilot_T_rq*invGamma_hpilot_rq)[`q'+1,`q'+1] V_m0_hpilot_T_CCT = (invGamma_hpilot_lp*Psi_hpilot_T_lp*invGamma_hpilot_lp)[`deriv'+1,`deriv'+1] + (invGamma_hpilot_rp*Psi_hpilot_T_rp*invGamma_hpilot_rp)[`deriv'+1,`deriv'+1] ** Covariance ** sigma_TY_l_pilot = altrdvce(X_l, T_l, Y_l, `p', `h_pilot_CCT',`matches',"`vce'","`kernel'") sigma_TY_r_pilot = altrdvce(X_r, T_r, Y_r, `p', `h_pilot_CCT',`matches',"`vce'","`kernel'") Psi_hpilot_TY_lq1 = quadcross(X_lq1, w_hpilot_l:*sigma_TY_l_pilot:*w_hpilot_l, X_lq1) Psi_hpilot_TY_rq1 = quadcross(X_rq1, w_hpilot_r:*sigma_TY_r_pilot:*w_hpilot_r, X_rq1) Psi_hpilot_TY_lq = Psi_hpilot_TY_lq1[1::`q1',1::`q1'] Psi_hpilot_TY_rq = Psi_hpilot_TY_rq1[1::`q1',1::`q1'] Psi_hpilot_TY_lp = Psi_hpilot_TY_lq1[1::`p1',1::`p1'] Psi_hpilot_TY_rp = Psi_hpilot_TY_rq1[1::`p1',1::`p1'] V_m3_hpilot_TY_CCT = (invGamma_hpilot_lq1*Psi_hpilot_TY_lq1*invGamma_hpilot_lq1)[`q'+2,`q'+2] + (invGamma_hpilot_rq1*Psi_hpilot_TY_rq1*invGamma_hpilot_rq1)[`q'+2,`q'+2] V_m2_hpilot_TY_CCT = (invGamma_hpilot_lq*Psi_hpilot_TY_lq*invGamma_hpilot_lq)[`q'+1,`q'+1] + (invGamma_hpilot_rq*Psi_hpilot_TY_rq*invGamma_hpilot_rq)[`q'+1,`q'+1] V_m0_hpilot_TY_CCT = (invGamma_hpilot_lp*Psi_hpilot_TY_lp*invGamma_hpilot_lp)[`deriv'+1,`deriv'+1] + (invGamma_hpilot_rp*Psi_hpilot_TY_rp*invGamma_hpilot_rp)[`deriv'+1,`deriv'+1] ** fuzzy variance ** V_m3_hpilot_F_CCT = (1/tau_T_prelim^2)*V_m3_hpilot_CCT + (tau_prelim^2/tau_T_prelim^4)*V_m3_hpilot_T_CCT - (2*tau_prelim/tau_T_prelim^3)*V_m3_hpilot_TY_CCT V_m2_hpilot_F_CCT = (1/tau_T_prelim^2)*V_m2_hpilot_CCT + (tau_prelim^2/tau_T_prelim^4)*V_m2_hpilot_T_CCT - (2*tau_prelim/tau_T_prelim^3)*V_m2_hpilot_TY_CCT V_m0_hpilot_F_CCT = (1/tau_T_prelim^2)*V_m0_hpilot_CCT + (tau_prelim^2/tau_T_prelim^4)*V_m0_hpilot_T_CCT - (2*tau_prelim/tau_T_prelim^3)*V_m0_hpilot_TY_CCT ** bandwidth ** N_q_F_CCT=(2*`q1'+1)*`N'*`h_pilot_CCT'^(2*`q'+3)*V_m3_hpilot_F_CCT *D_q_CCT=2*(`q1'+1-`q1')*(C1_q*(m4_r_pilot_CCT+m4_l_pilot_CCT))^2 D_q_F_CCT=2*(`q1'+1-`q1')*(C1_q*(1/tau_T_prelim*(m4_r_pilot_CCT-(-1)^(deriv+q)*m4_l_pilot_CCT)-tau_prelim/tau_T_prelim^2*(m4_T_r_pilot_CCT-(-1)^(deriv+q)*m4_T_l_pilot_CCT)))^2 q_F_CCT=(N_q_F_CCT/(`N'*D_q_F_CCT))^(1/(2*`q'+5)) *** Step 2: b_CCT ** commented out the regularization stuff for now ** Outcome ** w_q_l=kweight(X_l,c,q_F_CCT,"`kernel'") w_q_r=kweight(X_r,c,q_F_CCT,"`kernel'") *invGamma_q_lq1_CCT = cholinv(quadcross(X_lq1, w_q_l, X_lq1)) *invGamma_q_rq1_CCT = cholinv(quadcross(X_rq1, w_q_r, X_rq1)) *Psi_q_lq1_CCT = quadcross(X_lq1, w_q_l:*sigma_l_pilot:*w_q_l, X_lq1) *Psi_q_rq1_CCT = quadcross(X_rq1, w_q_r:*sigma_r_pilot:*w_q_r, X_rq1) *V_m3_q_CCT = (invGamma_q_lq1_CCT*Psi_q_lq1_CCT*invGamma_q_lq1_CCT)[`q'+2,`q'+2] + (invGamma_q_rq1_CCT*Psi_q_rq1_CCT*invGamma_q_rq1_CCT)[`q'+2,`q'+2] m_lq_CCT = cholinv(quadcross(X_lq1, w_q_l, X_lq1))*quadcross(X_lq1, w_q_l, Y_l) m_rq_CCT = cholinv(quadcross(X_rq1, w_q_r, X_rq1))*quadcross(X_rq1, w_q_r, Y_r) *V_m3_q_CCT= V_m3_q_CCT[1,1] m3_l_CCT= m_lq_CCT[q2,1] m3_r_CCT= m_rq_CCT[q2,1] ** First stage ** m_T_lq_CCT = cholinv(quadcross(X_lq1, w_q_l, X_lq1))*quadcross(X_lq1, w_q_l, T_l) m_T_rq_CCT = cholinv(quadcross(X_rq1, w_q_r, X_rq1))*quadcross(X_rq1, w_q_r, T_r) m3_T_l_CCT = m_T_lq_CCT[q2,1] m3_T_r_CCT = m_T_rq_CCT[q2,1] ** bandwidth ** D_b_F_CCT= 2*(q-p)*(C1_b*(1/tau_T_prelim*(m3_r_CCT - (-1)^(deriv+q+1)*m3_l_CCT)-tau_prelim/tau_T_prelim^2*(m3_T_r_CCT - (-1)^(deriv+q+1)*m3_T_l_CCT)))^2 N_b_F_CCT= (2*p+3)*`N'*`h_pilot_CCT'^(2*`p'+3)*V_m2_hpilot_F_CCT *R_b_CCT= `scaleregul'*2*(q-p)*C1_b^2*3*V_m3_q_CCT *b_CCT= (N_b_CCT / (`N'*(D_b_CCT + R_b_CCT)))^(1/(2*`q'+3)) b_F_CCT= (N_b_F_CCT / (`N'*D_b_F_CCT))^(1/(2*`q'+3)) *** Step 3: h_CCT ** Outcome ** w_b_l=kweight(X_l,`c',b_F_CCT,"`kernel'") w_b_r=kweight(X_r,`c',b_F_CCT,"`kernel'") *invGamma_b_lq_CCT = cholinv(quadcross(X_lq, w_b_l, X_lq)) *invGamma_b_rq_CCT = cholinv(quadcross(X_rq, w_b_r, X_rq)) *Psi_b_lq_CCT = quadcross(X_lq, w_b_l:*sigma_l_pilot:*w_b_l, X_lq) *Psi_b_rq_CCT = quadcross(X_rq, w_b_r:*sigma_r_pilot:*w_b_r, X_rq) *V_m2_b_CCT = (invGamma_b_lq_CCT*Psi_b_lq_CCT*invGamma_b_lq_CCT)[`p2',`p2'] + (invGamma_b_rq_CCT*Psi_b_rq_CCT*invGamma_b_rq_CCT)[`p2',`p2'] m_l_CCT = cholinv(quadcross(X_lq, w_b_l, X_lq))*quadcross(X_lq, w_b_l, Y_l) m_r_CCT = cholinv(quadcross(X_rq, w_b_r, X_rq))*quadcross(X_rq, w_b_r, Y_r) *V_m2_b_CCT = V_m2_b_CCT[1,1] m2_l_CCT= m_l_CCT[`p2',1] m2_r_CCT= m_r_CCT[`p2',1] ** First stage ** m_T_l_CCT = cholinv(quadcross(X_lq, w_b_l, X_lq))*quadcross(X_lq, w_b_l, T_l) m_T_r_CCT = cholinv(quadcross(X_rq, w_b_r, X_rq))*quadcross(X_rq, w_b_r, T_r) m2_T_l_CCT= m_T_l_CCT[`p2',1] m2_T_r_CCT= m_T_r_CCT[`p2',1] ** Bandwidth ** D_h_F_CCT = 2*(`p'+1-`deriv')*(C1_h*(1/tau_T_prelim*(m2_r_CCT - (-1)^(deriv+p+1)*m2_l_CCT)-tau_prelim/tau_T_prelim^2*(m2_T_r_CCT - (-1)^(deriv+p+1)*m2_T_l_CCT)))^2 N_h_F_CCT = (2*`deriv'+1)*`N'*`h_pilot_CCT'^(2*`deriv'+1)*V_m0_hpilot_F_CCT *R_h_CCT = `scaleregul'*2*(`p'+1-`deriv')*(C1_h)^2*3*V_m2_b_CCT h_F_CCT = (N_h_F_CCT / (`N'*D_h_F_CCT))^(1/(2*`p'+3)) st_numscalar("h_F_CCT",h_F_CCT) st_numscalar("q_F_CCT",q_F_CCT) if (`b_calc'==0) { b_F_CCT = h_F_CCT/`rho' } st_numscalar("b_F_CCT",b_F_CCT) } *************************************************************************************************** ******************** IK ************************************************************************************************** if ("`bwselect'"=="IK") { display("Computing IK Bandwidth Selector.") C1_b_uni=`C1_b_uni' C2_b_uni=`C2_b_uni' C1_q_uni=`C1_q_uni' C2_q_uni=`C2_q_uni' ** Density Variance Estimation ** h_pilot_IK = 1.84*sqrt(variance(X))*length(X)^(-1/5) n_l_h1 = length(select(X_l,X_l:>=`c'-h_pilot_IK)) n_r_h1 = length(select(X_r,X_r:<=`c'+h_pilot_IK)) ** Density ** f0_pilot=(n_r_h1+n_l_h1)/(2*`N'*h_pilot_IK) ** Variance and Covariance ** varmat_l=variance((select(Y_l,X_l:>=`c'-h_pilot_IK),select(T_l,X_l:>=`c'-h_pilot_IK))) s2_l_pilot = varmat_l[1,1] s2_T_l_pilot = varmat_l[2,2] s_TY_l_pilot = varmat_l[2,1] if (s2_l_pilot==0){ varmat_l=variance((select(Y_l,X_l:>=`c'-2*h_pilot_IK),select(T_l,X_l:>=`c'-2*h_pilot_IK))) s2_l_pilot = varmat_l[1,1] s2_T_l_pilot = varmat_l[2,2] s_TY_l_pilot = varmat_l[2,1] } varmat_r=variance((select(Y_r,X_r:<=`c'+h_pilot_IK),select(T_r,X_r:<=`c'+h_pilot_IK))) s2_r_pilot = varmat_r[1,1] s2_T_r_pilot = varmat_r[2,2] s_TY_r_pilot = varmat_r[2,1] if (s2_r_pilot==0){ varmat_r=variance((select(Y_r,X_r:<=`c'+2*h_pilot_IK),select(T_r,X_r:<=`c'+2*h_pilot_IK))) s2_r_pilot = varmat_r[1,1] s2_T_r_pilot = varmat_r[2,2] s_TY_r_pilot = varmat_r[2,1] } V_F_IK_pilot = ((s2_r_pilot+s2_l_pilot)/tau_T_prelim^2-2*tau_prelim/tau_T_prelim^3*(s_TY_r_pilot+s_TY_l_pilot)+tau_prelim^2/tau_T_prelim^4*(s2_T_r_pilot+s2_T_l_pilot))/f0_pilot Vm0_pilot_F_IK = C2_h*V_F_IK_pilot Vm2_pilot_F_IK = C2_b*V_F_IK_pilot * Select Median Sample to compute derivative (as in IK code) x_IK_med_l = select(X_l,X_l:>=`medX_l'); y_IK_med_l = select(Y_l,X_l:>=`medX_l'); t_IK_med_l = select(T_l,X_l:>=`medX_l') x_IK_med_r = select(X_r,X_r:<=`medX_r'); y_IK_med_r = select(Y_r,X_r:<=`medX_r'); t_IK_med_r = select(T_r,X_r:<=`medX_r') x_IK_med = x_IK_med_r \ x_IK_med_l y_IK_med = y_IK_med_r \ y_IK_med_l t_IK_med = t_IK_med_r \ t_IK_med_l sample_IK = length(x_IK_med) X_IK_med_q2 = J(sample_IK, `q3', .) for (j=1; j<= `q3' ; j++) { X_IK_med_q2[.,j] = (x_IK_med:-`c'):^(j-1) } X_IK_med_q1 = X_IK_med_q2[.,1::`q2'] * Add cutoff dummy multiplied by polynomial term of X, depending on the design X_IK_med_q2 = (X_IK_med_q2, (x_IK_med:>=c):*((x_IK_med:-`c'):^(`deriv'))) X_IK_med_q1 = (X_IK_med_q1, (x_IK_med:>=c):*((x_IK_med:-`c'):^(`deriv'))) *** Compute b_IK * Pilot Bandwidth N_q_r_pilot_IK = (2*q+3)*C2_q_uni*(s2_r_pilot/f0_pilot) N_q_l_pilot_IK = (2*q+3)*C2_q_uni*(s2_l_pilot/f0_pilot) m4_pilot_IK = (cholinv(quadcross(X_IK_med_q2, X_IK_med_q2))*quadcross(X_IK_med_q2, y_IK_med))[q+3,1] m4_T_pilot_IK = (cholinv(quadcross(X_IK_med_q2, X_IK_med_q2))*quadcross(X_IK_med_q2, t_IK_med))[q+3,1] D_q_pilot_IK = 2*(C1_q_uni*m4_pilot_IK)^2 D_q_T_pilot_IK = 2*(C1_q_uni*m4_T_pilot_IK)^2 h3_r_pilot_IK = (N_q_r_pilot_IK / (N_r*D_q_pilot_IK))^(1/(2*q+5)) h3_l_pilot_IK = (N_q_l_pilot_IK / (N_l*D_q_pilot_IK))^(1/(2*q+5)) h3_T_r_pilot_IK = (N_q_r_pilot_IK / (N_r*D_q_T_pilot_IK))^(1/(2*q+5)) h3_T_l_pilot_IK = (N_q_l_pilot_IK / (N_l*D_q_T_pilot_IK))^(1/(2*q+5)) * Data for derivative X_lq_IK_h3=select(X_lq1,X_l:>=c-h3_l_pilot_IK); Y_l_IK_h3 =select(Y_l,X_l:>=c-h3_l_pilot_IK); T_l_IK_h3 =select(T_l,X_l:>=c-h3_T_l_pilot_IK) X_rq_IK_h3=select(X_rq1,X_r:<=c+h3_r_pilot_IK); Y_r_IK_h3 =select(Y_r,X_r:<=c+h3_r_pilot_IK); T_r_IK_h3 =select(T_r,X_r:<=c+h3_T_r_pilot_IK) X_T_lq_IK_h3=select(X_lq1,X_l:>=c-h3_T_l_pilot_IK); X_T_rq_IK_h3=select(X_rq1,X_r:<=c+h3_T_r_pilot_IK) m3_l_IK = (cholinv(quadcross(X_lq_IK_h3, X_lq_IK_h3))*quadcross(X_lq_IK_h3, Y_l_IK_h3))[q+2,1] m3_r_IK = (cholinv(quadcross(X_rq_IK_h3, X_rq_IK_h3))*quadcross(X_rq_IK_h3, Y_r_IK_h3))[q+2,1] m3_T_l_IK = (cholinv(quadcross(X_T_lq_IK_h3, X_T_lq_IK_h3))*quadcross(X_T_lq_IK_h3, T_l_IK_h3))[q+2,1] m3_T_r_IK = (cholinv(quadcross(X_T_rq_IK_h3, X_T_rq_IK_h3))*quadcross(X_T_rq_IK_h3, T_r_IK_h3))[q+2,1] D_b_F_IK = 2*(q-p)*(C1_b*(1/tau_T_prelim*(m3_r_IK - (-1)^(deriv+q+1)*m3_l_IK)-tau_prelim/tau_T_prelim^2*(m3_T_r_IK - (-1)^(deriv+q+1)*m3_T_l_IK)))^2 N_b_F_IK = (2*p+3)*Vm2_pilot_F_IK * Regularization /*** temp = regconst(`q1',1) con = temp[`q2',`q2'] n_l_h3 = length(Y_l_IK_h3); n_r_h3 = length(Y_r_IK_h3) r_l_b = (con*s2_l_pilot)/(n_l_h3*h3_l_pilot_IK^(2*`q1')) r_r_b = (con*s2_r_pilot)/(n_r_h3*h3_r_pilot_IK^(2*`q1')) R_b_IK = `scaleregul'*2*(q-p)*C1_b^2*3*(r_l_b + r_r_b) ***/ * Final bandwidth: b_F_IK = (N_b_F_IK / (`N'*D_b_F_IK ))^(1/(2*q+3)) *** Step 3: h_IK * Pilot Bandwidth N_b_r_pilot_IK = (2*p+3)*C2_b_uni*(s2_r_pilot/f0_pilot) N_b_l_pilot_IK = (2*p+3)*C2_b_uni*(s2_l_pilot/f0_pilot) m3_pilot_IK = (cholinv(quadcross(X_IK_med_q1, X_IK_med_q1))*quadcross(X_IK_med_q1, y_IK_med))[q+2,1] m3_T_pilot_IK = (cholinv(quadcross(X_IK_med_q1, X_IK_med_q1))*quadcross(X_IK_med_q1, t_IK_med))[q+2,1] D_b_pilot_IK = 2*(q-p)*(C1_b_uni*m3_pilot_IK)^2 D_b_T_pilot_IK = 2*(q-p)*(C1_b_uni*m3_T_pilot_IK)^2 h2_l_pilot_IK = (N_b_l_pilot_IK / (N_l*D_b_pilot_IK))^(1/(2*q+3)) h2_r_pilot_IK = (N_b_r_pilot_IK / (N_r*D_b_pilot_IK))^(1/(2*q+3)) h2_T_l_pilot_IK = (N_b_l_pilot_IK / (N_l*D_b_T_pilot_IK))^(1/(2*q+3)) h2_T_r_pilot_IK = (N_b_r_pilot_IK / (N_r*D_b_T_pilot_IK))^(1/(2*q+3)) * Data for derivative X_lq_IK_h2=select(X_lq,X_l:>=c-h2_l_pilot_IK); Y_l_IK_h2 =select(Y_l,X_l:>=c-h2_l_pilot_IK); T_l_IK_h2 =select(T_l,X_l:>=c-h2_T_l_pilot_IK) X_rq_IK_h2=select(X_rq,X_r:<=c+h2_r_pilot_IK); Y_r_IK_h2 =select(Y_r,X_r:<=c+h2_r_pilot_IK); T_r_IK_h2 =select(T_r,X_r:<=c+h2_T_r_pilot_IK) X_T_lq_IK_h2=select(X_lq,X_l:>=c-h2_T_l_pilot_IK); X_T_rq_IK_h2=select(X_rq,X_r:<=c+h2_T_r_pilot_IK) m2_l_IK = (cholinv(quadcross(X_lq_IK_h2, X_lq_IK_h2))*quadcross(X_lq_IK_h2, Y_l_IK_h2))[p+2,1] m2_r_IK = (cholinv(quadcross(X_rq_IK_h2, X_rq_IK_h2))*quadcross(X_rq_IK_h2, Y_r_IK_h2))[p+2,1] m2_T_l_IK = (cholinv(quadcross(X_T_lq_IK_h2, X_T_lq_IK_h2))*quadcross(X_T_lq_IK_h2, T_l_IK_h2))[p+2,1] m2_T_r_IK = (cholinv(quadcross(X_T_rq_IK_h2, X_T_rq_IK_h2))*quadcross(X_T_rq_IK_h2, T_r_IK_h2))[p+2,1] * Bandwidth D_h_F_IK = 2*(`p'+1-`deriv')*(C1_h*(1/tau_T_prelim*(m2_r_IK - (-1)^(deriv+p+1)*m2_l_IK)-tau_prelim/tau_T_prelim^2*(m2_T_r_IK - (-1)^(deriv+p+1)*m2_T_l_IK)))^2 N_h_F_IK = (2*`deriv'+1)*Vm0_pilot_F_IK h_F_IK = (N_h_F_IK / (`N'*D_h_F_IK))^(1/(2*p+3)) st_numscalar("h_F_IK", h_F_IK) st_numscalar("b_F_IK", b_F_IK) if (`b_calc'==0) { b_F_IK = h_F_IK/`rho' } st_numscalar("b_F_IK",b_F_IK) } } ******************************************************************************* disp "" disp in smcl in gr "Bandwidth Estimators for RD Local Polynomial Regression" disp "" disp "" disp in smcl in gr "{ralign 21: Cutoff c = `c'}" _col(22) " {c |} " _col(23) in gr "Left of " in yellow "c" _col(36) in gr "Right of " in yellow "c" _col(61) in gr "Number of obs = " in yellow %10.0f `N_l'+`N_r' disp in smcl in gr "{hline 22}{c +}{hline 22}" _col(61) in gr "NN Matches = " in yellow %10.0f `matches' disp in smcl in gr "{ralign 21:Number of obs}" _col(22) " {c |} " _col(23) as result %9.0f `N_l' _col(37) %9.0f `N_r' _col(61) in gr "Kernel Type = " in yellow "{ralign 10:`kernel_type'}" disp in smcl in gr "{ralign 21:Order Loc. Poly. (p)}" _col(22) " {c |} " _col(23) as result %9.0f `p' _col(37) %9.0f `p' disp in smcl in gr "{ralign 21:Order Bias (q)}" _col(22) " {c |} " _col(23) as result %9.0f `q' _col(37) %9.0f `q' disp in smcl in gr "{ralign 21:Range of `x'}" _col(22) " {c |} " _col(23) as result %9.3f `range_l' _col(37) %9.3f `range_r' disp "" disp in smcl in gr "{hline 10}{c TT}{hline 35}" disp in smcl in gr "{ralign 9:Method}" _col(10) " {c |} " _col(18) "h" _col(30) "b" _col(41) "rho" _n "{hline 10}{c +}{hline 35}" if ("`bwselect'"=="IK") { disp in smcl in gr "{ralign 9:IK }" _col(10) " {c |} " _col(11) in ye %9.0g h_F_IK _col(25) in ye %9.0g b_F_IK _col(38) in ye %9.0g h_F_IK/b_F_IK } if ("`bwselect'"=="") | ("`bwselect'"=="CCT") { disp in smcl in gr "{ralign 9:CCT}" _col(10) " {c |} " _col(11) in ye %9.0g h_F_CCT _col(25) in ye %9.0g b_F_CCT _col(38) in ye %9.0g h_F_CCT/b_F_CCT } disp in smcl in gr "{hline 10}{c BT}{hline 35}" disp "In comparison, the h and b obtained by treating the outcome equation as a sharp design are `h_prelim' and `b_prelim' respectively." restore return clear return scalar N_l = `N_l' return scalar N_r = `N_r' return scalar c = `c' return scalar p = `p' return scalar q = `q' if ("`bwselect'"=="CCT" | "`bwselect'"=="") { return scalar h_F_CCT = h_F_CCT return scalar b_F_CCT = b_F_CCT } if ("`bwselect'"=="IK") { return scalar h_F_IK = h_F_IK return scalar b_F_IK = b_F_IK } return scalar h_prelim = `h_prelim' return scalar b_prelim = `b_prelim' *mata mata clear end