********************************** *** This section does "tf" *** ********************************** program define tf, eclass ereturn clear version 12.0 local lversion = "01" local ivreg2_command = "`0'" if "`ivreg2_command'"== ", version" { di in gr "`lversion'" ereturn clear ereturn local version `lversion' exit } // check ivreg2 version quietly ivreg2, version // if e(version) != "04.1.11" { // di as err "Please install ivreg2 version 04.1.11" // exit //} local unsupported = 0 // If the user uses these options, just do ivreg2 and exit. local options "gmm2s liml fuller kclass coviv cue b0 bw kernel wmatrix smatrix orthog endog redundant small noconstant nocollin noid partial level nofooter noheader replay dkraay kiefer hascons eform depname plus" foreach option of local options { if strpos("`0'", "`option'") != 0 { ivreg2 `ivreg2_command' di as err "Displaying ivreg2 results only. No tF adjustment." di as err "ivreg3 does not currently support the `option' option." local unsupported = 1 exit } } if `unsupported' == 1 { exit } else { // ensures proper syntax. if there's a typo or additional option, // this will return an error. syntax [anything(name=0)] [if] [in] [aw fw pw iw/] [, /// FIRST FFIRST SAVEFIRST SAVEFPrefix(name) /// RF SAVERF SAVERFPrefix(name) /// SFIRST SAVESFIRST SAVESFPrefix(name) /// Robust CLuster(varlist) /// ] // Use ivreg2 first option to check if just-id with 1 endogenous regressor if "`first'" == "" & strpos("`ivreg2_command'", ",") == 0 { local ivreg2_command_first = "`ivreg2_command', first" } else if "`first'" == "" & strpos("`ivreg2_command'", ",") != 0 { local ivreg2_command_first = "`ivreg2_command' first" } else { local ivreg2_command_first = "`ivreg2_command'" } // run ivreg2, suppress output quietly ivreg2 `ivreg2_command_first' // Generate tempvar to mark sample tempvar temp1 gen `temp1'=e(sample) // if just a first-stage, exit after doing first-stage if "`e(model)'" == "ols" { ivreg2 `ivreg2_command' exit } // Check to see if just-id with 1 endogenous regressor. matrix A = e(first) matrix C = A["df", 1] // if not, simply display ivreg2 output. if e(jdf) != 0 | C[1,1] != 1 { ivreg2 `0' di as err "The model either has multiple endogenous regressors or is not just-identified." di as err "Displaying ivreg2 results only. No tF adjustment." cap drop _est__ivreg2_`instd' exit } // Otherwise, we branch into doing tF. // first, get some locals from ivreg2 local N = e(N) local insts = e(insts) local depvar = e(depvar) local varnm = abbrev("`e(instd)'", 10) local depvar_ab = abbrev("`depvar'", 10) local ex_inst = e(exexog) local in_insts = e(inexog) local beta_hat = e(b)[1,1] local round_beta_hat = round(`beta_hat', 0.00001) local instd = e(instd) local se_bhat = _se[`instd'] matrix b = e(b) matrix V = e(V) // and display unadjusted ivreg2 results di as text " " di as text " " di as text "IV (2SLS) estimation" di as text "{hline 20}" di as text " " di as text "{col 54}" "Number of obs" "{col 68}" "=" "{col 71}" as result %8.0f `N' di as text "{col 54}" "F(" e(Fdf1) ", " e(Fdf2) ")" "{col 68}" "=" "{col 71}" as result %8.4f e(F) di as text "{col 54}" "Prob > F" "{col 68}" "=" "{col 71}" as result %8.4f e(Fp) di as text "Total (centered) SS" "{col 24}" "=" "{col 27}" as result %9.5f e(yyc) "{col 54}" as text "Centered R2" "{col 68}" "=" "{col 71}" as result %8.4f e(r2c) di as text "Total (uncentered) SS" "{col 24}" "=" "{col 27}" as result %9.5f e(yy) "{col 54}" as text "Uncentered R2" "{col 68}" "=" "{col 71}" as result %8.4f e(r2u) di as text "Residual SS" "{col 24}" "=" "{col 27}" as result %9.5f e(rss) "{col 54}" as text "Root MSE" "{col 68}" "=" "{col 71}" as result %8.4f e(rmse) di as text " " // Get options for the correct first-stage. if "`weight'" != "" { local weight_exp = "[`weight' = `exp']" } else if "`weight'" == "" { local weight_exp = "" } // Modify `if' to ensure it's the same sample if "`if'" != "" { local if = "`if' & `temp1' ==1" } else if "`if'" == "" { local if = "if `temp1' ==1" } if "`cluster'" ~= "" { local first_stage = "`e(instd)' `e(insts)' `if' `in' `weight_exp', cluster(`cluster')" } else if "`robust'" ~= "" { local first_stage = "`e(instd)' `e(insts)' `if' `in' `weight_exp', robust" } else if "`robust'`cluster'"=="" { local first_stage = "`e(instd)' `e(insts)' `if' `in' `weight_exp'" } // display unadj. 2SLS results ereturn clear ereturn post b V ereturn display // run and display first-stage di as text " " di as text " " ivreg2 `first_stage' // Get the F-statistic that we need. local z_beta = _b["`ex_inst'"] local z_se = _se["`ex_inst'"] local F = (`z_beta'/`z_se')^2 di as text "First-Stage F-Stat: " as result %9.5f `F' // do tF adjustments // first for 95% (alpha = 0.05) local sig_level = 0.05 local q = (invnormal(1 - (`sig_level'/2)))^2 mata: a = fileexists("IV_CriticalValues_matrix_95.mmat") mata: st_local("a", strofreal(a)) if `a' != 1 { mata: alpha = strtoreal(st_local("sig_level")) mata: createZ(alpha, "IV_CriticalValues_matrix_95.mmat") } // Based on F-statistic get the inflation factor mata: F = strtoreal(st_local("F")) mata: file_in = fopen("IV_CriticalValues_matrix_95.mmat", "r") mata: S = fgetmatrix(file_in) mata: zF = spline3eval(S, F) mata: sig_level = st_local("sig_level") mata: cF = zF/(F - (invnormal(1 - (strtoreal(sig_level)/2))^2)) mata: if (F>104.67) cF = (invnormal(1 - (strtoreal(sig_level)/2)))^2;; mata: st_local("cF", strofreal(cF)) // calculate the tF adjusted SE and 95% CI if (`F'< ((invnormal(1 - (`sig_level'/2)))^2)) { local tF_se = `se_bhat' * (sqrt(`cF')/((invnormal(1 - (`sig_level'/2))))) local tf_LB = . local tf_UB = . } else if (`F' < 104.67 & `F' >= ((invnormal(1 - (`sig_level'/2)))^2)) { local tF_se = `se_bhat' * (sqrt(`cF')/((invnormal(1 - (`sig_level'/2))))) } // if F>104.67, result will duplicate ivreg2 result else if (`F' >= 104.67) { local tF_se = `se_bhat' } if `F' >= ((invnormal(1 - (`sig_level'/2)))^2) { local tf_LB = `beta_hat' - ((invnormal(1 - (`sig_level'/2))))*`tF_se' local tf_UB = `beta_hat' + ((invnormal(1 - (`sig_level'/2))))*`tF_se' } // next for 99% (alpha = 0.01) local sig_level = 0.01 local q = (invnormal(1 - (`sig_level'/2)))^2 mata: a = fileexists("IV_CriticalValues_matrix_99.mmat") mata: st_local("a", strofreal(a)) if `a' != 1 { mata: alpha = strtoreal(st_local("sig_level")) mata: createZ(alpha, "IV_CriticalValues_matrix_99.mmat") } // Based on F-statistic get the inflation factor mata: F = strtoreal(st_local("F")) mata: file_in = fopen("IV_CriticalValues_matrix_99.mmat", "r") mata: S = fgetmatrix(file_in) mata: zF = spline3eval(S, F) mata: sig_level = st_local("sig_level") mata: cF = zF/(F - (invnormal(1 - (strtoreal(sig_level)/2))^2)) mata: if (F>252.34) cF = (invnormal(1 - (strtoreal(sig_level)/2)))^2;; mata: st_local("cF_99", strofreal(cF)) if (`F'< (2.726^2)) { local tF_se_01 = `se_bhat' * (sqrt(`cF_99')/((invnormal(1 - (`sig_level'/2))))) local tf_LB_01 = . local tf_UB_01 = . } else if (`F' < 252.34 & `F' >= (2.726^2)) { local tF_se_01 = `se_bhat' * (sqrt(`cF_99')/((invnormal(1 - (`sig_level'/2))))) } // if F>252.34, result will duplicate ivreg2 result else if (`F' >= 252.34) { local tF_se_01 = `se_bhat' } if `F' >= (2.726^2) { local tf_LB_01 = `beta_hat' - ((invnormal(1 - (`sig_level'/2))))*`tF_se_01' local tf_UB_01 = `beta_hat' + ((invnormal(1 - (`sig_level'/2))))*`tF_se_01' } // define some locals to return and display local critical_value_05 = sqrt(`cF') local critical_value_01 = sqrt(`cF_99') local unadj_LB = `beta_hat' - ((invnormal(1 - (`sig_level'/2))))*`se_bhat' local unadj_UB = `beta_hat' + ((invnormal(1 - (`sig_level'/2))))*`se_bhat' // display tF adjusted results di as text " " di as text " " di as text "tF adjusted Results at the 5% Level" di as text "{hline 35}" if `tf_LB'==. { display as text "{hline 13}{c +}{hline 67}" display as text "{col 13}" " {c |}" "{col 27}" "Unadj." "{col 37}" "Crit. Val." "{col 50}" "0.05 tF" "{col 69}" "Adj." display as text %12s "`depvar_ab'" " {c |}" "{col 18}" as text "Coef." "{col 26}" "Std. Err." "{col 38}" "for |t|" "{col 49}" "Std. Err." "{col 60}" "[95% Conf." "{col 73}" "Interval]" display as text "{hline 13}{c +}{hline 67}" display as text %12s "`varnm'" "{col 13}" " {c |}" as result `beta_hat' "{col 26}" `se_bhat' "{col 40}" "inf" "{col 52}" "inf" "{col 63}" "-inf" "{col 75}" "inf" display as text "{hline 13}{c +}{hline 67}" } else { display as text "{hline 13}{c +}{hline 67}" display as text "{col 13}" " {c |}" "{col 27}" "Unadj." "{col 37}" "Crit. Val." "{col 50}" "0.05 tF" "{col 69}" "Adj." display as text %12s "`depvar_ab'" " {c |}" "{col 18}" as text "Coef." "{col 26}" "Std. Err." "{col 38}" "for |t|" "{col 49}" "Std. Err." "{col 60}" "[95% Conf." "{col 73}" "Interval]" display as text "{hline 13}{c +}{hline 67}" display as text %12s "`varnm'" "{col 13}" " {c |}" as result `beta_hat' "{col 26}" `se_bhat' "{col 38}" `critical_value_05' "{col 49}" `tF_se' "{col 61}" `tf_LB' "{col 72}" `tf_UB' display as text "{hline 13}{c +}{hline 67}" } di as text " " di as text "tF adjusted Results at the 1% Level" di as text "{hline 35}" if `tf_LB_01'==. { display as text "{hline 13}{c +}{hline 67}" display as text "{col 13}" " {c |}" "{col 27}" "Unadj." "{col 37}" "Crit. Val." "{col 50}" "0.01 tF" "{col 69}" "Adj." display as text %12s "`depvar_ab'" " {c |}" "{col 18}" as text "Coef." "{col 26}" "Std. Err." "{col 38}" "for |t|" "{col 49}" "Std. Err." "{col 60}" "[99% Conf." "{col 73}" "Interval]" display as text "{hline 13}{c +}{hline 67}" display as text %12s "`varnm'" "{col 13}" " {c |}" as result `beta_hat' "{col 26}" `se_bhat' "{col 40}" "inf" "{col 52}" "inf" "{col 63}" "-inf" "{col 75}" "inf" display as text "{hline 13}{c +}{hline 67}" } else { display as text "{hline 13}{c +}{hline 67}" display as text "{col 13}" " {c |}" "{col 27}" "Unadj." "{col 37}" "Crit. Val." "{col 50}" "0.01 tF" "{col 69}" "Adj." display as text %12s "`depvar_ab'" " {c |}" "{col 18}" as text "Coef." "{col 26}" "Std. Err." "{col 38}" "for |t|" "{col 49}" "Std. Err." "{col 60}" "[99% Conf." "{col 73}" "Interval]" display as text "{hline 13}{c +}{hline 67}" display as text %12s "`varnm'" "{col 13}" " {c |}" as result `beta_hat' "{col 26}" `se_bhat' "{col 38}" `critical_value_01' "{col 49}" `tF_se_01' "{col 61}" `tf_LB_01' "{col 72}" `tf_UB_01' display as text "{hline 13}{c +}{hline 67}" } di as text " " di as text "Instrumented: `instd'" di as text "Excluded instrument: `ex_inst'" di as text "Included instrument: `in_insts'" // do not return ivreg2 results in e() ereturn clear cap drop _est__ivreg2_`instd' // return tF things in e() ereturn local N = `N' ereturn local F = `F' ereturn local tF_LB_05 = "`tf_LB'" ereturn local tF_UB_05 = "`tf_UB'" ereturn local beta_hat = `beta_hat' ereturn local tF_se_beta_hat_05 = `tF_se' ereturn local instd = "`instd'" ereturn local insts = "`insts'" ereturn local depvar = "`depvar'" ereturn local tF_critical_value_05 = `critical_value_05' ereturn local tF_critical_value_01 = `critical_value_01' ereturn local unadj_se = `se_bhat' ereturn local unadj_LB = `unadj_LB' ereturn local unadj_UB = `unadj_UB' ereturn local tF_LB_01 = "`tf_LB_01'" ereturn local tF_UB_01 = "`tf_UB_01'" ereturn local tF_se_beta_hat_01 = `tF_se_01' // close any files still open in mata forvalues i=0(1)50 { capture mata: fclose(`i') } } end ********************************************** *** This section generates critical values *** ********************************************** version 12 mata: void createZ(real scalar alph, file_name) { // set some constants //alph = 0.05 q = invnormal(1 - (alph/2))^2 obs = 400000 // empty mata matrix real matrix A A = J(obs, 5, .) // list of epsilon to loop through eps_list = range(0.0000001, 0.00009, 0.0000001) // this is a list of epsilon to loop through eps = 0.00000009 // this is an initial epsilon value // Initialize, this chunck of code fills in the first row of matrix A // F1 A[1,1] = q :+ eps // this fills in row 1, column 1 (e.g. the first F1) // z(F1) A[1,2] = ((q):^3):-(((3:*(q)):-(((q):^2):/2):+(((q):^3):/6)):*(A[1,1]:-(q))) // f0 A[1,3] = (A[1,1]):/((sqrt((A[1,2]):/(A[1,1]:-(q)))):-(sqrt(A[1,1]))) // F A[1,4] = ((A[1,3]):+(invnormal((1:-alph):+(normal((-sqrt(A[1,1])):-(A[1,3])))))):^2 F = A[1,4] // z(F) A[1,5] = (((A[1,4]):*((sqrt(A[1,4]):-A[1,3]):^2)):/(A[1,3]:^2)):*(A[1,4]:-q) j = 1 // set a counter for the loop // Iterate. Now F becomes the new F1 (for A[2, 1]), and we iterate to fill in the data. for(i = 2; i <= obs; i++) { if(j>898) break // we can only iterate for the number of epsilons we have in the list // when f0 becomes negative, re-initialize with new epsilon if(A[(i:-1), 3]:<0) { eps = eps_list[j] j = j+1 A[i,1] = q :+ eps A[i,2] = ((q):^3):-(((3:*(q)):-(((q):^2):/2):+(((q):^3):/6)):*(A[i,1]:-(q))) } // keep doing the algorithm and computing values else { // set F1 A[i, 1] = A[(i:-1), 4] // set zF1 A[i, 2] = A[(i:-1), 5] } // set f0 A[i, 3] = (A[i,1]):/((sqrt((A[i, 2]):/(A[i,1]:-(q)))):-(sqrt(A[i,1]))) // set F A[i, 4] = ((A[i,3]):+(invnormal((1:-alph):+(normal((-sqrt(A[i,1])):-(A[i,3])))))):^2 // set zF A[i, 5] = (((A[i,4]):*((sqrt(A[i,4]):-A[i,3]):^2)):/(A[i,3]:^2)):*(A[i,4]:-q) } // keep only rows without missing values A = select(A, rowmissing(A):==0) // sort by F A = sort(A, 4) // pull F and zF as vectors F = A[., 4] Z = A[., 5] // spline3 S = spline3(F, Z) file_out = fopen(file_name, "w") fputmatrix(file_out, S) fclose(file_out) } end