*! xtbfkbreak version 1.0.0 11jul2026

Title

xtbfkbreak -- Common structural breaks in heterogeneous panels with
correlated common effects and (optionally) endogenous regressors

Syntax

xtbfkbreak
depvar
[indepvars]
[(endog = instruments)]
[if] [in]
[, options]

depvar is the dependent variable. indepvars are exogenous regressors
whose slopes may break. The optional parenthetical list adds one or more
endogenous regressors together with the instruments that identify their
slopes (as in ivregress). The data must be xtset as a
balanced panel. All variables are continuous and numeric.

Breaks
breaks(#) number of common breaks to estimate; default
breaks(1).

trim(#) minimum regime length as a fraction of T; default
trim(0.15); must be in (0,0.5).

ivbreak locate the break(s) by IV instead of OLS (BFK 2019,
Fig. 2); OLS is the default and is theory-preferred.

Factor structure (CCE)
nocce do not partial out common factors (Model 1: no
cross-sectional dependence in the errors).

csa(varlist) extra variables whose cross-section averages augment
the factor proxies.

lags(#) number of lags of the cross-section averages added to the
factor proxies (Chudik & Pesaran 2015); default lags(0).

Reporting
noconstant suppress the regime intercepts.

level(#) confidence level; default level(95).

graph draw the break-identification and regime-coefficient
plots.

ssrname(name) name of the SSR plot; default xtbfk_ssr.

coefname(name) name of the coefficient plot; default
xtbfk_coef.

xtbfkbreak is e()-class. It stores the mean-group
coefficient vector and variance (see Stored results)
and can be replayed by typing xtbfkbreak
without arguments.

Description

xtbfkbreak estimates a heterogeneous panel-data model whose slope
coefficients undergo one or more common structural breaks at unknown dates,
while cross-sectional dependence is generated by an unobserved multifactor error
structure. It brings the two papers of Baltagi, Feng and Kao into a single
command:

(2016)
Baltagi, Feng & Kao
marry Pesaran's (2006) Common Correlated Effects (CCE) estimator to Bai's (1997,
2010) least-squares change-point estimation. Unobserved factors are partialled
out with the cross-section averages of depvar and the regressors; the
common break date(s) are then estimated consistently by least squares, and the
regime slopes by CCE mean group. A key result is that the panel pins down the
break date itself (super-consistency), not merely the break fraction.

(2019) Baltagi, Feng & Kao extend this to endogenous regressors. A
second endogeneity channel, Cov(eps,v)!=0, is
allowed on top of the factor-induced correlation, and a break in the error-factor
loadings is permitted. The break date is still estimated by OLS (which stays
consistent under endogeneity, Perron & Yamamoto 2015), and the regime slopes by
CCE-IV / 2SLS mean group. Because CCE wipes out the factors instead of
estimating them, a break in the factor loadings needs no special treatment.

Give instruments in the (endog = instruments) list to
obtain the endogenous-regressor (2019) estimator; omit it for the exogenous
(2016) estimator. Use nocce to drop the factor structure entirely (the
papers' "Model 1"). For the algebra, see xtbfkbreak
methods.

The model

For panel i=1,...,N and time t=1,...,T with a common (unknown) break at
k0:

y(it) = x(it)'b1(i) + e(it) for t Ĉ k0,

y(it) = x(it)'b2(i) + e(it) for t > k0,

e(it) = g(i)(k1)'f(t) + eps(it), x(it) = G(i)'f(t) + v(it),

where f(t) is a vector of m unobserved common factors with heterogeneous
loadings g(i). Regressors are endogenous through the factors and, in the
2019 model, also through Cov(eps(it),v(it))!=0. The
factor loadings themselves may break at a possibly different date k1. The
parameters of interest are the cross-sectional means of the regime slopes
and the break date(s). With B breaks there are R=B+1 regimes.

Options

Breaks

breaks(#) sets the number of common breaks. With #>1 the breaks are
located one at a time (the sequential procedure of Bai 2010; BFK 2016 Sec. 5):
each new break is the candidate date that most reduces the pooled sum of squared
residuals, holding the breaks already found fixed. The regime slopes are then
re-estimated jointly given all dates. See
choosing the number of breaks.

trim(#) forces every regime to contain at least #×T periods (and
at least as many periods as there are parameters per regime). Larger values
stabilise the search near the ends of the sample at the cost of ruling out breaks
there. # must be strictly inside (0,0.5); the default 0.15 is standard.

ivbreak performs the break search itself by IV (2SLS). This
reproduces the comparison in BFK (2019, Fig. 2). OLS is the default and the
theory-preferred choice: it is consistent under endogeneity and avoids
weak-instrument problems in the search step, and in the paper's simulations it
locates the break more accurately than IV. Use ivbreak only for
comparison.

Factor structure

nocce skips the CCE transformation, i.e. estimates the model without
partialling out common factors (BFK 2016 "Model 1"). Use it only when the errors
are cross-sectionally independent. Applying nocce to data that actually
contain a common factor leaves that factor in the errors and biases the slopes;
conversely, the default (CCE on) is harmless if there is no factor.

csa(varlist) adds the cross-section averages of varlist to the factor
proxies. Instruments are added to the proxy set automatically (BFK 2019:
instruments that load on f(t) enter the proxy vector). Adding informative
extra averages helps when the number of factors is large; see the
rank condition.

lags(#) augments the factor proxies with # lags of the cross-section
averages, following Chudik & Pesaran (2015) for models with weakly exogenous or
dynamic regressors. The first # periods are dropped from the estimation
sample; the reported break dates remain in the original time metric.

Reporting

noconstant drops the regime intercepts. By default a separate intercept is
fitted for each regime (a "pure" structural change), which also absorbs any
regime-specific level shift induced by a fixed effect that enters the regressors.
Keep the default unless you are certain no intercept is needed.

level(#) sets the confidence level for the reported intervals; default is
c(level) (usually 95).

graph draws two graphs (see Graphs), named by
ssrname(name) and coefname(name).

How it works (three steps)

Step 1 - remove the factors (CCE). The cross-section averages
w(t)=(ybar(t),xbar(t)',zbar(t)') together with a constant proxy
the unobserved factors; the annihilator
Mw = I - W(W'W)^(-1)W' removes them (BFK 2016
eq. 20; BFK 2019 eq. 19). Because the averaged idiosyncratic errors vanish as
N grows, w(t) is a valid proxy even under endogeneity and even when the
loadings break.

Step 2 - find the break(s). On the transformed data the pooled objective
{&Sigma}(i) SSR(i)(k) is minimised over candidate dates k (BFK 2016
eq. 24; BFK 2019 eq. 21). OLS is used (Perron & Yamamoto 2015), or 2SLS under
ivbreak.

Step 3 - estimate the regime slopes. Given the dates, each regime is fitted
by CCE (exogenous) or CCE-IV / 2SLS (endogenous; BFK 2019 eq. 23-24) for every
panel, and averaged into the mean-group estimator with Pesaran's (2006)
non-parametric MG variance. The full derivation is in
xtbfkbreak methods.

Interpreting the output

The header block reports the estimator actually run
(CCE-MG vs CCE-MG-IV), whether factors were partialled out, whether
the break search used OLS or IV, the panel dimensions, the trimming fraction, the
number of breaks and regimes, and the estimated break date(s). A break date
is reported as the last period of the pre-break regime: "Break date = 20"
means regime 1 is t=1,...,20 and regime 2 starts at t=21.

Mean-group regime slopes. For each regime the table gives, per regressor,
the cross-sectional mean of the individual CCE (or CCE-IV) slopes, its mean-group
standard error, the z statistic, p-value, and confidence interval.
Read a coefficient as the average marginal effect of the regressor within
that regime across the N panels. The _cons line in each regime is
the regime intercept; it is a nuisance level term (it also soaks up any
fixed-effect level shift) and is rarely of substantive interest.

Structural change in slopes. The second table reports, for each consecutive
pair of regimes, {&delta} = (regime r slope) - (regime r-1 slope), with a
standard error built from the mean-group variance
(Var({&delta}) = V(r,r)+V(r-1,r-1)-2V(r,r-1)). This is the quantity of primary
interest: a significant {&delta} is direct evidence that the slope changed at
the estimated break. A {&delta} indistinguishable from zero means the regressor's
effect did not move across that break, even though a break in some coefficient
was imposed.

Significance stars mark p<.10 (*), p<.05 (**), p<.01 (***).
Standard errors are the non-parametric mean-group standard errors across panels
(Pesaran 2006); they capture slope heterogeneity across units and require a
reasonably large N to be reliable.

What the break date does and does not tell you. Consistency of the break
date (Theorem 1) means that, as N and T grow, the estimated date
concentrates on the true date. The command does not currently test the null
of "no break" nor report a confidence interval for the date; decide on the
presence and number of breaks from theory, from the shape of the
SSR profile, and from whether the {&delta} contrasts are
significant. Re-running with breaks() increased and checking whether the
extra {&delta} is significant is a practical guide.

Replay. Type xtbfkbreak with no arguments (optionally with
level()) to redisplay the last results without re-estimating.

Remarks and practical guidance

Sample size. The theory is a joint (N,T){&rarr}{&infin} asymptotic
with sqrt(T)/N{&rarr}0. Both dimensions should be moderately large; the
mean-group standard errors in particular need a sizeable N (say NĈ20).
With a small N the point estimates can still be informative but the reported
SEs are noisy.

The rank condition. CCE requires the number of factors m to be no larger
than p+1 (regressors plus the dependent variable) in each regime, and
the mean factor loadings to be non-zero. Under a break this is more demanding than
in Pesaran (2006), because the averaging matrix must span the factor and its
regime-split copy. If you suspect many factors, add informative variables through
csa() to enrich the proxy set.

Choosing the number of breaks. There is no built-in test for the number of
breaks; breaks() must be supplied. A workable strategy: start from
breaks(1), inspect the SSR profile for one clear
trough, and increase breaks() only while each additional {&delta} contrast
remains significant and each new regime respects trim().

Endogeneity and instruments. Supply instruments only for genuinely
endogenous regressors. After the CCE transformation and the regime intercepts,
an instrument is only useful through the part of it that is orthogonal to the
factors and to the fixed effect - it must move the regressor's idiosyncratic
component. An instrument that correlates with the regressor only through the
common factor or a unit fixed effect is weak once those are partialled out, and
the IV slopes will be imprecise. The break date is unaffected: it is found by
OLS by default, which is why OLS-search is recommended even in endogenous models.

When to use nocce. Only when the errors are cross-sectionally
independent (no common factors, no spatial dependence). If in doubt, leave CCE on:
it is asymptotically harmless when there is no factor but essential when there is.

Balanced panels only. The command requires a balanced panel on the
estimation sample and errors out otherwise; fill gaps or restrict the sample
first.

Graphs

With graph, xtbfkbreak draws:

(a) Break-point identification (xtbfk_ssr) - the concentrated pooled
SSR against the candidate date. The estimated break(s) sit at the trough(s),
marked by dashed vertical lines. A sharp, deep, well-separated trough indicates a
clearly identified break; a flat profile warns that the date is weakly identified.

(b) Mean-group slope by regime (xtbfk_coef) - each regressor's
mean-group slope in each regime with its confidence interval, one panel per
regressor. A visible level shift between regimes with non-overlapping intervals
is the graphical counterpart of a significant {&delta}.

The SSR profile is also stored in e(ssrprofile) for custom plotting.

Stored results

xtbfkbreak stores the following in e():

Scalars

e(N) number of panels

e(T) time periods

e(T_eff) effective periods used (after lags())

e(k_breaks) number of breaks

e(N_regime) number of regimes (= breaks+1)

e(trim) trimming fraction

e(lags) number of CSA lags

e(ssr) pooled sum of squared residuals at the solution

e(df_m) model degrees of freedom

Macros

e(cmd) xtbfkbreak

e(depvar) dependent variable

e(indepvars) exogenous regressors

e(endog) endogenous regressors

e(insts) instruments

e(breaks) estimated break date(s), calendar time

e(estimator) CCE-MG or CCE-MG-IV

e(transform) factor control used

e(breaksrch) OLS or IV break search

e(panelvar) , e(timevar)panel and time variables

Matrices

e(b) mean-group coefficient vector (equation = regime)

e(V) mean-group variance matrix

e(bi) panel-by-panel coefficients (N × k)

e(breakdates) estimated break date(s)

e(ssrprofile) candidate date and pooled SSR (single-break
profile)

Functions

e(sample) estimation sample

Examples

Exogenous model, one break (BFK 2016) - recover regime slopes and the
break date, with graphs:

. webuse grunfeld, clear

. xtset company year

. xtbfkbreak invest mvalue kstock, breaks(1) graph

Read the second table's {&delta} row: a significant {&delta} on
mvalue means the investment-mvalue elasticity changed at the estimated
year.

Endogenous regressor (BFK 2019) - instrument mvalue with its
lag:

. xtbfkbreak invest kstock (mvalue = L.mvalue), breaks(1)

Two breaks, tighter trimming:

. xtbfkbreak invest mvalue kstock, breaks(2) trim(0.10)

Compare OLS and IV break search (BFK 2019, Fig. 2):

. xtbfkbreak y (x = z), breaks(1)

. xtbfkbreak y (x = z), breaks(1) ivbreak

No factor structure (Model 1):

. xtbfkbreak y x, breaks(1) nocce

A complete simulated demonstration of every option, with the true break and
slopes known, ships as xtbfkbreak_example.do
(open it).

References

Bai, J. 1997. Estimation of a change point in multiple regression models.
Review of Economics and Statistics 79: 551-563.

Bai, J. 2010. Common breaks in means and variances for panel data.
Journal of Econometrics 157: 78-92.

Baltagi, B. H., Q. Feng, and C. Kao. 2016. Estimation of heterogeneous
panels with structural breaks. Journal of Econometrics 191: 176-195.
doi:10.1016/j.jeconom.2015.03.048.

Baltagi, B. H., Q. Feng, and C. Kao. 2019. Structural changes in
heterogeneous panels with endogenous regressors. Center for Policy Research
Working Paper 214, Syracuse University.

Chudik, A., and M. H. Pesaran. 2015. Common correlated effects estimation
of heterogeneous dynamic panel data models with weakly exogenous regressors.
Journal of Econometrics 188: 393-420.

Perron, P., and Y. Yamamoto. 2015. Using OLS to estimate and test for
structural changes in models with endogenous regressors. Journal of Applied
Econometrics 30: 119-144.

Pesaran, M. H. 2006. Estimation and inference in large heterogeneous
panels with a multifactor error structure. Econometrica 74: 967-1012.

Author

Dr Merwan Roudane

merwanroudane920@gmail.com

github.com/merwanroudane

See also xtbfkbreak methods for the estimation
mathematics.