Skip to content

nessos666/quant-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quant Tools

Statistical tooling for quantitative finance — Ornstein-Uhlenbeck processes, volatility estimation, and core types.

Why · The Math · Quick Start · OU Module · Validation

Python 3.11+ MIT License Minimal deps Tests passing Stars


Why?

Most quant libraries are either too academic (no practical interface) or too black-box (no transparency into what's happening under the hood).

Quant Tools is a middle ground — correct math with clean Python APIs. Every estimator has the reference paper clearly documented, and results are validated against independent implementations.

Currently focused on:

  • Ornstein-Uhlenbeck processes — MLE fitting, simulation, stationarity tests, bias correction
  • Volatility estimation — quadratic variation, realized volatility, efficient estimators
  • Core types — Pydantic models for FitResult, SimParams, VolaResult with serialization

Why Traders Need This

The OU process is the mathematical backbone of mean reversion detection. Every trader asks:

  • "Is NQ mean-reverting right now, or trending?"
  • "How fast does price snap back to the mean?"
  • "Is my entry zone statistically valid or just noise?"

This library answers those questions with correct math — not heuristics.

from quant_tools.ou.estimator import fit_mle, half_life
from quant_tools.ou.stationarity import hurst_exponent

# Load 15-second NQ bars, NY session only
bars = load_nq_bars("2024-01-01", "2024-06-30", session="NY")

# Fit OU model → how fast does price mean-revert?
fit = fit_mle(bars["close"], dt=1/252/24/4)  # 15s bars
h = hurst_exponent(bars["close"])

print(f"Mean reversion speed θ:  {fit.mean_rev_speed:.3f}")
print(f"Half-life:               {half_life(fit.mean_rev_speed):.0f} bars")
print(f"Hurst exponent:          {h:.3f}")

# Interpretation:
# θ > 2.0 + H < 0.45 → strong mean reversion → fade extremes
# θ < 0.5 + H > 0.55 → trending market → trade with momentum
# Otherwise → noise → stay out

This isn't theory. This is the same math used by quant funds to separate mean-reverting regimes from trending ones — applied to NQ futures.


The Math Behind It

What is an Ornstein-Uhlenbeck Process?

The OU process is the continuous-time equivalent of an AR(1) model. It's the standard model for mean-reverting behavior in finance:

dX(t) = θ(μ - X(t))dt + σ dW(t)
Symbol Meaning Intuition
θ (theta) Mean reversion speed Higher = faster pull toward mean
μ (mu) Long-term mean level Price oscillates around this value
σ (sigma) Volatility Random component magnitude
dW(t) Wiener process Random noise (Brownian motion)

Key insight: When price X(t) is above μ, the drift term θ(μ − X(t)) becomes negative — pulling price back down. Below μ, it pulls up. The strength of this pull is proportional to distance from the mean.

Half-Life

The half-life tells you how many days (or bars) it takes for a deviation from the mean to decay by 50%:

τ = ln(2) / θ
θ Half-Life Interpretation
10 ~17 hours (1/252yr) Fast mean reversion — scalp-friendly
1 ~6 months (0.69yr) Slow mean reversion — swing trading
0.05 ~14 years Essentially a random walk

Why MLE and Not OLS?

Ordinary Least Squares (AR(1) regression) gives biased estimates in small samples. The bias is:

E[θ̂] ≈ θ − (1 + 3θ) / N

Where N is your sample size. For N=250 (1 year of daily data), this bias can be 10-20%. The bias_correct() function applies the Shaman-Stine (1988) correction to fix it.

Transition Density

The OU process has a known closed-form transition density (exact, not Euler). This means:

  • Simulation uses the exact distribution, not an approximation
  • MLE fitting uses the exact likelihood, not a noisy proxy
  • Confidence intervals are analytically computable
X(t+dt) | X(t) ~ Normal( μ + (X(t) - μ)e^{-θdt}, σ²(1 - e^{-2θdt}) / 2θ )

Quick Start

pip install quant-tools

Or from source:

git clone https://github.com/nessos666/quant-tools.git
cd quant-tools
pip install -e .

Ornstein-Uhlenbeck

The OU module provides end-to-end workflow for mean-reverting processes.

Fit an OU process to market data

from quant_tools.ou.estimator import fit_mle, half_life, bias_correct
from quant_tools.core.types import FitResult

# prices = pd.Series(...)  # your price data
prices = ...

# MLE fit — discrete-time exact likelihood
result: FitResult = fit_mle(prices, dt=1/252)

print(f"Mean reversion speed θ: {result.mean_rev_speed:.4f}")
print(f"Mean reversion level μ:  {result.mean_rev_level:.4f}")
print(f"Volatility σ:            {result.vola:.4f}")
print(f"Half-life:               {half_life(result.mean_rev_speed):.1f} days")

# Apply finite-sample bias correction
corrected = bias_correct(result, dt=1/252)

Simulate OU paths

from quant_tools.ou.simulator import path
import numpy as np

# Simulate 10 years of daily data
sim = path(
    x0=0.0,
    n_steps=2520,
    dt=1/252,
    params=FitResult(mean_rev_speed=5.0, mean_rev_level=0.0, vola=0.02),
    seed=42
)
# sim is a numpy array of shape (2520,)

Stationarity tests

from quant_tools.ou.stationarity import adf_test, hurst_exponent

# Augmented Dickey-Fuller with OU-aware lag selection
adf_result = adf_test(prices)
print(f"ADF statistic: {adf_result.statistic:.4f}, p-value: {adf_result.pvalue:.4f}")

# Hurst exponent via rescaled range (R/S)
h = hurst_exponent(prices)
print(f"Hurst: {h:.4f}")  # < 0.5 = mean-reverting, > 0.5 = trending

Volatility estimation

from quant_tools.ou.estimator import est_vola_qv

# Model-free volatility from quadratic variation
vola = est_vola_qv(prices, dt=1/252)
print(f"Annualized volatility: {vola:.4f}")

Validated Against

Implementation Result Status
Wergieluk (2019) OU-MLE θ, μ, σ match to 1e-6 ✅ Verified
Analytical OU transition density Closed-form vs. simulation ✅ Verified
Scipy ADF test p-values match ✅ Verified
Hurst R/S (Weron 2002) H within ±0.01 ✅ Verified
Quadratic variation (Barndorff-Nielsen) RV matches reference ✅ Verified

See tests/test_ou_integration.py for the full cross-validation suite.


Project Structure

quant_tools/
├── __init__.py
├── core/
│   ├── __init__.py
│   └── types.py           # FitResult, SimParams, VolaResult (Pydantic)
└── ou/
    ├── __init__.py
    ├── estimator.py        # fit_mle, bias_correct, est_vola_qv, transition_density
    ├── simulator.py        # exact OU path simulation
    └── stationarity.py     # adf_test, hurst_exponent
tests/
├── test_core_types.py
├── test_ou_estimator.py
├── test_ou_integration.py  # Cross-validation against reference implementations
├── test_ou_rolling.py
├── test_ou_simulator.py
└── test_ou_stationarity.py

Testing

pytest tests/ -v

All 6 test suites pass. The integration test validates against the Wergieluk reference implementation.


Philosophy

  1. Correctness first — every estimator cross-validated against academic reference implementations
  2. Clean interfaces — typed, documented, Pydantic-backed models
  3. No black boxes — open math, clear references. You can verify every formula.
  4. Minimal dependencies — numpy, scipy, pandas, pydantic, loguru. No ML bloat.

Related

Part of the NQ research ecosystem:


License

MIT — use it, validate it, improve it.

Built for systematic NQ futures research. Correct math, clean APIs, verified results.
github.com/nessos666

About

Statistical tooling for quantitative finance — Ornstein-Uhlenbeck MLE fitting, simulation, stationarity tests, bias correction, and volatility estimation.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages