// ------------------------------------------------------------------------------------------------- // xtbreak_estimate // ------------------------------------------------------------------------------------------------- capture program drop xtbreak_estimate program define xtbreak_estimate, eclass syntax varlist(min=1 ts) [if] , [ /// ] breaks(numlist) [ /// number of breaks csd /// add cross-sectional averages /// unknow breaks 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 /// breaks and variables 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 /// settings dynamic program TRIMming(real 0.15) /// minimal time periods without a break error(real 1e-5) /// error margin /// output showindex /// display index rather than breakpoint as CI /// internal options trace /// show output forcefe /// internal option: allows for fixed effects with constant donotdisptrim /// do not show trimming at bottom ] *** mark sample tempname touse marksample touse ************************************************ **** Checks ************************************************ *** 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' { disp "varlist is `varlist'" local varlist_o `varlist' 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 } *** 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)'" == "" { local tvar_o `r(timevar)' tempvar idvar_bogus gen `idvar_bogus' = 1 local idvar `idvar_bogus' } 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' *** 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'" != "" { disp "Trend added" 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' tempname EstCoeff EstCov EstBreak EstCI level stats mata xtbreak_EstBreaks("`indepdepvars'","`nobreakvariables'","`csa_list'","`csanb_list'","`idvar' `tvar'","`touse'",`breaks',`trimming',`vce',`ConstantType',`demean',(`dynamicpartial',`num_csa',`num_csanb'),`error',1,`EstCoeff'=.,`EstCov'=.,`EstBreak'=.,`EstCI'=.,"`level'", "`stats'") 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' mata st_matrix("CI",`EstCI') qui sum `tvar_o' if `touse' local adj = `r(min)' - 1 mata st_matrix("CI", `EstCI' \ `EstCI' :+`adj') matrix rownames CI = Low Up Low Up matrix roweq CI = Index Index TimeValue TimeValue matrix colnames CI = `tmp' *mata st_matrix("b",`EstCoeff') *tsunab vars: `varlist' *gettoken lhs rhs: vars *matrix rownames b = `tmp' `=`breaks' + 1' *matrix colnames b = `rhs' local timetype : format `tvar_o' } local timetype = subinstr("`timetype'","%","%-",.) tokenize ``stats'' local N = `1' local T = `2' local minSSR = `3' /// Output if "`showindex'" == "" { local dispCI "`timetype'" local timetypeCI "`timetype'" local colCI1 = 50 local colCI2 = 65 local colheader = 60 local colMax = 80 qui sum `tvar_o' if `touse' local adj = `r(min)' - 1 } else { local colCI1 = 40 local colCI2 = 55 local colheader = 50 local colMax = 70 local adj = 0 } disp "" disp in smcl as text _col(1) "Estimation of break points" if `N' > 1 { disp in smcl as text _col(`colheader') "N" _col(`colCI2') "= " as result %6.0f `N' } disp in smcl as text _col(`colheader') "T" _col(`colCI2') "= " as result %6.0f `T' disp in smcl as text _col(`colheader') "SSR " _col(`colCI2') "= " as result %9.2f `minSSR' disp in smcl as text _col(`=`colheader'-5') "Trimming " _col(`colCI2') "= " as result %9.2f `trimming' disp in smcl as text "{hline `colMax'}" disp in smcl as text _col(3) "#" _col(10) "Index" _col(20) "Date" _col(`colCI1') "[``level''% Conf. Interval]" disp in smcl as text "{hline `colMax'}" forvalues i = 1(1)`breaks'{ local val = breaks[2,`i'] local ini = breaks[1,`i'] local low = CI[1,`i']+`adj' local up = CI[2,`i']+`adj' disp in smcl as text _col(3) "`i'" as result _col(12) "`ini'" _col(20) `timetype' `val' _col(`colCI1') `timetypeCI' `low' _col(`colCI2') `timetypeCI' `up' } disp in smcl as text "{hline `colMax'}" if "`varname_csa_list'`varname_csanb_list'" != "" { 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 clear ereturn clear ereturn post , esample(`touse') tsunab vars: `varlist_o' gettoken lhs rhs: vars ereturn hidden local breakvars "`rhs'" ereturn hidden local depvar "`lhs'" ereturn local cmd "`cmd'" ereturn matrix breaks = breaks ereturn matrix CI = CI ereturn hidden local estat_cmd "xtbreak_estat" end ** auxiliary file with auxiliary programs findfile "xtbreak_auxiliary.ado" include "`r(fn)'"