*! version 1.0.0 12 May 2026

Title

xtfactortest -- A practitioner's battery of specification tests
for heterogeneous panel data models with interactive (multifactor) error
effects. Tells you whether you actually need CCE or PC at all, and if
you do, which flavour.

Syntax

xtfactortest
subcommand
depvar indepvars
[if] [in]
[, options]

A balanced panel previously declared with xtset is required.
The cross-section dimension N must exceed the number of regressors K and the
time-series dimension T must satisfy T > K+1.

Subcommand (required)
hb HB-CCE test of heterogeneity bias in pooled CCE
(Juodis & Reese 2026, Lesson 2; modifies Campello, Galvao & Juhl 2019)

lm LM-X test for conditional independence between regressors
and factor loadings (Kapetanios, Serlenga & Shin 2024)

hausman Hausman-type test of correlated factor loadings
(Kapetanios, Serlenga & Shin 2023; FE vs CCE)

joint Joint HBFB test for heterogeneity OR factor-omission bias
(Juodis & Reese 2026, Appendix A.2.2)

all Run all four tests with a summary table, a decision rule
and a 2x2 panel of diagnostic graphs

Estimation / test options
cross(varlist) extra observables to augment the CCE proxy
matrix bar-Z (e.g. macro controls that should help span the factor
space; rarely needed)

npc(#) number of leading principal components of the regressors
used as instruments in the LM-X and HBFB tests. Default 1; KSS 2024
Theorem 1 / Remark 5 prove validity even when the true r > 1 because the
portmanteau argument only requires the LEADING component to load.
Increase only if you suspect a very rich factor structure.

level(#) confidence / significance level (default 95)

Reporting / output
nograph suppress all graphs

graphsave(prefix) filename prefix for saved .png graphs;
produces prefix_hb.png, prefix_lm.png,
prefix_haus.png, prefix_summary.png,
prefix_all.png

replace overwrite existing graph files

noheader suppress the title block

compact print the test statistic table only; suppress
coefficient comparisons and CCE-MG estimates

Description

xtfactortest is a Stata library implementing a coherent battery of
specification tests for heterogeneous panel data models of the form

y_it = beta_i' x_it + gamma_i' f_t + eps_it ,

x_it = Lambda_i' f_t + v_it (i = 1..N , t = 1..T)

with heterogeneous slope coefficients beta_i, heterogeneous factor
loadings gamma_i and Lambda_i, an r-vector of unobserved common factors
f_t, and idiosyncratic errors eps_it and v_it.

Such Interactive-Effects (IE) panels nest both the standard two-way
fixed effects (2W-FE) model and the Common Correlated Effects (CCE)
framework of Pesaran (2006). Whether or not a researcher needs
CCE / PC depends on two concurrent issues:

(a) whether the slopes beta_i are heterogeneous and, if so, whether
that heterogeneity is correlated with VARIANCE features of the
regressors (Campello, Galvao & Juhl 2019);

(b) whether the regressors are correlated with the unobserved factor
loadings gamma_i (Bai 2009; Kapetanios, Serlenga & Shin 2023, 2024).

xtfactortest answers each question with a dedicated test plus a joint
test, and provides an explicit decision rule based on the five-lessons
review of Juodis & Reese (2026).

Background -- why the tests matter

The CCE estimator of Pesaran (2006) replaces the unobserved factors
f_t by the cross-sectional averages of y and x, producing a
residual-maker M_Fhat that partials out the common component. CCE is
simple, robust to heterogeneous slopes, and is implemented in Stata by
xtdcce2 (Ditzen 2018).

Twenty years on, three practical concerns have emerged from the
applied-CCE literature (Juodis & Reese 2026):

1. The POOLED CCE estimator (CCEP) can be biased when slopes are
heterogeneous and that heterogeneity is correlated with the variance
of the regressors AFTER the CCE projection -- a direct analogue of the
OLS-FE heterogeneity bias of Campello et al. (2019).

2. If the regressors are CONDITIONALLY INDEPENDENT of the loadings
gamma_i, the simple two-way FE estimator remains consistent even
under IE (Coakley, Fuertes & Smith 2006; Westerlund 2019a). In that
case CCE is unnecessary, possibly inefficient, and brings several
nontrivial complications (rank condition, leakage of nuisance
factors).

3. The Hausman-style choice between FE and PC/CCE is itself a test
about whether the regressors are correlated with the loadings;
Bai's (2009) original Hausman test is inconsistent in some regions
of the heterogeneous-slope DGP (Kapetanios, Serlenga & Shin 2023).

xtfactortest implements all four of the corresponding tests at once
and produces a single decision recommendation.

When to use each test

hb -- HB-CCE (Juodis-Reese 2026, Lesson 2)

Use the HB-CCE test AFTER you have decided that CCE estimation is
needed and you are choosing between the POOLED (CCEP) and MEAN-GROUP
(CCE-MG) variants.

H_0 : E[ X_i' M_Fhat X_i (beta_i - beta_CCEMG) ] = 0_K

H_1 : individual slopes beta_i are correlated with the unit-specific
CCE "information matrix" X_i' M_Fhat X_i ; under H_1 the pooled CCEP
is asymptotically biased.

Practical guidance. Rejection => use the mean-group estimator
CCE-MG (xtdcce2 option lr) rather than the pooled CCEP
(xtdcce2 default). Not rejecting does not imply CCEP is
efficient; it implies CCEP is consistent for this sample.

lm -- LM-X (Kapetanios-Serlenga-Shin 2024)

Use the LM-X test BEFORE deciding to estimate with CCE or PC at all.
Use it whenever you would otherwise apply Pesaran's (2015) CD test as
a diagnostic for cross-section dependence: rejection of CD does NOT
imply that 2W-FE is inconsistent.

H_0 : x_it is conditionally independent of gamma_i given f_t.

H_1 : regressors x_it correlated with factor loadings gamma_i.

Practical guidance. Not rejecting H_0 means the simple 2W-FE
estimator is consistent under IE (Coakley-Fuertes-Smith result);
the user can keep 2W-FE for simplicity / efficiency and apply HAC
robust SE (Kapetanios, Serlenga & Shin 2023, eq. 11). Rejection
means 2W-FE is biased: use CCE-MG or PC.

hausman -- FE vs CCE (Kapetanios-Serlenga-Shin 2023)

Use the Hausman-type test as a SECOND OPINION on what LM-X tells you:
it compares the actual point estimates of 2W-FE and CCE-MG. A large
coefficient gap is direct, intuitive evidence that the FE estimator
is inconsistent.

H_0 : regressors uncorrelated with loadings => beta_FE = beta_CCE
asymptotically.

H_1 : regressors correlated with loadings => beta_FE biased,
beta_CCE consistent => measurable coefficient gap.

Practical guidance. LM-X and Hausman test essentially the same
hypothesis but from complementary angles: LM-X uses moment conditions
on FE residuals (no CCE estimation needed), Hausman uses the actual
coefficient gap. When both reject, the conclusion is robust.

joint -- HBFB (Juodis-Reese 2026, App. A.2.2)

Use the HBFB joint test as a single-shot Wald check on whether 2W-FE
is plausible at all.

H_0 : 2W-FE has NEITHER heterogeneity bias NOR factor-omission bias.

H_1 : at least one source of bias is present.

Practical guidance. Useful when you want a single omnibus
diagnostic. If it does not reject, neither HB-CCE nor LM-X will (with
prob -> 1), so 2W-FE is safe. If it rejects, you need the individual
tests above to identify which bias.

Decision tree (Juodis-Reese 2026, Lessons 1-2)

The all subcommand automates the following logic:

Step 1. Run LM-X (or HBFB). If H_0 not rejected => estimate
with 2W-FE + Driscoll-Kraay or cluster-robust SE. Stop.

Step 2. If LM-X rejects: factor structure matters. Run HB-CCE.

Step 3. If HB-CCE not rejected: slopes appear homogeneous.
Estimate with pooled CCEP (xtdcce2, default options).

Step 4. If HB-CCE rejects: estimate with the mean-group CCE-MG
(xtdcce2 ..., lr). In dynamic models add the half-panel jackknife
correction (xtdcce2 ..., lr hpj).

This decision tree is printed at the bottom of the all subcommand's
output, instantiated with the actual rejections in your sample.

Subcommands -- formulas and theory

hb -- HB-CCE test (Juodis-Reese 2026, Lesson 2)

Let M_Fhat = I_T - Fhat (Fhat'Fhat)^(-1) Fhat' be the CCE residual
maker, with Fhat = (bar-y, bar-X) the cross-sectional averages.
Compute the unit-specific CCE slopes

beta_hat_ = ( X_i' M_Fhat X_i )^(-1) X_i' M_Fhat y_i

and the CCE-MG estimator

beta_hat_ = N^(-1) Sum_i beta_hat_

The HB-CCE moment condition is

delta_hat_ = [ X_i' M_Fhat X_i - N^(-1) Sum_j X_j' M_Fhat X_j ]
( beta_hat_ - beta_hat_ )

with delta_hat_ = (1/N) Sum_i delta_hat_ and non-parametric
variance

Var_hat( delta_hat_ ) = N^(-2) Sum_i delta_hat_
delta_hat_'

Under H_0 and standard regularity conditions

HB = delta_hat_' Var_hat^(-1) delta_hat_
~ chi^2(K)

where K is the number of regressors. Asymptotic theory holds for both
N -> infinity with T fixed and joint (N,T) -> infinity.

lm -- LM-X test (Kapetanios-Serlenga-Shin 2024)

Apply the two-way within transformation

ddot-y_it = y_it - bar-y_ - bar-y_{.t} + bar-y_{..}

and similarly for x. Compute the individual FE estimator

beta_hat_ = ( ddot-X_i' ddot-X_i )^(-1) ddot-X_i' ddot-y_i

and the FE residuals

u_hat_i = ddot-y_i - ddot-X_i beta_hat_.

Extract the leading r = npc() principal components of the
regressors from the eigendecomposition of

S = (NT)^(-1) Sum_i ddot-X_i ddot-X_i'

and set Fhat_X = sqrt(T) * (eigenvectors of S corresponding to the r
largest eigenvalues). Form the projected regressors

Xhat_i = Fhat_X ( Fhat_X' Fhat_X )^(-1) Fhat_X' ddot-X_i.

The LM-X statistic is the score-form Wald

LM_X = [ N^(-1/2) Sum_i Xhat_i' u_hat_i / T ]'
V_hat^(-1)
[ N^(-1/2) Sum_i Xhat_i' u_hat_i / T ]
~ chi^2(K)

with sandwich variance

V_hat = N^(-1) Sum_i Xhat_i' u_hat_i u_hat_i' Xhat_i / T^2 .

KSS 2024 prove that the test follows chi^2(K) under H_0 even when the
true number of factors r > 1 (portmanteau result, Theorem 1). This is
why setting npc(1) works in essentially all practical settings.

hausman -- FE vs CCE (Kapetanios-Serlenga-Shin 2023)

Compute the mean-group 2W-FE and CCE-MG estimators along with their
non-parametric variances

V_FE = [N(N-1)]^(-1) Sum_i (beta_hat_ - beta_hat_FE )
(beta_hat_ - beta_hat_FE )'

V_CCE = [N(N-1)]^(-1) Sum_i (beta_hat_ - beta_hat_)
(beta_hat_ - beta_hat_)'

and the cross-covariance

Cov = [N(N-1)]^(-1) Sum_i (beta_hat_ - beta_hat_FE )
(beta_hat_ - beta_hat_)'

The Hausman-type statistic is

H = ( beta_hat_FE - beta_hat_ )'
( V_FE + V_CCE - Cov - Cov' )^(-1)
( beta_hat_FE - beta_hat_ )
~ chi^2(K)

joint -- HBFB (Juodis-Reese 2026, App. A.2.2)

The HBFB statistic stacks the HB-CCE moments and a KSS-style
factor-omission moment into a 2K-dim vector

delta_hat_ = ( delta_hat_' , delta_hat_' )'

where delta_hat_ = Xhat_i' u_hat_ / T is the LM-X
moment for unit i. The joint statistic

HBFB = delta_hat_' Var_hat^(-1) delta_hat_
~ chi^2(2K)

Options -- details

cross(varlist) -- appends extra observed variables to the
cross-sectional average matrix bar-Z. Use this when there are
additional relevant macro-level variables that should help span the
unobserved factor space (cf. Pesaran et al. 2013, Pesaran 2007 in the
CIPS context). Most empirical work does not need this option.

npc(#) -- sets the number of regressor principal components used
as instruments in the LM-X test. The KSS 2024 portmanteau result
(their Theorem 1, Remark 5) supports npc(1) even when the true
number of factors r > 1. Increase only if your regressors clearly
carry several distinct trends (e.g. cross-country macro panels with
multiple global shocks).

level(#) -- significance level used for all four test decisions
and the 95% confidence intervals on the Hausman coefficient plot.

graphsave(prefix) -- writes the PNG files
prefix_hb.png, prefix_lm.png, prefix_haus.png,
prefix_summary.png and the combined view prefix_all.png.
Each individual graph also remains in memory under the names
xtft_hb, xtft_lm, xtft_haus, xtft_summary,
xtft_all, so you can redisplay any of them later with
graph display xtft_hb etc.

compact -- prints only the test header + statistic table; the
coefficient comparison block and CCE-MG coefficient block are omitted.

Interpreting the output

For each subcommand xtfactortest prints (i) a citation block, (ii) the
null and alternative in plain English, (iii) the statistic / df /
p-value / decision row. When run with all a unified summary
table and a plain-English decision rule are appended.

The output of all is colour-coded:

- Statistic : printed in result colour; df is the chi^2 dof, not
a sample-size statistic.

- Decision : if the p-value is below 1 - level/100 (default
0.05) the row is marked in red as REJECT H0; otherwise green "do not
reject".

The Decision rule paragraph at the bottom translates the four
rejections (HB-CCE, LM-X, Hausman, HBFB) into one of five recommended
estimators:

- no rejection => 2W-FE

- LM/Hausman reject, HB not => CCEP (pooled CCE)

- HB rejects, LM/Hausman not => CCE-MG (mean-group CCE)

- both reject => CCE-MG (with HPJ in dynamic settings)

- mixed => see individual results

The 2x2 graph window combines the four individual diagnostic plots.
The HB-CCE histogram of individual slopes is directly comparable to
Fig. 3 of Campello et al. (2019); the LM-X scatter and the FE-vs-CCE
coefficient plot replicate Figs. 1 and 2 of Juodis & Reese (2026).

Recommended workflow for empirical papers

Step 1. Declare the panel:

xtset id time

Step 2. Diagnose cross-section dependence (still
recommended even though CD rejection alone is not informative about
FE inconsistency, cf. KSS 2024):

xtreg y x1 x2, fe

xtcd2 e(sample)

Step 3. Run the xtfactortest battery:

xtfactortest all y x1 x2 x3

Step 4. Follow the recommendation produced by the
decision rule. Then estimate using xtdcce2:

xtdcce2 y x1 x2 x3, crosssectional(_all) lr(L.y x1) ...

Step 5. Report all four xtfactortest statistics in the
specification-test appendix of your paper to allow the reader to
evaluate your estimation choice.

Examples

Stata example panel (Penn World Table productivity data):

. use https://www.stata-press.com/data/r17/productivity, clear

. xtset state year

Run all four tests with default graphs and decision rule:

. xtfactortest all gsp pcap pc emp unemp

HB-CCE test only, saving the figure:

. xtfactortest hb gsp pcap pc emp, graphsave(myout) replace

LM-X test with two principal components:

. xtfactortest lm gsp pcap pc emp, npc(2)

Hausman-type test at the 1% level, compact output:

. xtfactortest hausman gsp pcap pc emp, level(99) compact

Full battery followed by CCE estimation (using xtdcce2):

. xtfactortest all gsp pcap pc emp

. xtdcce2 gsp pcap pc emp , crosssectional(_all) lr

Common pitfalls and FAQ

Q1. My CD test rejects. Does that mean I must use CCE?

A. No. Pesaran's CD test signals the PRESENCE of cross-section
dependence, not the inconsistency of 2W-FE. The Coakley-Fuertes-Smith
(2006) / Westerlund (2019a) result says 2W-FE is consistent if
regressors are conditionally independent of loadings. Run lm or
hausman to verify before switching to CCE.

Q2. HB-CCE rejects but Hausman does not. Which estimator?

A. HB-CCE is a test of POOLED CCE inconsistency under heterogeneous
slopes. Hausman compares the MEAN-GROUP versions of FE and CCE. The
pattern "HB reject, Hausman do not reject" implies your slopes are
heterogeneous but in a way that is uncorrelated with loadings;
therefore use CCE-MG (xtdcce2 ..., lr) or 2W-FE-MG, but
NOT pooled CCEP.

Q3. My panel has T = 10. Are these tests reliable?

A. All four tests are formally derived under joint (N,T) -> infinity.
KSS 2024 and Campello et al. (2019) show good finite-sample size and
power for T as small as 5 (LM-X) and 10 (HB) when the cross-section
is moderate (N >= 30). See Tables 1-5 of the respective papers.

Q4. My panel is unbalanced.

A. xtfactortest currently requires a balanced panel; it errors out
otherwise. Pre-process with xtbalance (Stata Journal package)
or by restricting the sample to a balanced subset before calling
xtfactortest. An unbalanced extension is on the roadmap.

Q5. I have a dynamic panel (lagged dependent variable).

A. All four tests remain valid under serial correlation of the
idiosyncratic errors and lagged dependent variables, provided the
factor structure is correctly specified. After deciding to use CCE,
add the HPJ bias correction via xtdcce2 ..., lr hpj.

Q6. My regressors include time-invariant variables.

A. Time-invariant regressors are absorbed by the two-way within
transformation and the CCE residual maker. Their slopes are not
identified and they should be removed from the indepvars list.

Q7. Some tests reject, some don't. Which estimator should I
report?

A. Follow the decision rule printed at the end of all. When in
doubt, the mean-group CCE-MG is the safer default: it is robust to
slope heterogeneity AND to factor structure, at the cost of moderate
efficiency loss when both are absent (Juodis & Reese 2026, Lesson 2).

Q8. How is xtfactortest related to xthbtest?

A. xthbtest (Hong & Galvao, original Campello-Galvao-Juhl
implementation) tests heterogeneity bias of the OLS-FE estimator
using the within projection M_iota. xtfactortest's HB-CCE subcommand
replaces M_iota with the CCE residual maker M_Fhat to test
heterogeneity bias of the CCEP estimator -- the modification
proposed in Juodis & Reese (2026, Lesson 2).

Q9. How does this compare to Bai's (2009) Hausman test?

A. Bai's H_B compares FE with the iterative PC estimator. KSS
(2023) and Westerlund (2019b) show that this test is inconsistent
against the alternative of correlated loadings when slopes are
heterogeneous. xtfactortest's hausman subcommand uses the
KSS (2023) modification with the non-parametric V_NON estimator,
which is consistent under both homogeneous AND heterogeneous slopes.

Stored results

xtfactortest subcmd stores the following in r():

Scalars (all subcommands)

r(N) cross-sectional dimension

r(T) time-series dimension

r(K) number of regressors

r(df) degrees of freedom of the chi^2 test

r(pvalue) p-value of the test

Scalars (subcommand-specific)

r(HB) | r(LM) | r(H) | r(HBFB) test statistic

r(npc) number of PCs used (LM-X only)

Macros

r(test) short name of the test

r(ref) methodological reference

Matrices (HB-CCE)

r(beta_CCEMG) CCE-MG mean-group coefficients

r(Var_CCEMG) Pesaran-2006 nonparametric variance

r(beta_i) N x K matrix of individual CCE slopes

r(delta_HB) sample moment delta_hat_HB

Matrices (LM-X)

r(diag_lm) N x 2 diagnostic data (PC projection, residuals)

Matrices (Hausman)

r(beta_FE) r(beta_CCE) coefficient vectors

r(V_FE) r(V_CCE) variance matrices

References

Bai, J. (2009). Panel data models with interactive fixed effects.
Econometrica 77(4): 1229-1279.

Campello, M., A.F. Galvao & T. Juhl (2019). Testing for slope
heterogeneity bias in panel data models.
Journal of Business & Economic Statistics 37(4): 749-760.

Coakley, J., A.-M. Fuertes & R.P. Smith (2006). Unobserved
heterogeneity in panel time series models.
Computational Statistics & Data Analysis 50: 2361-2380.

Ditzen, J. (2018). Estimating dynamic common-correlated effects in
Stata. Stata Journal 18(3): 585-617.

Juodis, A. & S. Reese (2026). Five lessons for applied researchers
from twenty years of common correlated effects estimation.
Journal of Econometrics 253: 106120.

Kapetanios, G., L. Serlenga & Y. Shin (2023). Testing for correlation
between the regressors and factor loadings in heterogeneous panels
with interactive effects.
Empirical Economics 64: 2611-2659.

Kapetanios, G., L. Serlenga & Y. Shin (2024). An LM test for the
conditional independence between regressors and factor loadings in
panel data models with interactive effects.
Journal of Business & Economic Statistics 42(2): 743-761.

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

Pesaran, M.H. (2015). Testing weak cross-sectional dependence in large
panels. Econometric Reviews 34(6-10): 1089-1117.

Westerlund, J. (2019a). On estimation and inference in heterogeneous
panel regressions with interactive effects.
Journal of Time Series Analysis 40: 852-857.

Westerlund, J. (2019b). Testing additive versus interactive effects in
fixed-T panels. Economics Letters 174: 5-8.

Author

Dr Merwan Roudane

merwanroudane920@gmail.com

xtfactortest v1.0 -- May 2026

Please cite the underlying methodological papers (Campello et al. 2019;
Juodis & Reese 2026; Kapetanios, Serlenga & Shin 2023, 2024) when
reporting test results obtained with this package.

For bug reports, feature requests or methodological discussion please
email the author or open a thread on Statalist with subject
[xtfactortest].