*! version 1.1.0 URALL: Unified Tests + Full Detailed Footnotes capture program drop urall capture program drop _urall_run_std capture program drop _urall_run_za capture program drop _urall_adf_select_lag capture program drop _urall_center capture program drop _urall_print_stat_p capture program drop _urall_za_get_date capture program drop _urall_za_get_sig program define urall version 11.0 syntax varlist(ts) [if] [in], TEST(string) /// [ /// /* Shared / ADF / PP / ERS Options */ /// CRIT(string) MAXlag(integer 12) PPLAG(integer 4) PPMATCH ERSMETHOD(string) /// /* Zivot-Andrews Options */ /// ZLAGMETHOD(string) ZMAXLAGS(string) ZTRIM(real 0.15) ZLEVEL(real 0.10) /// /* Formatting */ /// TITLE(string) FOOTNOTE(string) /// ] marksample touse local test = upper("`test'") if "`test'"=="RES" | "`test'"=="DFGLS" local test "ERS" if !inlist("`test'", "ADF", "PP", "ERS", "ZA") { di as err "Error: TEST() must be one of: ADF, PP, ERS, or ZA." exit 198 } if "`test'" == "ZA" { if "`title'" == "" local title "Table 1. Zivot-Andrews Unit Root Test (Structural Break)" _urall_run_za `varlist' if `touse', /// zlagmethod(`zlagmethod') zmaxlags(`zmaxlags') /// ztrim(`ztrim') zlevel(`zlevel') title("`title'") } else { _urall_run_std `varlist' if `touse', /// test(`test') crit(`crit') maxlag(`maxlag') /// pplag(`pplag') `ppmatch' ersmethod(`ersmethod') /// title("`title'") footnote("`footnote'") } end * ============================================================================== * SUB-ROUTINE A: STANDARD TESTS (ADF, PP, ERS) * ============================================================================== program define _urall_run_std syntax varlist(ts) [if], TEST(string) [CRIT(string) MAXlag(integer 12) PPLAG(integer 4) PPMATCH ERSMETHOD(string) TITLE(string) FOOTNOTE(string)] marksample touse if "`crit'"=="" local crit "BIC" local crit = upper("`crit'") if "`crit'"=="SIC" local crit "BIC" local ersmethod = upper("`ersmethod'") if "`test'"=="ERS" { if "`ersmethod'"=="" local ersmethod "SIC" if "`ersmethod'"=="BIC" local ersmethod "SIC" capture which ersur if _rc { di as err "Command {bf:ersur} not found. Install via: ssc install ersur" exit 199 } } local cols "L.C L.C+T d.C d.C+T" local nvars : word count `varlist' local ncols : word count `cols' tempname UR_STAT UR_P matrix `UR_STAT' = J(`nvars', `ncols', .) matrix `UR_P' = J(`nvars', `ncols', .) matrix rownames `UR_STAT' = `varlist' matrix rownames `UR_P' = `varlist' matrix colnames `UR_STAT' = `cols' matrix colnames `UR_P' = `cols' local r = 0 foreach v of local varlist { local ++r local L_L_C . local L_L_CT . local L_D_C . local L_D_CT . quietly _urall_adf_select_lag `v' if `touse', maxlag(`maxlag') det(c) crit(`crit') local L_L_C = r(lag) quietly _urall_adf_select_lag `v' if `touse', maxlag(`maxlag') det(ct) crit(`crit') local L_L_CT = r(lag) quietly _urall_adf_select_lag D.`v' if `touse', maxlag(`maxlag') det(c) crit(`crit') local L_D_C = r(lag) quietly _urall_adf_select_lag D.`v' if `touse', maxlag(`maxlag') det(ct) crit(`crit') local L_D_CT = r(lag) if "`test'"=="ADF" { quietly dfuller `v' if `touse', lags(`L_L_C') matrix `UR_STAT'[`r', 1] = r(Zt) matrix `UR_P'[`r', 1] = r(p) quietly dfuller `v' if `touse', lags(`L_L_CT') trend matrix `UR_STAT'[`r', 2] = r(Zt) matrix `UR_P'[`r', 2] = r(p) quietly dfuller D.`v' if `touse', lags(`L_D_C') matrix `UR_STAT'[`r', 3] = r(Zt) matrix `UR_P'[`r', 3] = r(p) quietly dfuller D.`v' if `touse', lags(`L_D_CT') trend matrix `UR_STAT'[`r', 4] = r(Zt) matrix `UR_P'[`r', 4] = r(p) } if "`test'"=="PP" { local P_L_C = cond("`ppmatch'"!="", `L_L_C', `pplag') local P_L_CT = cond("`ppmatch'"!="", `L_L_CT', `pplag') local P_D_C = cond("`ppmatch'"!="", `L_D_C', `pplag') local P_D_CT = cond("`ppmatch'"!="", `L_D_CT', `pplag') quietly pperron `v' if `touse', lags(`P_L_C') matrix `UR_STAT'[`r', 1] = r(Zt) matrix `UR_P'[`r', 1] = r(p) quietly pperron `v' if `touse', lags(`P_L_CT') trend matrix `UR_STAT'[`r', 2] = r(Zt) matrix `UR_P'[`r', 2] = r(p) quietly pperron D.`v' if `touse', lags(`P_D_C') matrix `UR_STAT'[`r', 3] = r(Zt) matrix `UR_P'[`r', 3] = r(p) quietly pperron D.`v' if `touse', lags(`P_D_CT') trend matrix `UR_STAT'[`r', 4] = r(Zt) matrix `UR_P'[`r', 4] = r(p) } if "`test'"=="ERS" { local ridx = . if "`ersmethod'"=="FIX" local ridx = 1 if "`ersmethod'"=="AIC" local ridx = 2 if "`ersmethod'"=="SIC" local ridx = 3 if "`ersmethod'"=="GTS05" local ridx = 4 if "`ersmethod'"=="GTS10" local ridx = 5 tempname R quietly ersur `v' if `touse', noprint maxlag(`maxlag') matrix `R' = r(results) matrix `UR_STAT'[`r',1] = `R'[`ridx',2] matrix `UR_P'[`r', 1] = `R'[`ridx',3] quietly ersur `v' if `touse', noprint maxlag(`maxlag') trend matrix `R' = r(results) matrix `UR_STAT'[`r',2] = `R'[`ridx',2] matrix `UR_P'[`r', 2] = `R'[`ridx',3] quietly ersur D.`v' if `touse', noprint maxlag(`maxlag') matrix `R' = r(results) matrix `UR_STAT'[`r',3] = `R'[`ridx',2] matrix `UR_P'[`r', 3] = `R'[`ridx',3] quietly ersur D.`v' if `touse', noprint maxlag(`maxlag') trend matrix `R' = r(results) matrix `UR_STAT'[`r',4] = `R'[`ridx',2] matrix `UR_P'[`r', 4] = `R'[`ridx',3] } } if "`title'"=="" { if "`test'"=="ADF" local title "Table 1. Unit Root Test (ADF): Test statistic and (p-value)" if "`test'"=="PP" local title "Table 1. Unit Root Test (PP): Test statistic and (p-value)" if "`test'"=="ERS" local title "Table 1. Unit Root Test (ERS/DF-GLS): Test statistic and (p-value)" } local fn "`footnote'" if "`fn'" == "" { if "`test'"=="PP" & "`ppmatch'" != "" local fn "PP lags are set equal to ADF-selected lags using maxlag(`maxlag') and `crit'." if "`test'"=="ERS" local fn "Lag selection method for ERS/DF-GLS (ersur): `ersmethod'." } _urall_print_stat_p, statname(`UR_STAT') pname(`UR_P') test("`test'") title("`title'") footnote("`fn'") end * ============================================================================== * SUB-ROUTINE B: ZIVOT-ANDREWS (ZA) * ============================================================================== program define _urall_run_za syntax varlist(ts) [if], [ZLAGMETHOD(string) ZMAXLAGS(string) ZTRIM(real 0.15) ZLEVEL(real 0.10) TITLE(string)] marksample touse capture which zandrews if _rc { di as err "Error: {bf:zandrews} not found. Install via: ssc install zandrews" exit 199 } if "`zlagmethod'" == "" local zlagmethod "BIC" local method_clean = upper(trim("`zlagmethod'")) local za_opts "" if "`method_clean'" == "INPUT" { if "`zmaxlags'" == "" { di as err "Error: zlagmethod(input) requires zmaxlags(#)." exit 198 } local za_opts "maxlags(`zmaxlags') lagmethod(BIC)" } else { local za_opts "lagmethod(`method_clean')" if "`zmaxlags'" != "" local za_opts "`za_opts' maxlags(`zmaxlags')" if "`method_clean'" == "TTEST" local za_opts "`za_opts' level(`zlevel')" } local za_opts "`za_opts' trim(`ztrim')" quietly tsset local timevar "`r(timevar)'" local timefmt "`r(tsfmt)'" if "`timefmt'" == "" local timefmt "%9.0g" local w_lbl 12 local w_col 20 local pos1 1 local pos2 14 local pos3 34 local pos4 54 local pos5 74 local totw = `pos5' + `w_col' if "`title'" != "" di as txt "`title'" di as txt "{hline `totw'}" di as txt _col(`pos1') "Variable" _continue di _col(`pos2') _continue _urall_center, text("L.C") width(`w_col') di _col(`pos3') _continue _urall_center, text("L.C+T") width(`w_col') di _col(`pos4') _continue _urall_center, text("d.C") width(`w_col') di _col(`pos5') _continue _urall_center, text("d.C+T") width(`w_col') di "" di as txt "{hline `totw'}" foreach var of local varlist { * 1. Level Intercept quietly capture zandrews `var' if `touse', break(intercept) `za_opts' if _rc { local l1_1 "N/A" local l2_1 "" } else { scalar temp_stat = r(tmin) scalar temp_obs = r(tminobs) _urall_za_get_date temp_obs "`timevar'" "`timefmt'" local l1_1 : display %9.3f temp_stat " [" r(date_str) "]" _urall_za_get_sig temp_stat "A" local l2_1 "(`r(sig_str)')" } * 2. Level Both quietly capture zandrews `var' if `touse', break(both) `za_opts' if _rc { local l1_2 "N/A" local l2_2 "" } else { scalar temp_stat = r(tmin) scalar temp_obs = r(tminobs) _urall_za_get_date temp_obs "`timevar'" "`timefmt'" local l1_2 : display %9.3f temp_stat " [" r(date_str) "]" _urall_za_get_sig temp_stat "C" local l2_2 "(`r(sig_str)')" } * 3. Diff Intercept quietly capture zandrews D.`var' if `touse', break(intercept) `za_opts' if _rc { local l1_3 "N/A" local l2_3 "" } else { scalar temp_stat = r(tmin) scalar temp_obs = r(tminobs) _urall_za_get_date temp_obs "`timevar'" "`timefmt'" local l1_3 : display %9.3f temp_stat " [" r(date_str) "]" _urall_za_get_sig temp_stat "A" local l2_3 "(`r(sig_str)')" } * 4. Diff Both quietly capture zandrews D.`var' if `touse', break(both) `za_opts' if _rc { local l1_4 "N/A" local l2_4 "" } else { scalar temp_stat = r(tmin) scalar temp_obs = r(tminobs) _urall_za_get_date temp_obs "`timevar'" "`timefmt'" local l1_4 : display %9.3f temp_stat " [" r(date_str) "]" _urall_za_get_sig temp_stat "C" local l2_4 "(`r(sig_str)')" } * PRINT local vname = substr("`var'", 1, `w_lbl') di as txt _col(`pos1') "`vname'" _continue di _col(`pos2') _continue _urall_center, text("`l1_1'") width(`w_col') di _col(`pos3') _continue _urall_center, text("`l1_2'") width(`w_col') di _col(`pos4') _continue _urall_center, text("`l1_3'") width(`w_col') di _col(`pos5') _continue _urall_center, text("`l1_4'") width(`w_col') di "" di as txt _col(`pos1') "" _continue di _col(`pos2') _continue _urall_center, text("`l2_1'") width(`w_col') di _col(`pos3') _continue _urall_center, text("`l2_2'") width(`w_col') di _col(`pos4') _continue _urall_center, text("`l2_3'") width(`w_col') di _col(`pos5') _continue _urall_center, text("`l2_4'") width(`w_col') di "" di "" } di as txt "{hline `totw'}" * --- FULL ZA FOOTNOTES --- di as txt "Notes: Statistic [Break Date]." di as txt " (Significance Level based on Zivot-Andrews 1992)." di as txt " < 0.01: 1%, < 0.05: 5%, < 0.10: 10%." di as txt " Lag selection: `method_clean' (Max: `zmaxlags'). Trim: `ztrim'." end * ============================================================================== * HELPERS * ============================================================================== program define _urall_center, sclass syntax , TEXT(string) WIDTH(integer) local len = length("`text'") if `len' >= `width' { di "`text'" _continue sreturn local out = substr("`text'", 1, `width') } else { local lpad = int((`width' - `len')/2) di _skip(`lpad') "`text'" _continue sreturn local out " " // dummy } end program define _urall_adf_select_lag, rclass syntax varname(ts) [if], MAXlag(integer) DET(string) CRIT(string) marksample touse tempvar dy ly tr quietly gen double `dy' = D.`varlist' if `touse' quietly gen double `ly' = L.`varlist' if `touse' if "`det'"=="ct" quietly gen double `tr' = _n if `touse' local bestlag = 0 local bestic = . forvalues L = 0/`maxlag' { local dlist "" if `L' > 0 local dlist "L(1/`L').D.`varlist'" if "`det'"=="c" quietly regress `dy' `ly' `dlist' if `touse' else quietly regress `dy' `ly' `tr' `dlist' if `touse' scalar __N = e(N) scalar __rss = e(rss) scalar __k = e(rank) scalar __aic = __N*ln(__rss/__N) + 2*__k scalar __bic = __N*ln(__rss/__N) + ln(__N)*__k local cur = cond("`crit'"=="AIC", __aic, __bic) if missing(`bestic') | (`cur' < `bestic') { local bestic = `cur' local bestlag = `L' } } return scalar lag = `bestlag' end program define _urall_za_get_date, rclass args idx tvar tfmt if "`idx'"!="" & "`idx'"!="." { capture { local val = `tvar'[`idx'] local dstr : display `tfmt' `val' } } return local date_str = trim("`dstr'") end program define _urall_za_get_sig, rclass args stat model local c1 = cond("`model'"=="A", -5.34, -5.57) local c5 = cond("`model'"=="A", -4.80, -5.08) local c10 = cond("`model'"=="A", -4.58, -4.82) if "`stat'"=="" | "`stat'"=="." return local sig_str "" else { if `stat' < `c1' return local sig_str "< 0.01" else if `stat' < `c5' return local sig_str "< 0.05" else if `stat' < `c10' return local sig_str "< 0.10" else return local sig_str "> 0.10" } end program define _urall_print_stat_p syntax , STATname(name) Pname(name) TEST(string) [TITLE(string) FOOTNOTE(string)] local rnames : rownames `statname' local cnames : colnames `statname' local nrows : word count `rnames' local ncols : word count `cnames' local varw 12 local colw 12 local totw = `varw' + 3 + `ncols'*`colw' if "`title'" != "" di as txt "`title'" di as txt "{hline `totw'}" di as txt _col(1) "Variable" _continue local pos = `varw' + 3 forvalues j = 1/`ncols' { local cn : word `j' of `cnames' di _col(`pos') _continue _urall_center, text("`cn'") width(`colw') local pos = `pos' + `colw' } di "" di as txt "{hline `totw'}" tempname s p forvalues i = 1/`nrows' { local rn : word `i' of `rnames' if length("`rn'") > `varw' local rn = substr("`rn'",1,`varw') di as txt _col(1) "`rn'" _continue * Stat Line local pos = `varw' + 3 forvalues j = 1/`ncols' { scalar `s' = `statname'[`i',`j'] local stxt : display %9.4f `s' di _col(`pos') _continue _urall_center, text("`stxt'") width(`colw') local pos = `pos' + `colw' } di "" * P-value Line di as txt _col(1) "" _continue local pos = `varw' + 3 forvalues j = 1/`ncols' { scalar `p' = `pname'[`i',`j'] if missing(`p') local pcell "(.)" else { local ptxt : display %6.4f `p' local pcell "(`ptxt')" } di _col(`pos') _continue _urall_center, text("`pcell'") width(`colw') local pos = `pos' + `colw' } di "" } di as txt "{hline `totw'}" * --- FULL STANDARD FOOTNOTES --- di as txt "Note: p-values are reported in parentheses." di as txt " L denotes level and d denotes first difference." di as txt " C denotes Constant, T denotes Trend, and C+T denotes Constant and Trend." if "`test'"=="ADF" | "`test'"=="PP" { di as txt " Reported p-values are based on MacKinnon (1996) one-sided critical values." } else if "`test'"=="ERS" { di as txt " Reported p-values are based on response-surface approximations for the ERS/DF-GLS test." } if "`footnote'" != "" { di as txt " `footnote'" } end