*! asycaus_static v1.0.0 24may2026 *! Hatemi-J (2012) Asymmetric Causality Test with leverage bootstrap (Hacker-Hatemi-J 2006) *! Author: Dr Merwan Roudane (merwanroudane920@gmail.com) program define asycaus_static, rclass version 14.0 syntax varlist(min=2 max=2 numeric) [if] [in] [, MAXLag(integer 8) IC(string) INTOrder(integer 1) SHOCK(string) BOOT(integer 1000) SEED(integer 12345) LNform noGRAPH SAVing(string) ] _asycaus_check_tsset marksample touse tokenize `varlist' local depvar `1' local causvar `2' if "`ic'" == "" local ic hjc _asycaus_iccode `ic' local icnum = r(ic) if "`shock'" == "" local shock pos local shock = lower("`shock'") if !inlist("`shock'", "pos", "positive", "neg", "negative", "both") { di as err "shock() must be one of: pos | neg | both" exit 198 } // Extract numeric matrix into Mata qui keep if `touse' if "`lnform'" != "" { tempvar _ld _lc qui gen double `_ld' = ln(`depvar') qui gen double `_lc' = ln(`causvar') tempname Yraw qui mkmat `_ld' `_lc', matrix(`Yraw') } else { tempname Yraw qui mkmat `depvar' `causvar', matrix(`Yraw') } // Loop over chosen shocks local shocks if inlist("`shock'", "pos", "positive", "both") local shocks `shocks' pos if inlist("`shock'", "neg", "negative", "both") local shocks `shocks' neg local nshocks : word count `shocks' // Storage for output table (one row per shock) tempname Restab matrix `Restab' = J(`nshocks', 6, .) local rowlabs "" local idx = 0 foreach s of local shocks { local ++idx local pflag = cond("`s'" == "pos", 1, 0) local stitle = cond("`s'" == "pos", "POSITIVE", "NEGATIVE") mata: st_matrix("Zcomp", asycaus_pos_neg(st_matrix("`Yraw'"), `pflag')) mata: st_local("nn", strofreal(rows(st_matrix("Zcomp")))) // Select lag via chosen IC mata: st_local("p_opt", strofreal( /// asycaus_lag_select(st_matrix("Zcomp"), 1, `maxlag', `icnum'))) local p = `p_opt' // H0: causvar (col 2) does NOT cause depvar (col 1) mata: st_matrix("wres", asycaus_wald(st_matrix("Zcomp"), `p', /// `intorder', 1, 2)) local W = wres[1,1] local dof = wres[1,2] // Bootstrap critical values mata: st_matrix("cv", asycaus_boot_cv(st_matrix("Zcomp"), `p', /// `intorder', 1, 2, `boot', `seed')) local cv1 = cv[1,1] local cv5 = cv[1,2] local cv10 = cv[1,3] // Asymptotic p-value local pchi = chi2tail(`dof', `W') // Fill row idx in result matrix matrix `Restab'[`idx', 1] = `W' matrix `Restab'[`idx', 2] = `p' matrix `Restab'[`idx', 3] = `dof' matrix `Restab'[`idx', 4] = `cv10' matrix `Restab'[`idx', 5] = `cv5' matrix `Restab'[`idx', 6] = `cv1' local rowlabs `"`rowlabs' "`stitle'""' } // ----------- PROFESSIONAL TABLE ----------- _asycaus_header "Asymmetric Causality Test — Hatemi-J (2012)" di as txt _col(2) "H0: " as res "`causvar'" as txt " does not Granger-cause " as res "`depvar'" di as txt _col(2) "Lag selection: " as res "`=upper("`ic'")'" di as txt _col(2) "Augmentation lags (max integration): " as res "`intorder'" di as txt _col(2) "Bootstrap replications: " as res "`boot'" di as txt _col(2) "Sample size (after differencing): " as res "`nn'" di as txt "{hline 78}" di as txt _col(2) "{ralign 10:Shock}" /// _col(15) "{ralign 11:Wald}" /// _col(27) "{ralign 5:Lag}" /// _col(33) "{ralign 11:Asy p-val}" /// _col(46) "{ralign 10:CV 10%}" /// _col(57) "{ralign 10:CV 5%}" /// _col(68) "{ralign 10:CV 1%}" di as txt "{hline 78}" local i = 1 foreach s of local shocks { local W = `Restab'[`i', 1] local p = `Restab'[`i', 2] local dof = `Restab'[`i', 3] local c10 = `Restab'[`i', 4] local c5 = `Restab'[`i', 5] local c1 = `Restab'[`i', 6] local pchi = chi2tail(`dof', `W') local lbl = cond("`s'" == "pos", "Positive", "Negative") local star = "" if `W' > `c1' local star "***" else if `W' > `c5' local star "**" else if `W' > `c10' local star "*" di as res _col(2) "{ralign 10:`lbl'}" /// _col(15) %11.4f `W' /// _col(27) %5.0f `p' /// _col(33) %11.4f `pchi' /// _col(46) %10.4f `c10' /// _col(57) %10.4f `c5' /// _col(68) %10.4f `c1' " " "`star'" local i = `i' + 1 } di as txt "{hline 78}" di as txt _col(2) "Significance: * 10% ** 5% *** 1% (leverage-adjusted bootstrap CVs)" di as txt _col(2) "Reject H0 if Wald > bootstrap CV at the chosen level." _asycaus_footer // ----------- GRAPH ----------- if "`graph'" != "nograph" { _asycaus_static_graph `"`Restab'"' `"`shocks'"' "`depvar'" "`causvar'" `"`saving'"' } // Return return matrix results = `Restab' return scalar boot = `boot' return scalar maxlag = `maxlag' return local shock "`shock'" return local ic "`ic'" return local depvar "`depvar'" return local cause "`causvar'" return local test "Hatemi-J (2012) Asymmetric Causality" end program define _asycaus_static_graph args results shocks dep cause saving tempname B matrix `B' = `results' local nrow = rowsof(`B') preserve qui drop _all qui set obs `nrow' qui gen str10 shock = "" qui gen double Wald = . qui gen double cv10 = . qui gen double cv5 = . qui gen double cv1 = . local i 1 foreach s of local shocks { local lbl = cond("`s'" == "pos", "Positive", "Negative") qui replace shock = "`lbl'" in `i' qui replace Wald = `B'[`i', 1] in `i' qui replace cv10 = `B'[`i', 4] in `i' qui replace cv5 = `B'[`i', 5] in `i' qui replace cv1 = `B'[`i', 6] in `i' local i = `i' + 1 } qui gen idx = _n label define _shk 1 "Positive" 2 "Negative" local note = `"Note: Bootstrap critical values (leverage-adjusted) at 10%, 5% and 1%. Reference: Hatemi-J (2012)."' twoway /// (bar Wald idx, barwidth(0.55) fcolor(navy*0.7) lcolor(navy)) /// (scatter cv10 idx, msymbol(diamond) mcolor(green) msize(small)) /// (scatter cv5 idx, msymbol(triangle) mcolor(orange) msize(small)) /// (scatter cv1 idx, msymbol(X) mcolor(cranberry) msize(small)) /// , xlabel(1 "Positive" 2 "Negative", noticks) /// legend(order(1 "Wald statistic" 2 "10% CV" 3 "5% CV" 4 "1% CV") /// rows(1) region(lcolor(none))) /// ytitle("Test statistic") /// xtitle("") /// title("Asymmetric Causality: {it:`cause'} → {it:`dep'}", size(medium)) /// subtitle("Hatemi-J (2012) — leverage bootstrap CVs", size(small)) /// note(`"`note'"', size(vsmall)) /// graphregion(color(white)) plotregion(lcolor(black)) /// scheme(s1color) name(asycaus_static, replace) restore if `"`saving'"' != "" { graph save asycaus_static `"`saving'"', replace } end