NARDL Model

The Nonlinear Autoregressive Distributed Lag (NARDL) model extends the linear ARDL framework to capture asymmetric effects in cointegrating relationships. Based on the seminal work of Shin, Yu & Greenwood-Nimmo (2014).

Overview

Traditional cointegration analysis assumes symmetric adjustments to equilibrium. However, many economic relationships exhibit asymmetry—variables may respond differently to positive versus negative changes. The NARDL model addresses this by decomposing regressors into partial sums of positive and negative changes.

📊
Key Features

NARDL allows testing for both short-run and long-run asymmetric effects while maintaining the advantages of the ARDL bounds testing approach for variables with mixed integration orders I(0)/I(1).

Theoretical Framework

The NARDL approach rests on the concept of asymmetric cointegration. Consider a long-run relationship between \(y_t\) and \(x_t\):

\[y_t = \beta^+ x_t^+ + \beta^- x_t^- + u_t\]

where \(x_t^+\) and \(x_t^-\) are partial sum processes of positive and negative changes in \(x_t\):

\[x_t^+ = \sum_{j=1}^{t} \Delta x_j^+ = \sum_{j=1}^{t} \max(\Delta x_j, 0)\] \[x_t^- = \sum_{j=1}^{t} \Delta x_j^- = \sum_{j=1}^{t} \min(\Delta x_j, 0)\]

Model Specification

The NARDL(p,q) error correction model is specified as:

\[\Delta y_t = \rho y_{t-1} + \theta^+ x_{t-1}^+ + \theta^- x_{t-1}^- + \sum_{j=1}^{p-1} \gamma_j \Delta y_{t-j} + \sum_{j=0}^{q} (\pi_j^+ \Delta x_{t-j}^+ + \pi_j^- \Delta x_{t-j}^-) + \varepsilon_t\]

Where:

Basic Usage

Python
from nardl_fourier import NARDL import pandas as pd # Load your data df = pd.read_csv('data.csv', index_col=0, parse_dates=True) # Fit NARDL model model = NARDL( data=df, depvar='coal', # Dependent variable exog_vars=['gdp', 'gdp2'], # Control variables (linear) decomp_vars=['oil_price'], # Variables to decompose (asymmetric) maxlag=4, # Maximum lag order ic='AIC', # Information criterion case=3 # Case for bounds test ) # View summary print(model.summary())

Parameters Explained

Parameter Type Description
data DataFrame Pandas DataFrame with time series data
depvar str Name of the dependent variable column
exog_vars list List of exogenous/control variable names (enter linearly)
decomp_vars list Variables to decompose into positive/negative components
maxlag int Maximum lag order to consider (default: 4)
ic str Information criterion: 'AIC', 'BIC', or 'HQIC'
case int Bounds test case (1-5, default: 3)

Partial Sum Decomposition

The core of NARDL is the partial sum decomposition. For any variable \(x\), we compute:

Python
from nardl_fourier.utils import partial_sum_decomposition # Decompose a variable x_positive, x_negative = partial_sum_decomposition(df['oil_price']) # x_positive: cumulative sum of positive changes # x_negative: cumulative sum of negative changes print(f"Final positive sum: {x_positive[-1]:.2f}") print(f"Final negative sum: {x_negative[-1]:.2f}")

Long-Run Multipliers

Long-run multipliers measure the cumulative impact of a unit change in \(x\) on \(y\):

\[L^+ = -\frac{\theta^+}{\rho} \quad \text{and} \quad L^- = -\frac{\theta^-}{\rho}\]
Python
# Access long-run multipliers lr = model.long_run['oil_price'] print("Long-Run Multipliers:") print(f" L⁺ (positive): {lr['positive']['coefficient']:.4f}") print(f" Std.Error: {lr['positive']['std_error']:.4f}") print(f" p-value: {lr['positive']['p_value']:.4f}") print(f" L⁻ (negative): {lr['negative']['coefficient']:.4f}") print(f" Std.Error: {lr['negative']['std_error']:.4f}") print(f" p-value: {lr['negative']['p_value']:.4f}")

Short-Run Dynamics

Short-run coefficients capture the immediate dynamic adjustments:

Python
# Error Correction Term ect = model.ect print(f"ECT (ρ): {ect['coefficient']:.4f}") print(f"Half-life: {ect['half_life']:.2f} periods") # Short-run coefficients table from nardl_fourier import ResultsTable table = ResultsTable(model) sr_df = table.short_run_table() print(sr_df)
⚠️
ECT Validity

The error correction term (ρ) should be negative and significant. If ρ ≥ 0 or |ρ| > 2, the model may be unstable.

Bounds Test for Cointegration

The PSS bounds test examines whether a long-run relationship exists:

Python
# Access bounds test results bt = model.bounds_test print("PSS Bounds Test:") print(f" F-statistic: {bt['f_statistic']:.4f}") print(f" Critical Values (5%):") print(f" I(0): {bt['critical_values']['F']['5%']['I(0)']:.4f}") print(f" I(1): {bt['critical_values']['F']['5%']['I(1)']:.4f}") print(f" Decision: {bt['decision']['F_5%']}")

Interpretation

Testing for Asymmetry

Wald tests formally examine whether positive and negative effects are statistically different:

Python
# Access Wald test results wald = model.wald['oil_price'] # Short-run asymmetry print("Short-Run Asymmetry Test:") print(f" H₀: π⁺ = π⁻ at all lags") print(f" F-statistic: {wald['short_run']['f_statistic']:.4f}") print(f" p-value: {wald['short_run']['p_value']:.4f}") print(f" Asymmetric: {wald['short_run']['asymmetric']}") # Long-run asymmetry print("\\nLong-Run Asymmetry Test:") print(f" H₀: L⁺ = L⁻") print(f" F-statistic: {wald['long_run']['f_statistic']:.4f}") print(f" p-value: {wald['long_run']['p_value']:.4f}") print(f" Asymmetric: {wald['long_run']['asymmetric']}")

Complete Example

Python
import pandas as pd import numpy as np from nardl_fourier import NARDL, ResultsTable, NARDLPlots # Create sample data np.random.seed(42) n = 200 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 NARDL model model = NARDL( data=df, depvar='coal', exog_vars=['gdp'], decomp_vars=['oil_price'], maxlag=4, ic='AIC' ) # Print full summary print(model.summary()) # Generate publication tables table = ResultsTable(model) print("\\nLong-Run Multipliers:") print(table.long_run_table()) print("\\nDiagnostics:") print(table.diagnostics_table()) # Export to LaTeX table.to_latex('nardl_results.tex') # Create plots plots = NARDLPlots(model) plots.dynamic_multipliers('oil_price', horizon=20) plots.cusum()
🎉
Next Steps

For handling structural breaks, see Fourier NARDL. For eliminating inconclusive bounds test results, see Bootstrap NARDL.