* Maximo Sangiacomo * Nov. 2018 * v 4.0 * Based on: Pesaran, M. H. (2007). "A Simple Panel Unit Root Test In The Presence Of Cross-section Dependence." * Journal Of Applied Econometrics 22: 265–312 program define xtcips, rclass version 9 syntax varname(ts) [if] [in] , MAXLags(numlist min=1 max=1 int >=1) BGLags(numlist int >=1) [ Q Trend Noc ] qui tsset local id `r(panelvar)' local time `r(timevar)' if ("`noc'"!=""&"`trend'"!="") { disp in smcl in r "{opt noconstant} cannot be used with the {opt trend} option" error 198 } tempname Vals pgr cv tempvar vvar vvarm dvvar dvvarm res local case 2 local text "constant" scalar k1 = 6.19 scalar k2 = 2.61 if "`noc'" != "" { local noc ", noc" local case 1 local text "no constant nor trend" scalar k1 = 6.12 scalar k2 = 4.16 } if "`trend'" != "" { local trend "`time'" local case 3 local text "constant & trend" scalar k1 = 6.42 scalar k2 = 1.70 } marksample touse markout `touse' `time' qui tsreport if `touse', report panel if r(N_gaps) { di in red "sample may not contain gaps" error 198 } qui xtsum `time' if `touse' local N `r(n)' local T `r(Tbar)' if int(`T')*`N' != r(N) { di in red "panel must be balanced" error 198 } local tmin `r(min)' local tmax `r(max)' * copy variable to prevent alteration and allow ts ops qui gen double `vvar' = `varlist' if `touse' * cross-section averages qui gen double `vvarm' = . if `touse' qui gen double `dvvarm' = . if `touse' qui gen double `dvvar' = D.`vvar' if `touse' local vvarm "`vvarm'" local dvvarm "`dvvarm'" forv t = `tmin'/`tmax' { qui { sum `vvar' if `time' == `t' & `touse' replace `vvarm' = r(mean) if `time' == `t' & `touse' sum `dvvar' if `time' == `t' & `touse' replace `dvvarm' = r(mean) if `time' == `t' & `touse' } } * define unit identifier qui tab `id' if `touse', matrow(`Vals') local nvals = r(r) local i = 1 while `i' <= `nvals' { local val = `Vals'[`i',1] local vals "`vals' `val'" local ++i } *Lags criterion decision *Q if "`q'" != "" { qui { foreach i of local vals { local psr`i' = 0 local tpsr`i' reg D.`vvar' L.`vvar' L.`vvarm' `dvvarm' `trend' if `id' == `i' & `touse' `noc' predict `res' if `id' == `i' & `touse', resid wntestq `res' if `id' == `i' & `touse' scalar tsq`i' = r(p) drop `res' while (scalar(tsq`i')<.05 & `psr`i'' <= `maxlags') { local ++psr`i' local tpsr`i' "L(1/`psr`i'')D.`vvar' L(1/`psr`i'').`dvvarm'" reg D.`vvar' L.`vvar' L.`vvarm' `dvvarm' `tpsr`i'' `trend' if `id' == `i' & `touse' `noc' predict `res' if `id' == `i' & `touse', resid wntestq `res' if `id' == `i' & `touse' scalar tsq`i' = r(p) drop `res' } } } } *F else { qui { foreach num of numlist 1/`maxlags' { local list L`num'D.`vvar' L`num'.`dvvarm' local list_t "`list_t' `list'" } local psr = `maxlags' local tpsr "L(1/`psr')D.`vvar' L(1/`psr').`dvvarm'" local lag1 = `maxlags'-1 foreach i of local vals { local list_t`i' "`list_t'" local tpsr`i' local psr`i' = 0 reg D.`vvar' L.`vvar' L.`vvarm' `dvvarm' `tpsr' `trend' if `id' == `i' & `touse' `noc' test `list_t' scalar tsf`i' = r(p) if scalar(tsf`i')<.05 & `lag1' > 0 { while (scalar(tsf`i')<.05 & `psr`i'' < `maxlags') { local ++psr`i' gettoken first list_t`i': list_t`i' gettoken first list_t`i': list_t`i' test `list_t`i'' scalar tsf`i' = r(p) local tpsr`i' "L(1/`psr`i'')D.`vvar' L(1/`psr`i'').`dvvarm'" } } } } } *B-G lags local bgnpi : word count `bglags' local bgslags : list sort bglags local bgmaxlag : word `bgnpi' of `bgslags' if `bgnpi' == 1 { foreach i of local vals { local bgps`i' = `bglags' } } else if `bgnpi' != `N' { di in r "Error: `N' panel units, either 1 or `N' lag lengths must be specified in Breusch-Godfrey" error 198 } else { local j = 0 foreach i of local vals { local ++j local bgps`i' : word `j' of `bglags' } } *Panel Unit Root Test scalar cips = 0 scalar nt = 0 foreach i of local vals { qui { reg D.`vvar' L.`vvar' L.`vvarm' `dvvarm' `tpsr`i'' `trend' if `id' == `i' & `touse' `noc' mat b = e(b) mat v = e(V) scalar nt = nt + e(N) scalar _tst = b[1,1]/sqrt(v[1,1]) scalar tst_`i' = b[1,1]/sqrt(v[1,1]) *truncation if (scalar(tst_`i')>-scalar(k1) & scalar(tst_`i')