*! xbtreak test program *! v. 1.1 capture program drop xtbreak_tests program define xtbreak_tests, rclass syntax varlist(min=1 ts) [if] , [ /// Hypothesis(real 1) /// which hypothesis to test wdmax /// if hypothesis 2, do weighted UDmax test instead of UDmax /// unknow breaks breaks(string) /// number of breaks under alternative TRIMming(real 0.15) /// minimal time periods without a break level(string) /// level for p-value error(real 0.0001) /// error margin SEQuential /// do sequentiual test for H3 with max breaks defined by breaks /// knwon breaks BREAKPoints(string) /// periods of breakpoints /// general variable options NOBREAKVARiables(varlist ts) /// constant variables NOCONStant /// no constant BREAKCONStant /// constant has break BREAKFixedeffects /// break in fixed effects NOFixedeffects /// if fixed effects are part of the model vce(string) varestimator(string) /// empty for standard, kw/nw for newey west, np for non parametric (Pesaran 2006), HC for hc [only N=1], SSR for SSR [only N=1] /// trend trend /// add linear trend without break breaktrend /// add linear trend with break /// csa csd /// add cross-sectional averages csa(string) /// cross-sectional averages to add; support dynamic panel, i.e. csa removed CSANObreak(string) /// cross-sectional averages with no break KFactors(varlist ts) /// known factors with breaks NBKFactors(varlist ts) /// known factors without breaks /// internal options trace /// show output showindex /// display index rather than breakpoint forcefe /// internal option: allows for fixed effects with constant donotdisptrim /// do not show trimming at bottom ] ************************************************ **** Checks ************************************************ *** main check: are necessary options there? local auto = 0 if "`breakpoints'`breaks'" == "" { *noi disp "Option breakpoints or breaks required." *error 198 local breaks = floor(1/`trimming')-1 local hypothesis = 3 local sequential "sequential" local auto = 1 } *** check that moremata is installed qui{ cap findfile moremata.hlp if _rc != 0 { noi disp "Moremata is required. Please install:" noi disp in smcl "{stata ssc install moremata}" error 198 } } local cmd "`*'" if "`trace'" == "" { local trace "qui" } else { local trace noi } `trace' { if "`vce'" == "" & "`varestimator'" != "" { local vce "`vce'" } *** parse options if strlower("`vce'") == "np" { local vce = 1 } else if strlower("`vce'") == "ssr" { local vce = 2 } else if strlower("`vce'") == "kw" | strlower("`vce'") == "nw" | strlower("`vce'") == "hac" { local vce = 3 } else if strlower("`vce'") == "hc" | { local vce = 4 } else { /// standard case; for panel switch to KW; for time series to ssr local vce = 99 } *** check for impossible options if wordcount("`varlist'") == 1 { if "`breakconstant'" == "" { noi disp "No variable(s) to test." error 100 } if "`breakfixedeffects'" != "" { noi disp "Break in model with only fixed effects not possible." error 100 } } if "`noconstant'" != "" & "`breakconstant'" != "" { noi disp "Options noconstant and breakconstant cannot be combined." error 184 } if "`nofixedeffects'" != "" & "`breakfixedeffects'" != "" { noi disp "Options nofixedeffects and breakfixedeffects cannot be combined." error 184 } if "`level'" == "" { local level = c(level)/100 } if "`hypothesis'" != "2" & wordcount("`breaks'") > 1 { noi disp in smcl "Option {cmd:breaks()} can only take one number." error 199 } *** name of hypothesis if "`hypothesis'" == "1" { local typename "supf" local statname "supW(tau)" } else if "`hypothesis'" == "2" { if "`wdmax'" == "" { local wdmax = 0 local wdmaxName "UDmax(tau)" local wdmaxRname "UDmax" } else { local wdmax = 1 local wdmaxName "WDmax(tau)" local wdmaxRname "WDmax" } local typename "`wdmaxRname'" local statname "`wdmaxName'" } else if "`hypothesis'" == "3" { local typename "fll1" local statname "F(s+1|s)*" if "`sequential'" == "" { local sequential = 0 } else { local sequential = 1 } } *** mark sample tempname touse marksample touse *** check if tsset or xtset and sorted cap _xt if _rc == 0 { local tvar_o `r(tvar)' local idvar `r(ivar)' local idvars `idvar' local IsPanel = 0 xtset if `r(imax)' != `r(imin)' { local IsPanel = 1 } if "`r(balanced)'" != "strongly balanced" { noi disp as error "Only balanced panels allowed." error(199) } } else{ tsset if "`r(panelvar)'" == "" { tempvar idvar_bogus gen `idvar_bogus' = 1 local tvar_o `r(timevar)' local idvar `idvar_bogus' local idvars } local IsPanel = 0 } issorted `idvars' `tvar_o' *** Additional check if panel model used and only breakconstant specified, assumption is no fixed effects if "`breakconstant'" != "" & `IsPanel' == 1 & "`nofixedeffects'" == "" { noi disp "Option {cmd:nofixedeffects} assumed." local nofixedeffects "nofixedeffects" } *** generate new tvar from 1...T tempvar tvar egen `tvar' = group(`tvar_o') if `touse' *** tsset varlist issorted `idvars' `tvar_o' tsrevar `varlist' local indepdepvars "`r(varlist)'" *** adjust touse markout `touse' `indepdepvars' *** create cross-sectional averages *** main csd option - will overwrite csa and csanobreak! if "`csd'" != "" { *** use gettoken to get only RHS vars gettoken tmp1 tmp2: indepdepvars *local csa "`tmp2'" *local csanobreak "`nobreakvariables'" hascommonfactors `tmp2' if `touse' , tvar(`tvar') idvar(`idvar') localname(csa) hascommonfactors `nobreakvariables' if `touse' , tvar(`tvar') idvar(`idvar') localname(csanobreak) } local num_csanb = 0 local num_csa = 0 if "`csa'" != "" { issorted `idvars' `tvar_o' tempname csa_name1 csa_name2 local 0 `csa' syntax varlist(ts) , [lags(numlist) EXCludecsa ] if "`lags'" == "" { local lags "0" } if "`excludecsa'" == "" { local dyn1 "dyn" } issorted `idvars' `tvar_o' get_csa `varlist' , idvar("`idvar'") tvar("`tvar'") cr_lags("`lags'") touse(`touse') csa("`csa_name1'") local csa_list "`r(varlist)'" local num_csa = wordcount("`csa_list'") issorted `idvars' `tvar_o' tsunab varname_csa_list : `varlist' } if "`kfactors'" != "" { local csa_list "`csa_list' `kfactors'" } if "`csanobreak'" != "" { issorted `idvars' `tvar_o' tempname csanb_name1 csanb_name2 local 0 `csanobreak' syntax varlist(ts) , [lags(numlist) EXCludecsa ] if "`lags'" == "" { local lags "0" } if "`excludecsa'" == "" { local dyn2 "dyn" } get_csa `varlist' , idvar("`idvar'") tvar("`tvar'") cr_lags("`lags'") touse(`touse') csa("`csanb_name1'") local csanb_list "`r(varlist)'" local num_csanb = wordcount("`csanb_list'") issorted `idvars' `tvar_o' tsunab varname_csanb_list : `varlist' } if "`nbkfactors'" != "" { local csanb_list "`csanb_list' `nbkfactors'" } *** internal use: dynamic panel forces dynamic program to remove CSA as well. if "`dyn1'`dyn2'" != "" { local dynamicpartial = 1 } else { local dynamicpartial = 0 } issorted `idvars' `tvar_o' markout `touse' `indepdepvars' `nobreakvariables' `csa_list' `csanb_list' *local num_s = 0 if "`breakpoints'" != "" { local 0 `breakpoints' syntax anything(name = breakpoints) , [index fmt(string)] transbreakpoints `breakpoints' , `index' tvar(`tvar' `tvar_o') touse("`touse'") format(`fmt') local breakpoints "`r(index)'" } *** constant and fixed effects /* Cases Options 1. Fixed Effects (noconstant) default 2. FE with break breakfixed (noconstant) 3. POLS nofixedeffects 4. POLS with break breakconstant 5. No FE and no POLS nofixedeffects noconstant */ if "`breakconstant'" != "" & "`breakfixedeffects'" != "" { noi disp as error "Break in constant and fixed effects at the same time not possible." error(199) } if "`breakfixedeffects'" != "" & wordcount("`indepdepvars'") == 1 { noi disp as error "Explanatory variables missing. Model cannot have only fixed effects with breaks." error(199) } local demean = 0 if `IsPanel' == 1 { if "`nofixedeffects'" == "" & "`breakfixedeffects'" == "" { *** Standard case local demean = 1 local noconstant noconstant } else if "`nofixedeffects'" == "" & "`breakfixedeffects'" != "" { tempvar fes gen double `fes' = 1 local csa_list `csa_list' `fes' ///local num_csa = `num_csa' + 1 ///do not update number of csa, because then FE are in determinsitic csa! /// make sure FE are removed even if no other CSA are added! local dynamicpartial = 1 local noconstant noconstant } if "`forcefe'" != "" local demean = 1 } if "`noconstant'" == "" { if "`breakconstant'" == "" { tempname cons gen double `cons' = 1 if wordcount("`indepdepvars'") > 1 { local nobreakvariables `nobreakvariables' `cons' local ConstantType = 1 } else if wordcount("`indepdepvars'") == 1 { local indepdepvars `indepdepvars' `cons' local ConstantType = -1 } } else { *** constant has a break *** check if constant only coefficient if wordcount("`indepdepvars'") > 1 { local ConstantType = 2 tempname cons gen double `cons' = 1 local indepdepvars `indepdepvars' `cons' } else { *** model with only a constant tempname cons gen double `cons' = 1 local indepdepvars `indepdepvars' `cons' local ConstantType = -1 } } } else { local ConstantType = 0 } *** trend if "`trend'`breaktrend'" != "" { tempvar trend by `idvar' (`tvar_o'), sort: gen `trend' = _n *** Trend is added to CSA lists, will always be assumed as determinsitic if "`breaktrend'" != "" { local csa_list "`csa_list' `trend'" } else { local csanb_list "`csanb_list' `trend'" } } issorted `idvars' `tvar_o' if "`breakpoints'" != "" { *** Test for hypothesis i) tempname testh `trace' mata `testh' = xtbreak_Test_Hi_known("`indepdepvars'","`nobreakvariables'","`csa_list'","`csanb_list'","`idvar' `tvar'","`touse'","`breakpoints'",`vce',`ConstantType',`demean') } else { *** unknown breakpoints tempname testh if "`hypothesis'" == "1" { tempname EstBreak `trace' mata `testh' = xtbreak_Test_Hi_unknown("`indepdepvars'","`nobreakvariables'","`csa_list'","`csanb_list'","`idvar' `tvar'","`touse'",`breaks',`trimming',`vce',`ConstantType',`demean',(`dynamicpartial',`num_csa',`num_csanb'),`error',1,`EstBreak'=.) } else if "`hypothesis'" == "2" { tempname testh `trace' mata `testh' = xtbreak_Test_Hii_unknown("`indepdepvars'","`nobreakvariables'","`csa_list'","`csanb_list'","`idvar' `tvar'","`touse'","`breaks'",`trimming',`vce',`ConstantType',`demean',(`dynamicpartial',`num_csa',`num_csanb'),`error',1,`level',`wdmax') } else if "`hypothesis'" == "3" { tempname testh `trace' mata `testh' = xtbreak_Test_Hiii_unknown("`indepdepvars'","`nobreakvariables'","`csa_list'","`csanb_list'","`idvar' `tvar'","`touse'",`breaks',`trimming',`vce',`ConstantType',`demean',(`dynamicpartial',`num_csa',`num_csanb'),`error',`sequential') } } } *** Output return clear disp "" if "`breakpoints'" != "" { tempname wtau pvalF pvalChi mata st_numscalar("`wtau'",`testh'[1,1]) mata st_numscalar("`pvalF'",1- F(`testh'[1,2]*`testh'[1,3],`testh'[1,5],`testh'[1,1])) mata st_numscalar("`pvalChi'",1- chi2(`testh'[1,2]*`testh'[1,3],`testh'[1,1])) disp as text " W(tau) " _col(15) " = " as result _col(20) %9.2f `wtau' disp as text " p-value (F)" _col(15) " = " as result _col(20) %9.2f `pvalF' return scalar p = `pvalF' return scalar Wtau = `wtau' } else { tempname ml ml1 if inlist(`trimming',0.05,0.1,0.15,0.2,0.25) == 0 { local trimming_o "`trimming'" mata `ml1' = (0.05,0.1,0.15,0.2,0.25) mata `ml' = abs(`ml1':-`trimming') mata `ml' = selectindex(min(`ml'):==`ml') mata `ml1' = `ml1'[`ml'] mata st_local("trimming",strofreal(`ml1')) local minset = 1 mata mata drop `ml' `ml1' } mata st_local("SeqN",strofreal(rows(`testh'))) noi disp as text _col(17) as smcl "{hline 17}" as text _col(35) "Bai & Perron Critical Values" as smcl _col(64) "{hline 17}" noi disp as text _col(22) "Test" _col(36) "1% Critical" _col(52) "5% Critical" _col(67) "10% Critical" noi disp as text _col(19) "Statistic" _col(38) "Value" _col(55) "Value" _col(71) "Value" noi disp as text "{hline 80}" local last_reject90 = . local last_reject95 = . local last_reject99 = . tempname m_breaks mata `m_breaks' = J(`SeqN',3,.) forvalues i = 1(1)`SeqN' { tempname testhi mata `testhi' = `testh'[`i',.] tempname stat c90 c95 c99 s mata st_numscalar("`stat'",`testhi'[1,1]) mata st_numscalar("`s'",`testhi'[1,2]) mata st_numscalar("`c90'", xtbreak_GetCritVal(`trimming',0.9,`testhi'[1,2],`testhi'[1,3],"`typename'")) mata st_numscalar("`c95'", xtbreak_GetCritVal(`trimming',0.95,`testhi'[1,2],`testhi'[1,3],"`typename'")) mata st_numscalar("`c99'", xtbreak_GetCritVal(`trimming',0.99,`testhi'[1,2],`testhi'[1,3],"`typename'")) mata `m_breaks'[`i',.] = (`=`c99' < `stat'',`=`c95' < `stat'',`=`c90' < `stat'') if `SeqN' > 1 { local statname "F(`i'|`=`i'-1')" } noi disp as text _col(2) "`statname'" as result _col(18) %9.2f `stat' _col(35) %9.2f `c99' _col(51) %9.2f `c95' _col(67) %9.2f `c90' if `SeqN' == 1 noi disp as text "{hline 80}" if `hypothesis' == 1 { mata st_local("`EstBreak'",invtokens(strofreal(`EstBreak'))) `trace' transbreakpoints ``EstBreak'' , index tvar(`tvar' `tvar_o') touse("`touse'") mata st_matrix("breaks",(strtoreal(tokens("`r(index)'")) \ (strtoreal(tokens("`r(ival)'"))))) mata st_local("tmp",invtokens(strofreal((1..cols(st_matrix("breaks")))))) matrix rownames breaks = Index TimeValue matrix colnames breaks = `tmp' if "`showindex'" == "" { noi disp as text "Estimated break points: `r(val)'" } else { noi disp as text "Estimated break points: `=stritrim(``EstBreak'')'" } } if `hypothesis' == 2 & "`wdmax'" != "" { noi disp as text "* evaluated at a level of " %04.2f `level' "." } if `hypothesis' == 3 & `SeqN' == 1 { noi disp as text "* s = " `s'-1 } if "`minset'" == "1" { noi disp as text "No critical values for specified trimming available, set to `trimming'" } } *** Return local GotMax = 0 if `hypothesis' == 1 { return scalar supWtau = `stat' return matrix breaks = breaks } else if `hypothesis' == 2 { return scalar `wdmaxRname' = `stat' } else if `hypothesis' == 3 { if `SeqN' == 1 { return scalar f = `stat' } else { noi disp as text "{hline 80}" *** Get optimals mata `m_breaks' = ((`m_breaks'[2..rows(`m_breaks'),.]:== 0) :* (`m_breaks'[1..rows(`m_breaks')-1,.]:==1 )) \ `m_breaks'[rows(`m_breaks'),.] local c_Vals 99 95 90 forvalues i = 1(1)3 { local c_valsi = word("`c_Vals'",`i') tempname zeros mata `zeros' = mm_which(`m_breaks'[.,`i']:==1) mata st_local("all_1_`c_valsi'",strofreal(sum(`zeros':==1):==rows(`zeros'))) mata st_local("all_0_`c_valsi'",strofreal(rows(`zeros'):==0)) if "`all_0_`c_valsi''" != "1" { mata st_local("opt`c_valsi'_min",strofreal(`zeros'[1])) mata st_local("opt`c_valsi'_max",strofreal(`zeros'[rows(`zeros')])) } else { local opt`c_valsi'_min = . local opt`c_valsi'_max = . } mata mata drop `zeros' } tempname Nbreaks if `opt90_min' == `opt90_max' & `opt95_min' == `opt95_max' & `opt99_min' == `opt99_max' { noi disp as text "Detected number of breaks: " _col(35) %9.0f `opt99_min' _col(51) %9.0f `opt95_min' _col(67) %9.0f `opt90_min' matrix `Nbreaks' = (`opt99_min', `opt95_min', `opt90_min') matrix colnames `Nbreaks' = 99 95 90 } else { noi disp as text "Detected number of breaks: (min)" _col(35) %9.0f `opt99_min' _col(51) %9.0f `opt95_min' _col(67) %9.0f `opt90_min' noi disp as text _col(28) "(max)" _col(35) %9.0f `opt99_max' _col(51) %9.0f `opt95_max' _col(67) %9.0f `opt90_max' matrix `Nbreaks' = (`opt99_min', `opt95_min', `opt90_min' \ `opt99_max', `opt95_max', `opt90_max') matrix colnames `Nbreaks' = 99 95 90 matrix rownames `Nbreaks' = min max } noi disp as text "{hline 80}" *mata st_local("end_sum",strofreal(sum(`m_breaks'[rows(`m_breaks'),.]))) *if `auto' == 1 { * if `opt99' == `breaks' & `opt95' == `breaks' & `opt90' == `breaks' & `end_sum' == 3 { * local GotMax = 1 * } *} *noi disp as text "Detected number of breaks: " _col(35) %9.0f `opt99' _col(51) %9.0f `opt95' _col(67) %9.0f `opt90' if `all_1_99' == 1 & `all_1_95' == 1 & `all_1_90' == 1 { noi disp as text _col(3) "Maximum number of breaks reached with null always rejected. " } else if `all_0_99' == 1 & `all_0_95' == 1 & `all_0_90' == 1 { noi disp as text _col(3) "No breaks detected. " } else if `opt90_min' == `opt90_max' & `opt95_min' == `opt95_max' & `opt99_min' == `opt99_max' { noi disp as text "The detected number of breaks indicates the highest number of" noi disp as text " breaks for which the null hypothesis is rejected." } else { noi disp as text "Null hypothesis rejected more than once after non-rejection." noi disp as text " The detected number of breaks indicates the minimum and maximum" noi disp as text " number of breaks for which the null hypothesis is rejected." } /* if `GotMax' == 0 { if `end_sum' < 3 { noi disp as text "The detected number of breaks indicates the highest number of" noi disp as text " breaks for which the null hypothesis is rejected." } else { noi disp as text "The detected number of breaks indicates the highest number of" noi disp as text " breaks for which the null hypothesis is first rejected." } } else { noi disp as text _col(3) "Maximum number of breaks reached with null always rejected. " } */ mata st_matrix("f",`testh'[.,1]) return matrix f = f return matrix Nbreaks = `Nbreaks' } } if "`donotdisptrim'" == "" { noi disp "Trimming: " %4.2f `trimming' } if "`varname_csa_list'`varname_csanb_list'" != "" & `auto' ==0 { noi disp as text "Cross-section averages:" if "`varname_csa_list'" != "" { noi disp " with breaks: `varname_csa_list'" } if "`varname_csanb_list'" != "" { noi disp " without breaks: `varname_csanb_list'" } } return scalar c90 = `c90' return scalar c95 = `c95' return scalar c99 = `c99' } return local cmd "xtbreak test `cmd'" if "`trace'" != "" { mata mata drop `testh' `testhi' `EstBreak' } end ** auxiliary file with auxiliary programs findfile "xtbreak_auxiliary.ado" include "`r(fn)'"