Metadata-Version: 2.4
Name: threshcoint
Version: 1.0.0
Summary: Comprehensive threshold cointegration tests and models in Python — TAR, MTAR, TVECM, supF, Hansen-Seo, and 12+ methods from the literature.
Home-page: https://github.com/merwanroudane/threshcoint
Author: Dr Merwan Roudane
Author-email: Dr Merwan Roudane <merwanroudane920@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/merwanroudane/threshcoint
Project-URL: Repository, https://github.com/merwanroudane/threshcoint
Project-URL: Documentation, https://github.com/merwanroudane/threshcoint#readme
Project-URL: Bug Tracker, https://github.com/merwanroudane/threshcoint/issues
Keywords: threshold,cointegration,econometrics,TAR,MTAR,TVECM,nonlinear,time-series,error-correction,Enders-Siklos,Hansen-Seo,asymmetric-adjustment,structural-breaks
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Education
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Office/Business :: Financial
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: English
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Provides-Extra: plot
Requires-Dist: matplotlib>=3.4; extra == "plot"
Provides-Extra: tables
Requires-Dist: tabulate>=0.8; extra == "tables"
Provides-Extra: full
Requires-Dist: matplotlib>=3.4; extra == "full"
Requires-Dist: tabulate>=0.8; extra == "full"
Requires-Dist: pandas>=1.3; extra == "full"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# threshcoint

<p align="center">
  <strong>Comprehensive Threshold Cointegration Tests & Models in Python</strong><br>
  <em>All major methods from 12+ academic papers, 3 R packages, and original R code — unified in one library.</em>
</p>

<p align="center">
  <a href="https://pypi.org/project/threshcoint/"><img src="https://img.shields.io/pypi/v/threshcoint?color=blue" alt="PyPI"></a>
  <a href="https://github.com/merwanroudane/threshcoint/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
  <img src="https://img.shields.io/badge/python-3.8%2B-blue" alt="Python">
</p>

---

## Author

**Dr Merwan Roudane**
- 📧 merwanroudane920@gmail.com
- 🔗 [github.com/merwanroudane/threshcoint](https://github.com/merwanroudane/threshcoint)

---

## Table of Contents

1. [Overview](#overview)
2. [Installation](#installation)
3. [Quick Start](#quick-start)
4. [Tests Reference](#tests-reference)
   - [Enders-Siklos TAR/MTAR](#1-enders--siklos-2001--tarmtar-test)
   - [GLS-MTAR (Cook 2007)](#2-gls-mtar-cook-2007)
   - [Extended E-S (Osińska & Gałecki 2022)](#3-extended-enders-siklos-osińska--gałecki-2022)
   - [Covariates-Augmented (Oh et al. 2017)](#4-covariates-augmented-oh-lee--meng-2017)
   - [Balke-Fomby Sup-Wald](#5-balke--fomby-1997-sup-wald)
   - [ADL-BDM (Li & Lee 2010)](#6-adl-bdm-li--lee-2010)
   - [ADL-BO (Li & Lee 2010)](#7-adl-bo-li--lee-2010)
   - [System ADL (Li 2016)](#8-system-adl-li-2016)
   - [supF* with Breaks (Schweikert 2019)](#9-supf-with-structural-breaks-schweikert-2019)
   - [Hansen-Seo supLM](#10-hansen--seo-2002-suplm)
   - [KSS Nonlinear Cointegration](#11-kss-2006-nonlinear-cointegration)
   - [BBC Unit Root vs SETAR](#12-bbc-2004-unit-root-vs-setar)
5. [Models Reference](#models-reference)
   - [TARModel](#tarmodel)
   - [MTARModel](#mtarmodel)
   - [EQ_TAR](#eq_tar)
   - [BandTAR](#bandtar)
   - [RD_TAR](#rd_tar)
   - [SETAR](#setar)
   - [TVECM](#tvecm)
6. [Visualization](#visualization)
7. [Comparison Table](#running-all-tests-at-once)
8. [Critical Values](#critical-values)
9. [Core Utilities](#core-utilities)
10. [Academic References](#academic-references)
11. [License](#license)

---

## Overview

`threshcoint` is a **pure-Python** library that implements **every major threshold cointegration test and model** from the econometrics literature. It consolidates methods from:

| Source | Methods Included |
|--------|-----------------|
| **Balke & Fomby (1997)** | EQ-TAR, Band-TAR, RD-TAR, sup-Wald test |
| **Enders & Siklos (2001)** | TAR / MTAR cointegration tests (Φ, F_asy, t_max) |
| **Lo & Zivot (2001)** | Bivariate TVECM testing & estimation |
| **Gonzalo & Pitarakis (2006)** | Threshold effects in cointegrating regressions |
| **Cook (2007)** | GLS-MTAR test with increased power |
| **Li & Lee (2010)** | ADL-BDM and ADL-BO tests |
| **Li (2016)** | System-equation ADL test |
| **Krishnakumar & Neto (2015)** | Cointegration rank in TVECM |
| **Wang, Chan & Yau (2016)** | Multiple-threshold cointegration |
| **Oh, Lee & Meng (2017)** | Covariates-augmented TAR/MTAR |
| **Schweikert (2019)** | supF* with structural breaks (from ZIP archive) |
| **Osińska & Gałecki (2022)** | Extended Enders-Siklos test |
| **tsDyn R package** | Hansen-Seo supLM, Seo sup-Wald, BBC test, TVECM |
| **NonlinearTSA R package** | Enders-Granger 1998, KSS 2006, ESTAR ECM, MTAR ECM, SETAR |

### Key Features

- ✅ **12+ threshold cointegration tests** with tabulated critical values
- ✅ **7 model classes** (TAR, MTAR, EQ-TAR, Band-TAR, RD-TAR, SETAR, TVECM)
- ✅ **No bootstrap required** for most tests (asymptotic critical values provided)
- ✅ **Grid search** for unknown thresholds with sup-type statistics
- ✅ **Publication-quality dark-themed visualizations**
- ✅ **Comparison tables** — run all tests on your data in one line
- ✅ **Pure NumPy/SciPy** — no R dependency

---

## Installation

```bash
# From GitHub
pip install git+https://github.com/merwanroudane/threshcoint.git

# Local install (development)
cd thrshcoint
pip install -e ".[full]"

# Minimal (no plotting)
pip install -e .
```

### Dependencies

| Package | Required | Purpose |
|---------|----------|---------|
| `numpy>=1.20` | ✅ Yes | Core computation |
| `scipy>=1.7` | ✅ Yes | Statistical distributions |
| `matplotlib>=3.4` | ⬜ Optional | Visualization |
| `tabulate>=0.8` | ⬜ Optional | Pretty tables |
| `pandas>=1.3` | ⬜ Optional | Data handling |

---

## Quick Start

```python
import numpy as np
import threshcoint as tc

# Generate example cointegrated data with threshold adjustment
np.random.seed(42)
T = 500
e = np.zeros(T)
for t in range(1, T):
    if e[t-1] > 0.5:
        e[t] = -0.4 * e[t-1] + np.random.normal(0, 0.5)
    elif e[t-1] < -0.5:
        e[t] = -0.8 * e[t-1] + np.random.normal(0, 0.5)
    else:
        e[t] = e[t-1] + np.random.normal(0, 0.5)

x = np.cumsum(np.random.normal(0, 1, T))
y = x + e

# Run Enders-Siklos MTAR test
result = tc.enders_siklos_test(y, x, model="mtar")
result.summary()

# Run ALL tests at once and compare
results = tc.comparison_table(y, x)

# Visualize regimes
tc.plot_regime_diagram(result.regression["resid"], result.threshold, model="mtar")
```

---

## Tests Reference

### 1. Enders & Siklos (2001) — TAR/MTAR Test

**The foundational threshold cointegration test.**

**Equation (TAR):**
```
Δê_t = ρ₁·I_t·ê_{t-1} + ρ₂·(1-I_t)·ê_{t-1} + Σγⱼ·Δê_{t-j} + ε_t
where I_t = 1{ê_{t-1} ≥ τ}
```

**Equation (MTAR):**
```
Same but M_t = 1{Δê_{t-1} ≥ τ}
```

**Hypotheses:**
- H₀: ρ₁ = ρ₂ = 0 (no cointegration)
- H₁: at least one ρ ≠ 0 (threshold cointegration)
- Symmetry test: H₀: ρ₁ = ρ₂

#### Syntax

```python
result = tc.enders_siklos_test(
    y,                  # array: dependent variable (I(1))
    x,                  # array: independent variable(s) (I(1))
    model="mtar",       # str: "tar" or "mtar"
    threshold=0.0,      # float: threshold value τ
    max_lag=8,          # int: maximum augmentation lag
    criterion="aic",    # str: "aic" or "bic" for lag selection
    case="c",           # str: "nc", "c", or "ct"
)
```

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.phi_stat` | Φ statistic = (t²_ρ₁ + t²_ρ₂) / 2 |
| `result.rho1` | Adjustment coefficient ρ₁ (above threshold) |
| `result.rho2` | Adjustment coefficient ρ₂ (below threshold) |
| `result.t_rho1` | t-statistic for ρ₁ |
| `result.t_rho2` | t-statistic for ρ₂ |
| `result.f_asymmetry` | F-statistic for H₀: ρ₁ = ρ₂ |
| `result.lags` | Selected lag order |
| `result.cv` | Critical values {0.01, 0.05, 0.10} |
| `result.conclusion` | Text: reject/fail-to-reject at 5% |
| `result.regime_obs` | (n₁, n₂) observations per regime |

#### Example

```python
result = tc.enders_siklos_test(y, x, model="mtar", threshold=0.0)
print(f"Φ = {result.phi_stat}, ρ₁ = {result.rho1}, ρ₂ = {result.rho2}")
print(f"Asymmetry F = {result.f_asymmetry}")
print(result.conclusion)
```

---

### 2. GLS-MTAR (Cook 2007)

**Higher power than standard MTAR via GLS local-to-unity detrending.**

#### Syntax

```python
result = tc.gls_mtar_test(
    y, x,
    threshold=0.0,      # float: MTAR threshold
    max_lag=8,           # int: max lag
    case="c",            # str: "c" (c̄=-7) or "ct" (c̄=-13.5)
    criterion="aic",     # str: lag selection criterion
    cbar=None,           # float or None: custom c̄ value
)
```

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.phi_gls_stat` | GLS-detrended Φ* statistic |
| `result.cv_5pct` | Interpolated 5% critical value for sample size T |

#### Example

```python
result = tc.gls_mtar_test(y, x, case="c")
print(f"Φ*_GLS = {result.phi_gls_stat}, CV(5%) = {result.cv_5pct}")
```

---

### 3. Extended Enders-Siklos (Osińska & Gałecki 2022)

**Uses individual variables (not ECM residual) as threshold variable. Splits both short-run and long-run.**

#### Syntax

```python
result = tc.extended_enders_siklos_test(
    y, x,
    threshold_var=None,  # array or None (default: Δx)
    model="mtar",        # str: "tar" or "mtar"
    max_lag=8,
    criterion="aic",
    trim=0.15,           # float: trimming for grid search
)
```

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.sup_phi_stat` | Supremum Φ over the grid |
| `result.estimated_threshold` | Optimal threshold from grid search |

---

### 4. Covariates-Augmented (Oh, Lee & Meng 2017)

**Augments E-S testing equation with Δx (stationary covariates) for power gains.**

#### Syntax

```python
result = tc.covariates_augmented_test(
    y, x,
    model="mtar",        # str: "tar" or "mtar"
    threshold=0.0,
    max_lag=8,
    criterion="aic",
)
```

---

### 5. Balke & Fomby (1997) Sup-Wald

**Two-step: (1) Engle-Granger, (2) sup-Wald for threshold behavior.**

#### Syntax

```python
result = tc.balke_fomby_supwald(
    y, x,
    max_lag=4,
    trim=0.15,
    n_grid=300,          # int: grid search resolution
)
```

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.sup_wald` | Sup-Wald statistic |
| `result.estimated_threshold` | Optimal threshold |
| `result.eg_stat` | Engle-Granger ADF statistic (step 1) |
| `result.grid_stats` | Array of Wald stats over grid |
| `result.grid_values` | Threshold grid values |

---

### 6. ADL-BDM (Li & Lee 2010)

**Cointegrating vector NOT pre-specified. Uses percentile-based grid search.**

#### Syntax

```python
result = tc.adl_bdm_test(
    y, x,
    max_lag=4,
    trim=0.15,
    n_grid=200,
    case="c",            # str: "c" or "ct"
)
```

---

### 7. ADL-BO (Li & Lee 2010)

**Boswijk variant: tests joint significance of lagged regressand AND lagged conditioning variables.**

#### Syntax

```python
result = tc.adl_bo_test(
    y, x,
    max_lag=4,
    trim=0.15,
    n_grid=200,
    case="c",
)
```

---

### 8. System ADL (Li 2016)

**System-equation test. No weak exogeneity required. Detects asymmetric speeds AND roles.**

#### Syntax

```python
result = tc.system_adl_test(
    data,                # (T, k) array: multivariate data
    lag=1,
    trim=0.15,
    n_grid=200,
    case="c",
)
```

---

### 9. supF* with Structural Breaks (Schweikert 2019)

**Threshold cointegration robust to structural breaks. Python translation of `supF.r` from the ZIP archive.**

#### Syntax

```python
result = tc.supF_test(
    y, x,
    model="tar",         # str: "tar" or "mtar"
    breaktype=1,         # int: 1=none, 2=intercept, 3=trend, 4=slope
    max_lag=4,
    threshold=0.0,       # float: TAR threshold
    u=None,              # float: MTAR percentile (e.g. 0.5)
    trim=0.15,
    criterion="aic",
)
```

#### Break Types

| Value | Type | Model |
|-------|------|-------|
| 1 | No break | Standard E-S |
| 2 | C₀ (intercept shift) | y = μ + DU·δ + α'x + e |
| 3 | C/T (trend shift) | y = μ + DU·δ + trend + α'x + e |
| 4 | C/S (slope shift) | y = μ + DU·δ + DU·x·δ₂ + α'x + e |

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.f_star` | supF* statistic |
| `result.breakpoint` | Estimated break date (index) |
| `result.rho1`, `result.rho2` | Regime-specific adjustment coefficients |

---

### 10. Hansen & Seo (2002) supLM

**Linear VECM vs. threshold VECM test. Python translation of `TVECM.HStest` from tsDyn.**

#### Syntax

```python
result = tc.hansen_seo_test(
    data,                # (T, 2) array
    lag=1,
    beta=None,           # float or None: cointegrating coefficient
    trim=0.05,
    n_grid=300,
    nboot=0,             # int: bootstrap replications (0 = asymptotic)
)
```

#### Output

| Attribute | Description |
|-----------|-------------|
| `result.supLM_stat` | Sup-LM statistic |
| `result.estimated_threshold` | Optimal threshold for ECT |
| `result.grid_stats` | LM values over the grid |

---

### 11. KSS (2006) Nonlinear Cointegration

**ESTAR-based cointegration test using cubic transformation. From NonlinearTSA package.**

#### Syntax

```python
result = tc.kss_cointegration_test(
    y, x,
    case=1,              # int: 1=raw, 2=demeaned, 3=detrended
    max_lag=8,
    criterion="aic",
)
```

---

### 12. BBC (2004) Unit Root vs SETAR

**Tests unit root null against stationary three-regime SETAR. From tsDyn package.**

#### Syntax

```python
result = tc.bbc_test(
    y,                   # array: univariate series
    m=1,                 # int: AR lag order
    trim=0.10,
    test_type="Wald",    # str: "Wald", "LM", or "LR"
)
```

---

## Models Reference

### TARModel

```python
model = tc.TARModel(threshold=0.0)
result = model.fit(residuals, max_lag=4, criterion="aic")
print(result.rho1, result.rho2, result.phi_stat)
```

### MTARModel

```python
model = tc.MTARModel(threshold=0.0)
result = model.fit(residuals, max_lag=4)
```

### EQ_TAR

```python
model = tc.EQ_TAR(threshold=None)   # None = grid search
result = model.fit(residuals, max_lag=4, trim=0.15, n_grid=300)
print(result.rho_low, result.rho_mid, result.rho_high)
print(result.regime_obs)   # [n_low, n_mid, n_high]
```

### BandTAR

```python
model = tc.BandTAR(threshold=0.5)
result = model.fit(residuals)
```

### RD_TAR

```python
model = tc.RD_TAR(threshold=None)
result = model.fit(residuals)
print(result.drift_low, result.drift_mid, result.drift_high)
```

### SETAR

```python
model = tc.SETAR(nthresh=1, delay=1, trim=0.15)
result = model.fit(y, lag=2, n_grid=300)
print(result.threshold, result.coefficients)
```

### TVECM

```python
model = tc.TVECM(nthresh=1, lag=1, trim=0.05, beta=None)
result = model.fit(data, n_grid=300)     # data shape (T, 2)
print(result.threshold, result.beta)
print(result.regime_obs)
# Access equation-by-equation regressions:
print(result.regressions["eq1"]["coef"])
```

---

## Visualization

### Regime Diagram

```python
import threshcoint as tc

result = tc.enders_siklos_test(y, x, model="mtar")
tc.plot_regime_diagram(
    residuals=result.regression["resid"],
    threshold=result.threshold,
    model="mtar",
    title="MTAR Regime Classification"
)
```

### Grid Search Plot

```python
result = tc.balke_fomby_supwald(y, x)
tc.plot_threshold_grid_search(
    grid_values=result.grid_values,
    grid_stats=result.grid_stats,
    title="Sup-Wald Grid Search"
)
```

### TVECM Regimes

```python
model = tc.TVECM(lag=1)
result = model.fit(data)
tc.plot_tvecm_regimes(
    ect=result.ect,
    data=data,
    threshold=result.threshold
)
```

### Results Table

```python
result = tc.gls_mtar_test(y, x)
tc.results_table(result)
```

---

## Running All Tests at Once

```python
import threshcoint as tc

# Run all tests and display comparison table
results = tc.comparison_table(y, x)

# Or manually select tests:
r1 = tc.enders_siklos_test(y, x, model="tar")
r2 = tc.enders_siklos_test(y, x, model="mtar")
r3 = tc.gls_mtar_test(y, x)
r4 = tc.covariates_augmented_test(y, x)

tc.summary_table({
    "TAR": r1,
    "MTAR": r2,
    "GLS-MTAR": r3,
    "Covariates-MTAR": r4,
})
```

---

## Critical Values

All critical values are tabulated in `threshcoint.critical_values`:

```python
from threshcoint.critical_values import (
    ES_TAR_PHI,          # Enders-Siklos TAR
    ES_MTAR_PHI,         # Enders-Siklos MTAR
    GLS_MTAR_PHI,        # Cook GLS-MTAR (by sample size)
    ADL_BDM_CV,          # Li & Lee ADL-BDM
    ADL_BO_CV,           # Li & Lee ADL-BO
    SUPF_BREAK_CV,       # Schweikert supF* with breaks
    BBC_CV,              # BBC unit root vs SETAR
    KSS_COINT_CV,        # KSS nonlinear cointegration
    COVAUG_TAR_CV,       # Oh et al. covariates-augmented TAR
    COVAUG_MTAR_CV,      # Oh et al. covariates-augmented MTAR
    get_gls_mtar_cv,     # Interpolation function
)

# Example: get 5% critical value for GLS-MTAR with T=200
cv = get_gls_mtar_cv(T=200, case="c", sig=0.05)
```

---

## Core Utilities

```python
from threshcoint import adf_test, pp_test, engle_granger_test

# ADF test
r = adf_test(y, max_lag=12, case="c", criterion="aic")
print(r["stat"], r["cv"])

# Phillips-Perron test
r = pp_test(y, case="c")

# Engle-Granger cointegration
r = engle_granger_test(y, x, case="c")
print(r["stat"], r["cv"], r["coint_vec"])
```

### Utility Functions

```python
from threshcoint.utils import (
    ols,              # OLS regression → dict with coef, resid, se, tstat, etc.
    embed,            # Time-delay embedding (like R's embed)
    lag_matrix,       # Build lag matrix
    gls_detrend,      # GLS local-to-unity detrending
    heaviside_tar,    # TAR indicator: I(z ≥ τ)
    heaviside_mtar,   # MTAR indicator: I(Δz ≥ τ)
    heaviside_band,   # Band-TAR: 3-regime indicator
)
```

---

## Academic References

1. Balke, N.S. & Fomby, T.B. (1997). Threshold cointegration. *International Economic Review*, 38(3), 627-645.
2. Enders, W. & Siklos, P.L. (2001). Cointegration and threshold adjustment. *JBES*, 19(2), 166-176.
3. Lo, M.C. & Zivot, E. (2001). Threshold cointegration and nonlinear adjustment to the law of one price. *Macroeconomic Dynamics*, 5, 533-576.
4. Hansen, B.E. & Seo, B. (2002). Testing for two-regime threshold cointegration in vector error-correction models. *J. Econometrics*, 110, 293-318.
5. Bec, F., Ben Salem, M. & Carrasco, M. (2004). Tests for unit-root versus threshold specification. *JBES*, 22(4).
6. Gonzalo, J. & Pitarakis, J.-Y. (2006). Threshold effects in cointegrating relationships. *Oxford Bull. Econ. Stat.*, 68(s1), 813-833.
7. Kapetanios, G., Shin, Y. & Snell, A. (2006). Testing for cointegration in nonlinear STAR ECM. *Econometric Theory*, 22(2), 279-303.
8. Cook, S. (2007). A threshold cointegration test with increased power. *Math. Comput. Simul.*, 73, 386-392.
9. Li, J. & Lee, J. (2010). ADL tests for threshold cointegration. *J. Time Ser. Anal.*, 31, 241-254.
10. Krishnakumar, J. & Neto, D. (2015). Testing for the cointegration rank in threshold systems. *Statistical Methodology*, 26, 84-102.
11. Li, J. (2016). System-equation ADL test for threshold cointegration. *Oxford Bull. Econ. Stat.*
12. Wang, C., Chan, N. & Yau, C. (2016). Nonlinear error correction model and multiple-threshold cointegration. *Statistica Sinica*, 26, 1479-1498.
13. Oh, D.-Y., Lee, H. & Meng, M. (2017). More powerful threshold cointegration tests. *Empirical Economics*.
14. Schweikert, K. (2019). Testing for cointegration with threshold adjustment in the presence of structural breaks. *SNDE*.
15. Osińska, M. & Gałecki, J. (2022). Extended Enders and Siklos test for threshold cointegration. *Statistical Review*, 69(1), 1-20.

---

## License

MIT License. Copyright (c) 2025 Dr Merwan Roudane.
