Nonlinear Unit Root Testing Library — 17+ tests with embedded critical values, automatic decisions, and publication-quality output
Project description
TARUR
Nonlinear Unit Root Testing Library for Python
17+ tests · Embedded critical values · Automatic decisions · Publication-quality output
--- ## Why TARUR? Most nonlinear unit root test implementations in R (e.g., `NonlinearTSA`) **do not include critical values**, forcing researchers to manually look them up in the original papers every single time. This is tedious, error-prone, and slows empirical research. **TARUR** solves this by: | Feature | Description | |---------|-------------| | ✅ **Embedded CVs** | All critical values from the original papers (asymptotic + finite-sample) | | ✅ **Auto decisions** | Reject / fail-to-reject at 1%, 5%, 10% — no manual comparison | | ✅ **One-line API** | `tarur.kss_test(y)` gives you everything | | ✅ **Full battery** | `tarur.run_all_tests(y)` runs 11+ tests at once | | ✅ **Bug fixes** | Corrects errors in R implementations (Kruse, Hu-Chen, Sollis 2009) | | ✅ **LaTeX export** | Publication-ready tables for your papers | --- ## Installation ```bash pip install tarur ``` From source: ```bash git clone https://github.com/merwanroudane/tarur.git cd tarur && pip install -e . ``` **Dependencies:** `numpy`, `scipy`, `pandas`, `matplotlib` (all standard scientific stack). --- ## Quick Start ```python import numpy as np import tarur # Load your time series (level, not differenced) y = np.cumsum(np.random.randn(300)) # Single test result = tarur.kss_test(y, case='demeaned', max_lags=8) print(result) # Full battery batch = tarur.run_all_tests(y, case='demeaned', max_lags=8) ``` Output: ``` ============================================================ KSS (2003) Nonlinear Unit Root Test ============================================================ H0: Unit root (linear random walk) H1: Globally stationary ESTAR process ------------------------------------------------------------ Test Statistic (tNL) | -1.649 Selected Lag | 4 (AIC) Case | demeaned ------------------------------------------------------------ Critical Values: 1%: -3.930 | 5%: -3.400 | 10%: -3.130 Source: Kapetanios, Shin & Snell (2003), Table 1 ------------------------------------------------------------ 1%: [ACCEPT] H0 5%: [ACCEPT] H0 10%: [ACCEPT] H0 ------------------------------------------------------------ >> Fail to reject H0. Unit root (linear random walk). ============================================================ ``` --- ## Researcher's Guide — Complete Test Reference ### 1. ESTAR-Based Unit Root Tests These tests are based on the Exponential Smooth Transition Autoregressive (ESTAR) model: $$y_t = y_{t-1} + \phi y_{t-1} G(\theta; y_{t-1}) + \varepsilon_t$$ where $G(\theta; y_{t-1}) = 1 - \exp(-\theta y_{t-1}^2)$ is the exponential transition function. Under H₀ ($\theta = 0$), the process is a unit root. Under H₁ ($\theta > 0$), the process is globally stationary with nonlinear mean reversion. --- #### 1.1 KSS (2003) — `kss_test()` **Reference:** Kapetanios, G., Shin, Y., & Snell, A. (2003). *Testing for a unit root in the nonlinear STAR framework.* Journal of Econometrics, 112(2), 359–379. **Auxiliary regression:** $$\Delta y_t = \beta_1 y_{t-1}^3 + \sum_{i=1}^{p} \rho_i \Delta y_{t-i} + u_t$$ **Test statistic:** $t_{NL} = \hat{\beta}_1 / \text{se}(\hat{\beta}_1)$ — a standard t-ratio. **Decision rule:** Reject H₀ when $t_{NL} < \text{CV}$ (left-tailed). **Critical values (asymptotic, Table 1):** | Case | 1% | 5% | 10% | |------|-----|-----|------| | Raw | −3.48 | −2.93 | −2.66 | | Demeaned | −3.93 | −3.40 | −3.13 | | Detrended | −3.40 | −2.93 | −2.66 | ```python result = tarur.kss_test(y, case='demeaned', max_lags=12, lag_method='aic') ``` **Interpretation:** If rejected, the series exhibits **globally stationary ESTAR dynamics** — it may wander away from its mean but will always revert back, with the speed of reversion increasing with the distance from equilibrium. --- #### 1.2 Kruse (2011) — `kruse_test()` **Reference:** Kruse, R. (2011). *A new unit root test against ESTAR based on a class of modified statistics.* Statistical Papers, 52(1), 71–85. **Improvement over KSS:** Allows a **nonzero location parameter** $c$ in the ESTAR model, which the KSS test implicitly restricts to zero. **Auxiliary regression:** $$\Delta y_t = \beta_1 y_{t-1}^3 + \beta_2 y_{t-1}^2 + \sum_{i=1}^{p} \rho_i \Delta y_{t-i} + u_t$$ **Test statistic (Modified Wald):** $$\tau = t^2_{\beta_{2\perp}=0} + \mathbb{1}(\hat{\beta}_1 < 0) \cdot t^2_{\beta_1=0}$$ **Decision rule:** Reject H₀ when $\tau > \text{CV}$ (right-tailed). > ⚠️ **Bug fix:** The R `NonlinearTSA` package incorrectly uses a standard Chi-squared test. TARUR implements the correct modified Wald τ with the indicator function from the paper. **Critical values (asymptotic, T=1000, Table 1):** | Case | 1% | 5% | 10% | |------|------|------|------| | Raw | 13.15 | 9.53 | 7.85 | | Demeaned | 13.75 | 10.17 | 8.60 | | Detrended | 17.10 | 12.82 | 11.10 | ```python result = tarur.kruse_test(y, case='demeaned', max_lags=12) ``` --- #### 1.3 Sollis (2009) — `sollis2009_test()` **Reference:** Sollis, R. (2009). *A simple unit root test against asymmetric STAR nonlinearity with an application to real exchange rates.* Economic Modelling, 26(1), 118–125. **Key contribution:** Tests whether mean reversion is **symmetric or asymmetric** — i.e., whether the speed of adjustment differs for positive vs negative deviations. **Auxiliary regression:** $$\Delta y_t = \phi_1 y_{t-1}^3 + \phi_2 y_{t-1}^4 + \sum_{i=1}^{p} \kappa_i \Delta y_{t-i} + \eta_t$$ **Two test statistics:** - **$F_{AE}$:** Joint F-test of $\phi_1 = \phi_2 = 0$ (unit root test, reject when $F > \text{CV}$) - **$F_{as}$:** F-test of $\phi_2 = 0$ (symmetry test) > ⚠️ **Bug fix:** The R code uses the wrong auxiliary regression. TARUR implements the correct AESTAR formulation from the paper. ```python result = tarur.sollis2009_test(y, case='demeaned', max_lags=12) # Access symmetry test print(f"Symmetry Fas: {result.extra['Fas']:.3f} (p={result.extra['Fas_pvalue']:.4f})") print(f" → {result.extra['symmetry_test']}") ``` **Interpretation:** If $F_{AE}$ rejects H₀ and $F_{as}$ also rejects, the series has **asymmetric** nonlinear mean reversion (e.g., real exchange rates that adjust faster from overvaluation than undervaluation). --- #### 1.4 Hu & Chen (2016) — `hu_chen_test()` **Reference:** Hu, J., & Chen, Z. (2016). *A unit root test against globally stationary ESTAR models when local condition is non-stationary.* Economics Letters, 146, 89–94. **Key contribution:** Allows for **locally explosive** but **globally stationary** ESTAR — the process can be locally non-stationary near the equilibrium but still globally mean-reverting. **Auxiliary regression:** $$\Delta y_t = \beta_1 y_{t-1} + \beta_2 y_{t-1}^2 + \beta_3 y_{t-1}^3 + \sum \rho_i \Delta y_{t-i} + u_t$$ **Test statistic:** 3-parameter modified Wald τ (right-tailed, reject when τ > CV). ```python result = tarur.hu_chen_test(y, case='demeaned', max_lags=12) ``` --- ### 2. Threshold / Asymmetric Unit Root Tests #### 2.1 Enders & Granger (1998) — `enders_granger_test()` **Reference:** Enders, W., & Granger, C.W.J. (1998). *Unit-root tests and asymmetric adjustment.* JBES, 16(3), 304–311. **Model:** Momentum Threshold Autoregression (MTAR): $$\Delta \hat{u}_t = I_t \rho^+ \hat{u}_{t-1} + (1 - I_t) \rho^- \hat{u}_{t-1} + \sum \delta_i \Delta \hat{u}_{t-i} + \varepsilon_t$$ where $I_t = 1$ if $\Delta y_{t-1} \geq 0$ (momentum indicator). **Test statistic:** $\Phi$ (joint F-test $\rho^+ = \rho^- = 0$, right-tailed). ```python result = tarur.enders_granger_test(y, case='demeaned', max_lags=12) # Asymmetric coefficients print(f"ρ⁺ = {result.extra['rho_pos']:.4f}, ρ⁻ = {result.extra['rho_neg']:.4f}") print(f"Symmetry test: F = {result.extra['F_symmetry']:.3f} (p={result.extra['F_sym_pvalue']:.4f})") ``` #### 2.2 Sollis (2004) — `sollis2004_test()` **Reference:** Sollis, R. (2004). *Asymmetric adjustment and smooth transitions.* J. Time Series Analysis, 25(3), 409–417. Combines smooth transition detrending with TAR-type asymmetric adjustment. ```python result = tarur.sollis2004_test(y, model='A', max_lags=8) ``` --- ### 3. Smooth Transition Unit Root Tests These tests first estimate a nonlinear smooth transition trend function via NLS, then apply an ADF test to the residuals. **Each has its own distinct critical values.** #### 3.1 LNV (1998) — `lnv_test()` **Reference:** Leybourne, S., Newbold, P., & Vougas, D. (1998). *Unit roots and smooth transitions.* J. Time Series Analysis, 19(1), 83–97. **Model A:** $y_t = \alpha_1 + \alpha_2 S_t(\gamma, \tau) + \nu_t$ (transition in mean) **Model B:** $y_t = \alpha_1 + \beta_1 t + \alpha_2 S_t(\gamma, \tau) + \nu_t$ (transition in intercept + trend) **Model C:** $y_t = \alpha_1 + \beta_1 t + \alpha_2 S_t(\gamma, \tau) + \beta_2 t S_t(\gamma, \tau) + \nu_t$ (transition in both) where $S_t(\gamma, \tau) = [1 + \exp(-\gamma(t - \tau T))]^{-1}$ is the logistic function. **Critical values (LNV 1998, Table I — Model A):** | T | 1% | 5% | 10% | |---|------|------|------| | 25 | −5.669 | −4.750 | −4.280 | | 50 | −5.095 | −4.363 | −4.009 | | 100 | −4.882 | −4.232 | −3.909 | | 200 | −4.761 | −4.161 | −3.851 | | 500 | −4.685 | −4.103 | −3.797 | ```python result = tarur.lnv_test(y, model='A', max_lags=12) ``` #### 3.2 Vougas (2006) — `vougas_test()` **Reference:** Vougas, D. (2006). *On unit root testing with smooth transitions.* Computational Statistics & Data Analysis, 51(2), 797–800. Extends LNV with **5 functional forms** (Models A–E), including trend-only transitions. ```python # Test all 5 models for m in ['A', 'B', 'C', 'D', 'E']: r = tarur.vougas_test(y, model=m, max_lags=12) cv5 = r.critical_values.cv5 print(f"Model {m}: t = {r.statistic:.3f}, CV(5%) = {cv5:.3f}, {'REJECT' if r.decision.get('5%') else 'ACCEPT'}") ``` #### 3.3 Harvey & Mills (2002) — `harvey_mills_test()` **Reference:** Harvey, D.I., & Mills, T.C. (2002). *Unit roots and double smooth transitions.* J. Applied Statistics, 29(5), 675–683. **Key feature:** Allows **two** smooth transitions (double structural break). The critical values are substantially larger in absolute value than LNV because the more flexible alternative shifts the null distribution. **Critical values (Harvey & Mills 2002, Table 1 — Model A):** | T | 1% | 5% | 10% | |---|------|------|------| | 50 | −6.49 | −5.73 | −5.33 | | 100 | −6.05 | −5.37 | −5.04 | | 200 | −5.80 | −5.20 | −4.90 | | 1000 | −5.64 | −5.07 | −4.79 | ```python result = tarur.harvey_mills_test(y, model='A', max_lags=12) ``` #### 3.4 Cook & Vougas (2009) — `cook_vougas_test()` **Reference:** Cook, S., & Vougas, D. (2009). *Unit root testing against an ST–MTAR alternative.* Applied Economics, 41(11), 1397–1404. Combines smooth transition detrending with **MTAR** asymmetric adjustment (F-statistic). --- ### 4. Grid-Search Tests #### 4.1 Kılıç (2011) — `kilic_test()` **Reference:** Kılıç, R. (2011). *Testing for a unit root in a stationary ESTAR process.* Econometric Reviews, 30(3), 274–302. Uses a **grid search** over the transition parameter γ to find the infimum of the t-statistic, which has greater power than fixing γ. ```python result = tarur.kilic_test(y, case='demeaned', max_lags=12) print(f"Optimal γ: {result.extra['optimal_gamma']:.4f}") ``` #### 4.2 Park & Shintani (2016) — `park_shintani_test()` **Reference:** Park, J.Y., & Shintani, M. (2016). *Testing for a unit root against transitional autoregressive models.* International Economic Review, 57(2), 635–664. ```python result = tarur.park_shintani_test(y, case='raw', max_lags=12) ``` --- ### 5. Extended Tests #### 5.1 Pascalau (2007) — `pascalau_test()` Tests against **asymmetric NLSTAR** with y⁴, y³, y² regressors (F-test, right-tailed). #### 5.2 Cuestas & Garratt (2011) — `cuestas_garratt_test()` **Cubic polynomial detrending** followed by KSS-type regression. χ² test statistic. #### 5.3 Cuestas & Ordóñez (2014) — `cuestas_ordonez_test()` **NLS logistic detrending** (allows smooth transition in trend) followed by KSS test on residuals. ```python result = tarur.cuestas_garratt_test(y, max_lags=12) result = tarur.cuestas_ordonez_test(y, max_lags=12) ``` --- ### 6. Cointegration Tests #### 6.1 KSS Nonlinear Cointegration — `kss_cointegration_test()` Tests whether two series are cointegrated in a **nonlinear** sense (ESTAR stationary residuals). ```python result = tarur.kss_cointegration_test(y1, y2, case='demeaned', max_lags=12) ``` #### 6.2 Enders & Siklos (2001) — `enders_siklos_test()` **Threshold cointegration** — tests for cointegration with asymmetric adjustment in the equilibrium error. ```python result = tarur.enders_siklos_test(y1, y2, max_lags=12) ``` --- ### 7. Linearity & Diagnostics #### 7.1 Teräsvirta (1994) — `terasvirta_test()` Tests linearity and suggests whether **LSTAR** or **ESTAR** is more appropriate. ```python result = tarur.terasvirta_test(y, d=1) print(f"Suggested model: {result.extra['suggested_model']}") ``` #### 7.2 ARCH Test — `arch_test()` Engle (1982) LM test for ARCH effects. #### 7.3 McLeod-Li Test — `mcleod_li_test()` Portmanteau test for nonlinear dependence in squared residuals. --- ## API Reference ### Common Parameters | Parameter | Options | Description | |-----------|---------|-------------| | `case` | `'raw'`, `'demeaned'`, `'detrended'` | Deterministic terms | | `max_lags` | integer (default 8) | Maximum lag order for augmentation | | `lag_method` | `'aic'`, `'bic'`, `'t-stat'` | Automatic lag selection criterion | | `model` | `'A'`–`'E'` | Smooth transition model specification | ### TestResult Object ```python result.statistic # Test statistic value result.statistic_name # Label (e.g., "tNL", "τ", "F_AE") result.critical_values # CriticalValues with .cv1, .cv5, .cv10 result.decision # {"1%": bool, "5%": bool, "10%": bool} result.interpretation # Plain-English interpretation result.selected_lag # Optimal lag order result.case # Deterministic specification used result.model_summary # Regression coefficients, R², AIC, BIC result.extra # Test-specific extras result.reference # Full citation # Export result.to_dict() # Flat dictionary for DataFrame result.to_latex() # LaTeX table snippet result.plot() # Visualization ``` ### BatchResult Object ```python batch = tarur.run_all_tests(y, case='demeaned', max_lags=8) batch.summary() # Comparison DataFrame batch.to_latex() # Full LaTeX table batch.plot() # Dashboard visualization print(batch) # Formatted table ``` --- ## Recommended Workflow for Researchers ```python import numpy as np import tarur # 1. Load your data (log-levels for financial data) y = np.log(your_price_series) # 2. Test for linearity first lin = tarur.terasvirta_test(np.diff(y), d=1) print(f"Linearity p-value: {lin.extra['p_linearity']:.4f}") print(f"Suggested model: {lin.extra['suggested_model']}") # 3. Run the full nonlinear unit root battery batch = tarur.run_all_tests(y, case='demeaned', max_lags=12) # 4. Get summary table for your paper df = batch.summary() print(df[['test', 'statistic', 'cv_5%', 'reject_5%']].to_string(index=False)) # 5. Export to LaTeX print(batch.to_latex()) # 6. Visualization for presentations batch.plot() ``` --- ## Critical Values — Complete Mapping Every test uses its **own distinct critical values** from its original paper: | Test | Source | Table | Type | Tail | |------|--------|-------|------|------| | KSS (2003) | KSS, Table 1 | Asymptotic | t-type | Left | | Kruse (2011) | Kruse, Table 1 | Asymptotic (T=1000) | Wald τ | Right | | Sollis (2009) | Sollis, Table 1 | Finite-sample (T=50–200) | F-type | Right | | Hu & Chen (2016) | Hu & Chen, Table 1 | Asymptotic (T=1000) | Wald τ | Right | | Enders & Granger (1998) | E&G, Table 1 | Asymptotic | F-type | Right | | LNV (1998) | LNV, Table I | Finite-sample (T=25–500) | t-type | Left | | Vougas (2006) | Vougas, Table 1 | Finite-sample (T=25–500) | t-type | Left | | Harvey & Mills (2002) | H&M, Table 1 | Finite-sample (T=50–1000) | t-type | Left | | Cook & Vougas (2009) | C&V, Table 1 | Finite-sample (T=50–500) | F-type | Right | | Sollis (2004) | Sollis, Table II | Simulated (T=100) | F-type | Right | | Kılıç (2011) | Kılıç, Table 1 | Asymptotic (grid-search) | t-type | Left | | Park & Shintani (2016) | P&S, Table 1 | Asymptotic | t-type | Left | | Pascalau (2007) | Pascalau | Simulated | F-type | Right | | Cuestas & Garratt (2011) | C&G | Simulated | χ²-type | Right | --- ## Bug Fixes vs R `NonlinearTSA` Package | Issue | R Code | TARUR (Correct) | |-------|--------|-----------------| | **Kruse (2011)** | Uses standard Wald/Chi² | Modified Wald τ with indicator function | | **Hu & Chen (2016)** | Same as above | 3-parameter modified Wald with orthogonalization | | **Sollis (2009)** | Wrong auxiliary regression | Correct AESTAR with y³ and y⁴ | | **TAR/MTAR** | Depends on `tsDyn` R package | Fully native Python implementation | | **Critical values** | Not included | All embedded from original papers | --- ## Visualization ```python # Series diagnostic plot tarur.plot_series_analysis(y, title='Real Exchange Rate') # Individual test result result = tarur.kss_test(y) result.plot() # Full battery dashboard batch = tarur.run_all_tests(y) batch.plot() ``` --- ## Citation If you use TARUR in your research, please cite: ```bibtex @software{tarur2024, author = {Roudane, Merwan}, title = {TARUR: Nonlinear Unit Root Testing Library for Python}, year = {2024}, url = {https://github.com/merwanroudane/tarur} } ``` --- ## Author **Dr. Merwan Roudane** 📧 merwanroudane920@gmail.com 🔗 [github.com/merwanroudane/tarur](https://github.com/merwanroudane/tarur) ## License MIT License — see [LICENSE](LICENSE) for details. ]]>Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
tarur-1.0.0.tar.gz
(39.7 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
tarur-1.0.0-py3-none-any.whl
(45.1 kB
view details)
File details
Details for the file tarur-1.0.0.tar.gz.
File metadata
- Download URL: tarur-1.0.0.tar.gz
- Upload date:
- Size: 39.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12d3c835df87846755bb7ae9bcb2f557a878a9fe8f9aedd9e0aed585ec70223f
|
|
| MD5 |
303d572af64da5d4c8f3ea602d8e1ecb
|
|
| BLAKE2b-256 |
6a7a277b7b8fdedfb8b83c9e41ae114af742fe5e2a035dd94a51b9faf6a46756
|
File details
Details for the file tarur-1.0.0-py3-none-any.whl.
File metadata
- Download URL: tarur-1.0.0-py3-none-any.whl
- Upload date:
- Size: 45.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39ec610fd60a84745e0dc469f5da00d12971e5efead3ad2075364f23561d0c7f
|
|
| MD5 |
88406e916b8272cd14d464a324ab4956
|
|
| BLAKE2b-256 |
a4c3e6b3a338d73a15612117ab669b1ee97253d2542c33c28912f5bb2cca3b66
|