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.
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:
- F > I(1): Cointegration (clear result)
- F < I(0): No cointegration (clear result)
- I(0) < F < I(1): Inconclusive (problematic!)
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:
- Estimate the unrestricted model and obtain residuals \(\hat{\varepsilon}_t\)
- 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
- Compute bootstrap critical values from the empirical distribution
- Compare original statistics to bootstrap critical values
Basic Usage
Pythonfrom 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:
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
Pythonimport 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']}")
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
"Bootstrap cointegration tests in ARDL models." Economic Modelling, 116, 105987. https://doi.org/10.1016/j.econmod.2022.105987