*! version 1.0.0 22mar2026

Title

fjcoint -- Johansen-Fourier cointegration tests with
smooth structural breaks

Syntax

fjcoint varlist [if] [in]
[, options]

Test specification
test(testname) test to run: johansen, fourier (default),
sbc, or all

Model specification
model(string) deterministic component; see Models

maxlag(#) max lag order for the VAR; default is 2

freq(#) Fourier frequency k; default is 1, range 1-5

option(string) frequency type: single (default) or
cumulative

maxfreq(#) max frequency for SBC grid search; default is 3

trimming(#) trimming proportion for SC-VECM; default 0.1

Output
graph produce four diagnostic graphs plus a combined panel

notable suppress table output

Description

fjcoint implements the Johansen-type cointegration tests with a Fourier
function, as proposed by Pascalau, Lee, Nazlioglu and Lu (2022).

Why this test? The standard Johansen (1991) test assumes no structural
breaks in the deterministic components of the VECM. When breaks are present
(e.g. regime changes, policy shifts, crises), the standard test can have
severe size distortion and power loss.

Key insight: A Fourier expansion f(t) = A*cos(2kt/T) +
B*sin(2kt/T) can approximate virtually any smooth deterministic
function, including functions with multiple breaks, nonlinear shifts, and
gradual transitions (Gallant, 1981). Unlike dummy-variable approaches, this
avoids the need to pre-specify break dates, forms, and numbers.

When to use each test:

test(johansen) -- When you believe there are no structural breaks
in the system. This is the classical benchmark.

test(fourier) -- When you suspect smooth, gradual breaks such as
slow policy transitions, demographic changes, or evolving technology. Best for
trigonometric, ESTAR, LSTAR break patterns.

test(sbc) -- When you are unsure about the break type. The SBC
procedure automatically compares Johansen, SC-VECM (sharp breaks), and Fourier
(smooth breaks) using the Schwarz criterion, then applies the test from the
best-fitting model. This is the recommended test for applied work.

test(all) -- Runs all three tests sequentially for comprehensive
comparison.

Available Tests

test(johansen) -- Standard Johansen Test

The standard Johansen (1991) system-based cointegration rank test.

Null hypothesis: H0: rank() r (at most r cointegrating
vectors)

Alternative: H1: rank() > r

Two test statistics are computed:

Trace statistic: LR_trace = -T (i=r+1 to p) ln(1 - _i)

Tests H0: rank r against H1: rank = p (full rank). The Trace test
evaluates all remaining eigenvalues simultaneously.

Lambda-max statistic: _max = -T * ln(1 - _)

Tests H0: rank = r against H1: rank = r+1. The Lambda-max test evaluates
only the next eigenvalue.

Five model specifications are available (models 1-5); see
Models.

test(fourier) -- Johansen-Fourier Test

Extends the Johansen framework by augmenting the VECM with Fourier
trigonometric terms. The key equation becomes:

X_t = * X_ + _1*X_ + ... +
+ f(t) + e_t

where f(t) = (j=1 to n) [A_j * cos(2jt/T) + B_j * sin(2jt/T)].

Two frequency options:

option(single) -- Uses one frequency k. The Fourier terms are
sin(2kt/T) and cos(2kt/T). Parsimonious: adds only 2 extra
regressors. Best when you expect one dominant smooth break.

option(cumulative) -- Uses frequencies 1 through k. The Fourier
terms include all sin(2jt/T) and cos(2jt/T) for j=1,...,k.
More flexible: can approximate complex break patterns with multiple
inflection points. Uses more degrees of freedom (2k extra regressors).

Choosing the frequency k:

k=1: One smooth, gradual shift over the sample (U-shaped, or one regime
change). Start here.

k=2: Two cycles or a V-shaped/W-shaped shift (e.g. pre-crisis, crisis,
recovery).

k=3: Complex patterns with multiple inflection points.

k=4-5: Very complex break structures. Use with caution -- high k
reduces power.

Four model specifications are available (models 1-4); see
Models.

test(sbc) -- SBC Model Selection Procedure

The SBC procedure (Pascalau et al. 2022, Section 4) is a data-driven approach
that selects the best model among three candidates:

1. Standard Johansen -- No breaks.

2. SC-VECM (Harris, Leybourne & Taylor 2016) -- Sharp/sudden
structural break in the trend function at an unknown date.

3. Johansen-Fourier -- Smooth/gradual structural break via Fourier
function.

How it works:

Step 1: For each candidate model, compute the Schwarz Bayesian Criterion
(SBC).

Step 2: For SC-VECM, search over all break dates (within trimming bounds)
and lag orders, selecting the combination with minimum SBC.

Step 3: For Fourier, search over all frequencies (1 to maxfreq) and lag
orders, selecting the combination with minimum SBC.

Step 4: Compare the three SBC values. The model with the smallest SBC is
selected.

Step 5: The cointegration test statistic from the selected model is used for
inference, with the corresponding critical values.

Advantage: The SBC procedure has correct empirical size under all
break types, including no breaks, smooth breaks, and sharp breaks. The
standard Fourier test may lose power for sharp breaks; the SBC procedure
avoids this by switching to SC-VECM when sharp breaks dominate.

Options

Test specification

test(testname) specifies which test to run. Choose from:
johansen, fourier (default), sbc, or all.

Model specification

model(string) specifies the deterministic component. Choose from:

rc -- Restricted constant (default). Constant enters only in the
cointegrating vector. Implies the cointegrating relationship has a nonzero
mean but no linear trend. Recommended for most applications.

none -- No deterministic terms. Rare in practice; implies the
data have zero mean and no trend.

constant or uc -- Unrestricted constant. Allows a linear
deterministic trend in the levels of the variables.

rt -- Restricted trend. Linear trend enters the cointegrating
vector only. Appropriate when you expect a deterministic trend in the
cointegrating relationship (e.g. trend-stationary deviations).

trend or ut -- Unrestricted trend. Allows a quadratic
deterministic trend in the levels.

maxlag(#) maximum lag order for the VAR model. The VECM uses k-1
lagged differences. Default is 2. For quarterly data, try 4-8. For
monthly data, try 12-24.

freq(#) Fourier frequency for test(fourier). Default is 1. Range:
1 to 5. Start with 1 and increase only if there is reason to suspect
complex multi-break patterns.

option(single|cumulative) frequency type.
single (default) uses one frequency k.
cumulative uses all frequencies 1 through k.

maxfreq(#) maximum frequency for SBC grid search. Default is 3.
The SBC procedure searches over frequencies 1, 2, ..., maxfreq.

trimming(#) trimming proportion for SC-VECM break point search.
Default is 0.1 (10%). The first and last (trimming * 100)% of observations
are excluded as candidate break dates.

graph produces four diagnostic graphs plus a combined panel.
See Graph Interpretation.

notable suppresses the table output. Useful when you only want
stored results or graphs.

Model Specifications

Johansen model numbers (standard test):

Model Name Deterministic terms

1 None No constant, no trend
2 Restricted Constant Constant in CI vector only
3 Unrestricted Constant Constant in short-run
4 Restricted Trend Trend in CI vector only
5 Unrestricted Trend Trend in short-run

Fourier model numbers:

Model Name Deterministic terms

1 Unrestricted Constant Constant + Fourier
2 Unrestricted Trend Constant + Trend + Fourier
3 Restricted Constant Constant in CI + Fourier
4 Restricted Trend Trend in CI + Fourier

Practical guidance:

Use model(rc) (restricted constant, the default) for most applications.
This is the most common specification in empirical work and corresponds to
the case where the cointegrating relationship has an intercept but the
individual series do not exhibit deterministic linear trends beyond those
induced by unit roots.

Use model(constant) or model(rt) if you believe the data have
linear trends in levels, or if the series show trending behavior.

Methodology

1. The Vector Error Correction Model (VECM)

X_t = *X_ + (i=1 to k-1) _i*X_
+ + e_t

where = *' is a (p x p) matrix of rank r. The
matrix contains the r cointegrating vectors, and contains
the adjustment coefficients (loading matrix).

2. The Fourier Extension

X_t = *X_ + (i) _i*X_
+ + f(t) + e_t

where f(t) = A*cos(2kt/T) + B*sin(2kt/T) is the Fourier
approximation of an unknown smooth break function.

3. Reduced-Rank Regression

The test is based on solving the eigenvalue problem:

|*S_kk - S_k0 * S_00^(-1) * S_0k| = 0

where S_00, S_kk, and S_k0 are residual product moment matrices from
regressions of X_t and X_ on lagged differences and
deterministic terms. The ordered eigenvalues _1 >= ... >= _p
provide information about the cointegration rank.

4. Trace and Lambda-max Statistics

Trace: LR = -T * (i=r+1 to p) ln(1 - _i)

Tests whether there are at most r cointegrating vectors.

Lambda-max: _max = -T * ln(1 - _)

Tests whether the rank is exactly r against r+1.

5. Log-Likelihood

logL(r) = -(T/2) * [m*(1+ln(2)) + ln(det(S_00)) + (i=1 to r) ln(1-_i)]

The log-likelihood should be monotonically increasing as the rank r increases,
because each additional cointegrating vector adds parameters to the model.

Critical Values

Standard Johansen: 5% critical values from Johansen (1991). Available
for up to 6 variables and 5 model specifications.

Fourier-Trace and Fourier-Lambda: 5% critical values from Pascalau et al.
(2022), Online Appendix Tables 1-8. Available for 4 models, frequencies 1-5,
single and cumulative, and up to 5 variables (10 variables per system).

SBC procedure: Extended critical value tables from the original GAUSS
code supporting up to 8 variables per system. Includes both no-break and
break critical values for SC-VECM (the break CVs vary by break location).

Note: All critical values are at the 5% level. Values are based on
response surface regressions from Monte Carlo simulations with 50,000
replications (Pascalau et al. 2022).

Output Interpretation

Johansen Test Table

The Johansen table has the following columns:

Column Interpretation
Rank Hypothesized cointegration rank (r = 0, 1, ..., p)
Eigen Value Ordered eigenvalue _r from reduced-rank regression
Larger values indicate stronger cointegrating relationships
Lambda Lambda-max test statistic: _max = -T*ln(1-_)
Tests H0: rank=r vs H1: rank=r+1
Trace Trace test statistic: LR = -T* ln(1-_i)
Tests H0: rank<=r vs H1: rank=p (full rank)
cv(5%) Trace 5% critical value for the Trace test
Log-Likelihood Concentrated log-likelihood at rank r
Should be monotonically increasing in r

How to read the table:

1. Start at Rank = 0. This tests H0: no cointegration.

2. Compare the Trace statistic to the cv(5%) value.

3. If Trace > cv(5%), reject H0 (marked with **). Move to Rank = 1.

4. Continue until the first non-rejection.

5. The estimated cointegration rank is the rank where you first fail to
reject.

Example interpretation:

If Rank 0 is rejected (**) and Rank 1 is not rejected, the estimated
cointegration rank is r = 1, meaning there is one long-run equilibrium
relationship among the variables.

Fourier Test Table

The Fourier table adds two extra columns compared to Johansen:

Column Interpretation
Fourier Lambda Fourier Lambda-max statistic
Fourier Trace Fourier Trace statistic
cv(5%) Lambda 5% critical value for Fourier Lambda-max
cv(5%) Trace 5% critical value for Fourier Trace
Log-Likelihood Concentrated log-likelihood at rank r

Key differences from standard Johansen:

The Fourier critical values are larger than standard Johansen CVs because
the Fourier terms use additional degrees of freedom. This means the Fourier
test is more conservative: it may fail to reject when the standard Johansen
test rejects. This is the correct behavior when no break exists (the Fourier
terms are nuisance parameters).

When smooth breaks are present, the Fourier test controls for them and
provides correctly-sized inference, whereas the standard Johansen test may
spuriously reject or fail to reject.

Comparing Johansen and Fourier results:

Both reject at similar ranks: Cointegration relationship is robust to
break specification.

Johansen rejects but Fourier does not: The Johansen rejection may be
driven by an uncontrolled structural break. Trust the Fourier result.

Fourier rejects but Johansen does not: The structural break was masking
a cointegrating relationship. The Fourier test recovers it.

SBC Table

The SBC table compares three models at each rank:

Row Interpretation
Trace Trace statistic from each model
SBC Schwarz Bayesian Criterion value
Lower SBC is better (more parsimonious fit)
Lag Optimal lag order selected for each model
TB & F Break date (for SC-VECM) or frequency (for Fourier)
A dot (.) means no break parameter
5% cv 5% critical value from the selected model
Select Model selected by minimum SBC

How to read the SBC table:

1. Look at the "SBC" row. The smallest SBC value determines which model
fits best.

2. Look at the "Select" row to see which model was chosen.

3. If "Johansen" is selected, no structural break was detected.

4. If "SC-VECM" is selected, a sharp structural break was detected at the
date shown in "TB & F".

5. If "Fourier" is selected, a smooth structural break was detected at the
frequency shown in "TB & F".

6. Use the Trace statistic and cv from the selected model for inference.

Graph Interpretation

When the graph option is specified, fjcoint produces four diagnostic
graphs plus a combined panel (fjc_combined):

Graph 1: Time Series with Fourier Fit (fjc_timeseries)

What it shows: The first variable in the system (solid blue line) overlaid
with the fitted Fourier deterministic function (dashed red line).

How to interpret:

- If the Fourier fit (red dashed) tracks the broad movements of the series
well, a smooth structural break is present and the Fourier approach is
appropriate.

- The Fourier fit captures only the deterministic component (breaks,
shifts) -- it should follow the slow-moving trend, not the short-run
fluctuations.

- Large deviations between the series and the fit suggest the break may be
sharp rather than smooth (consider SC-VECM instead).

- If the fit is essentially flat (near the mean), the Fourier terms add
little and standard Johansen may suffice.

Graph 2: Fourier Smooth Break Approximation (fjc_fourier)

What it shows: The isolated Fourier component f(t) plotted as a shaded
area chart. This is the estimated smooth break function, stripped of the
intercept.

How to interpret:

- A smooth sinusoidal wave indicates a gradual structural shift in the
data-generating process.

- The amplitude (height) shows the magnitude of the break. Large
amplitude = large structural shift.

- The number of peaks and troughs corresponds to the frequency k.
With k=1, there is one complete cycle. With k=2, there are two cycles.

- If the curve is very close to zero throughout, there is no meaningful
smooth structural break -- standard Johansen is sufficient.

- The timing of peaks/troughs indicates when the structural shifts
occur. A peak followed by a trough suggests a U-shaped or inverted-U
break.

Graph 3: Variables in the Cointegration System (fjc_variables)

What it shows: All variables in the system plotted together on the same
axes, each in a different color.

How to interpret:

- Variables that move together (similar trends, turning points) are likely
to be cointegrated. They should show common stochastic trends.

- Variables that diverge persistently suggest the absence of cointegration
or the presence of structural breaks that disrupt the long-run
relationship.

- This graph helps verify that the variables are indeed I(1) (trending,
non-stationary) -- a prerequisite for cointegration testing.

- Sudden jumps or level shifts visible in one or more series suggest
structural breaks that should be controlled for (via Fourier or SC-VECM).

Graph 4: Regression Residuals (fjc_residuals)

What it shows: The residuals from regressing the first variable on the
Fourier terms (constant, sin, cos). These are the movements not
explained by the smooth break function.

How to interpret:

- Residuals should look roughly stationary (mean-reverting around zero)
if the Fourier terms adequately capture the break.

- Persistent trends in the residuals suggest the Fourier frequency k
may be too low -- try increasing k or using cumulative frequencies.

- Large spikes or outliers indicate possible sharp breaks or extreme
events not well captured by the smooth Fourier approximation.

- Heteroskedasticity (changing variance over time) in the residuals
may affect inference and suggests using robust methods.

Graph 5: Ordered Eigenvalues (fjc_eigenvals)

What it shows: Bar chart of the ordered eigenvalues from the
reduced-rank regression, from largest to smallest.

How to interpret:

- The eigenvalues represent the strength of each potential cointegrating
relationship. Larger eigenvalues = stronger cointegration.

- A sharp drop between eigenvalue i and i+1 visually suggests the
cointegrating rank is i.

- Eigenvalues close to zero correspond to non-cointegrating directions
(common stochastic trends).

- This graph is most useful for visual confirmation of the rank identified
by the formal test statistics.

Step-by-Step Applied Guide

Step 1: Check data prerequisites

- Declare time series: tsset time

- All variables must be I(1). Test with: dfuller y, lags(4). If any
variable is I(0), remove it from the system. If any variable is I(2), take
first differences.

Step 2: Run the standard Johansen test

. fjcoint y x1 x2, test(johansen) model(rc)

Examine the Trace column. Identify the cointegration rank (first
non-rejection). This is your baseline result.

Step 3: Check for structural breaks

. fjcoint y x1 x2, test(fourier) model(rc) freq(1) graph

Examine the Fourier Smooth Break graph. If the Fourier component is large
(substantial amplitude), breaks are present. Compare the Fourier test rank
with the Johansen rank from Step 2.

Step 4: Run the SBC procedure (recommended)

. fjcoint y x1 x2, test(sbc) model(rc) maxlag(4)

This is the most robust test. The SBC procedure automatically selects the
best model (Johansen, SC-VECM, or Fourier) and applies the corresponding
test. Use the selected model's rank for inference.

Step 5: Report results

Report the selected test, the estimated rank, and the test statistic with
its critical value. For example: "The SBC procedure selects the Fourier
model (k=1). The Fourier Trace test rejects the null of r=0 at 5% (Trace =
33.06, cv = 29.59) and fails to reject r=1 (Trace = 17.24, cv = 22.20),
indicating one cointegrating vector."

Examples

Example 1: Basic Johansen-Fourier test

. tsset time, monthly

. fjcoint y x1 x2

Example 2: Standard Johansen test

. fjcoint y x1 x2, test(johansen)

Example 3: Fourier with restricted constant and frequency 2

. fjcoint y x1 x2, test(fourier) model(rc) freq(2)

Example 4: Cumulative frequencies

. fjcoint y x1 x2, test(fourier) option(cumulative) freq(2)

Example 5: SBC model selection (recommended)

. fjcoint y x1 x2, test(sbc) maxlag(4)

Example 6: All tests with diagnostic graphs

. fjcoint y x1 x2, test(all) graph

Example 7: Replicating the paper application

Step 1: Unit root testing

dfuller y, lags(4)

dfuller x1, lags(4)

dfuller x2, lags(4)

Step 2: Standard Johansen

fjcoint y x1 x2, test(johansen) model(rc)

Step 3: Fourier test (single, k=1)

fjcoint y x1 x2, test(fourier) model(rc) freq(1)

Step 4: Fourier test (cumulative, k=2)

fjcoint y x1 x2, test(fourier) model(rc) freq(2) option(cumulative)

Step 5: SBC model selection

fjcoint y x1 x2, test(sbc) model(rc) maxlag(4) graph

Stored Results

fjcoint stores the following in r():

Scalars

r(nobs) number of effective observations used

r(nvars) number of variables in the system

r(maxlag) VAR lag order

r(frequency) Fourier frequency k

Macros

r(cmd) fjcoint

r(test) test name (johansen, fourier, sbc, all)

r(model) model specification (rc, constant, etc.)

r(option) frequency option (single, cumulative)

r(varlist) variable list used

Matrices (Johansen/Fourier tests)

r(eigenvalues) p x 1 vector of ordered eigenvalues

r(lambda) p x 1 vector of Lambda-max statistics

r(trace) p x 1 vector of Trace statistics

r(cv_trace) 1 x p vector of 5% Trace critical values

r(cv_lambda) 1 x p vector of 5% Lambda-max CVs (Fourier only)

r(logL) (p+1) x 1 vector of log-likelihood values

References

Pascalau, R., J. Lee, S. Nazlioglu, and Y.O. Lu (2022).
Johansen-type cointegration tests with a Fourier function.
Journal of Time Series Analysis 43(5): 828-852.

Johansen, S. (1991).
Estimation and hypothesis testing of cointegration vectors in Gaussian
vector autoregressive models.
Econometrica 59(6): 1551-1580.

Johansen, S. and K. Juselius (1990).
Maximum likelihood estimation and inference on cointegration with
applications to the demand for money.
Oxford Bulletin of Economics and Statistics 52(2): 169-210.

Harris, D., S.J. Leybourne, and A.R. Taylor (2016).
Tests of the co-integration rank in VAR models in the presence of a
possible break in trend at an unknown point.
Journal of Econometrics 192(2): 451-467.

Enders, W. and J. Lee (2012).
A unit root test using a Fourier series to approximate smooth breaks.
Oxford Bulletin of Economics and Statistics 74(4): 574-599.

Gallant, A.R. (1981).
On the bias in flexible functional forms and an essentially unbiased form.
Journal of Econometrics 15: 211-245.

Author

Dr Merwan Roudane

merwanroudane920@gmail.com

Translated from original GAUSS code by Saban Nazlioglu
(snazlioglu@pau.edu.tr).

Also see

Online: tsset, dfuller, pperron, vec,
vecrank