Bootstrap Fourier NARDL

The Bootstrap Fourier NARDL combines the Fourier-NARDL framework with bootstrap-based cointegration tests following Bertelli, Vacca & Zoia (2022). This approach eliminates the inconclusive zone problem inherent in PSS bounds tests.

Overview

The PSS bounds test has a well-known limitation: when the F-statistic falls between the I(0) and I(1) critical value bounds, the test is inconclusive. The bootstrap approach resolves this by generating data-specific critical values through resampling.

Key Advantage

Bootstrap critical values are computed from your specific data, providing a definitive cointegration decision without inconclusive zones.

Motivation

The traditional PSS bounds test creates three possible outcomes:

The inconclusive zone can be frustrating for researchers. Moreover, tabulated critical values may not be accurate for small sample sizes or non-standard error distributions.

Theoretical Framework

Bertelli, Vacca & Zoia (2022) propose a comprehensive testing strategy with three tests:

Test 1 (F_ov): Overall F-test for cointegration

\[H_0: \rho = \theta^+ = \theta^- = 0 \text{ (no long-run relationship)}\]

Test 2 (t): Degenerate case of Type 1

\[H_0: \rho = 0 \text{ (dependent variable does not adjust)}\]

Test 3 (F_ind): Degenerate case of Type 2

\[H_0: \theta^+ = \theta^- = 0 \text{ (X not in long-run relationship)}\]

Three Bootstrap Tests

1. Overall F-test (F_ov)

Tests whether all level coefficients are jointly zero. This is the primary cointegration test.

2. t-test for Error Correction

Tests whether the error correction coefficient (\(\rho\)) is zero. If \(\rho = 0\), the dependent variable does not adjust to disequilibrium.

3. Independent Variables F-test (F_ind)

Tests whether the independent variables have zero long-run effect. If we reject \(H_0\) for F_ov but fail to reject for F_ind, we have a "degenerate" relationship.

Bootstrap Algorithm

The bootstrap procedure follows these steps:

  1. Estimate the unrestricted model and obtain residuals \(\hat{\varepsilon}_t\)
  2. For each bootstrap replication \(b = 1, \ldots, B\):
    • Resample residuals with replacement
    • Recenter resampled residuals (Davidson & MacKinnon, 2005)
    • Generate bootstrap \(y^*\) values
    • Re-estimate the model and compute test statistics
  3. Compute bootstrap critical values from the empirical distribution
  4. Compare original statistics to bootstrap critical values

Basic Usage

Python
from nardl_fourier import BootstrapNARDL # Fit Bootstrap Fourier NARDL model = BootstrapNARDL( data=df, depvar='coal', exog_vars=['gdp'], decomp_vars=['oil_price'], maxlag=4, max_freq=3, n_bootstrap=1000, # Number of bootstrap replications random_state=42 # For reproducibility ) # View summary with bootstrap tests print(model.summary()) # Get cointegration decision print(model.cointegration_decision())

Bootstrap Parameters

Parameter Type Description
n_bootstrap int Number of bootstrap replications (default: 1000)
bootstrap_case str Case for bootstrap test: 'II' or 'III' (default: 'III')
random_state int Random seed for reproducibility

Interpreting Results

The bootstrap test follows a decision flowchart:

🔍
Decision Flowchart

1. If F_ov is significant: Continue to next tests
2. If t is significant: Y adjusts to equilibrium ✓
3. If F_ind is significant: X appears in long-run ✓
4. All three significant: COINTEGRATION ✅

Possible Outcomes

F_ov t F_ind Conclusion
✓ Reject ✓ Reject ✓ Reject COINTEGRATION
✓ Reject ✓ Reject ✗ Fail ⚠️ Degenerate Type 2 (X not in long-run)
✓ Reject ✗ Fail ✓ Reject ⚠️ Degenerate Type 1 (Y does not adjust)
✗ Fail - - ❌ NO COINTEGRATION
Python
# Access detailed bootstrap results results = model.bootstrap_results print("Bootstrap Cointegration Tests:") print("=" * 50) for test in ['F_ov', 't', 'F_ind']: stat = results['statistics'][test] cv = results['critical_values'][test]['5%'] pval = results['p_values'][test] decision = '✓ Reject H₀' if results['conclusions'][test] else '✗ Fail to reject' print(f"\\n{test}:") print(f" Statistic: {stat:.4f}") print(f" Bootstrap CV 5%: {cv:.4f}") print(f" p-value: {pval:.4f}") print(f" Decision: {decision}") print("\\n" + "=" * 50) print(f"Overall: {results['overall']}") print(f"{results['interpretation']}")

Visualization

Visualize the bootstrap distributions to see how your test statistics compare:

Python
# Plot bootstrap distributions fig = model.plot_bootstrap_distributions(figsize=(15, 5)) # The plot shows: # - Histogram of bootstrap statistics # - Red line: observed statistic # - Green dashed line: 5% critical value fig.savefig('bootstrap_distributions.png', dpi=300, bbox_inches='tight')

Complete Example

Python
import pandas as pd import numpy as np from nardl_fourier import BootstrapNARDL # Load or create data np.random.seed(42) n = 150 df = pd.DataFrame({ 'coal': np.cumsum(np.random.randn(n)), 'oil_price': np.cumsum(np.random.randn(n)), 'gdp': np.cumsum(np.random.randn(n)) }) # Fit Bootstrap Fourier NARDL model = BootstrapNARDL( data=df, depvar='coal', exog_vars=['gdp'], decomp_vars=['oil_price'], maxlag=4, max_freq=2, n_bootstrap=1000, random_state=42 ) # Full summary output print(model.summary()) # Bootstrap summary table if model.bootstrap_test: table = model.bootstrap_test.summary_table() print("\\nBootstrap Tests Summary:") print(table.to_string(index=False)) # Final decision print("\\n" + "=" * 50) print(model.cointegration_decision()) # Compare with standard bounds test print("\\nComparison with PSS Bounds Test:") bt = model.bounds_test print(f" PSS F-statistic: {bt['f_statistic']:.4f}") print(f" PSS Decision: {bt['decision']['F_5%']}") print(f" Bootstrap Decision: {model.bootstrap_results['overall']}")
⏱️
Computation Time

Bootstrap tests require more computation time than standard bounds tests. For 1000 replications, expect several seconds to a minute depending on sample size and model complexity.

References

📚
Bertelli, S., Vacca, G., & Zoia, M. (2022)

"Bootstrap cointegration tests in ARDL models." Economic Modelling, 116, 105987. https://doi.org/10.1016/j.econmod.2022.105987