Exercise · m10_ratio_meanrev.py
Is the gold/silver ratio mean-reverting?
not run yet
Not saved: sign up to keep your code"""M10 exercise: is the gold/silver ratio mean-reverting? (notes §10.7).
Model the log ratio x_t = ln(Gold_t / Silver_t) as an Ornstein-Uhlenbeck process
dx = kappa (theta - x) dt + sigma dW.
Sampled every dt it is an exact AR(1):
x_{k+1} = a + phi x_k + e_k, phi = exp(-kappa dt), a = theta (1 - phi),
Var(e) = sigma^2 (1 - phi^2) / (2 kappa).
Half-life in sampling periods: h = -ln 2 / ln phi (Proposition 10.11); in years h*dt = ln2/kappa.
Check with
cd exercises && .venv/bin/python -m pytest modules/M10-commodities/tests/test_m10_ratio_meanrev.py
"""
from __future__ import annotations
import warnings # noqa: F401 (statsmodels may emit a FutureWarning from adfuller)
import numpy as np
from statsmodels.tsa.stattools import adfuller # noqa: F401
def simulate_ou(kappa: float, theta: float, sigma: float, dt: float, n: int, x0: float | None = None, seed: int = 0) -> np.ndarray:
"""Exact-discretisation OU path of length n.
x[0] = x0 (theta if None); x[k] = theta + (x[k-1]-theta)*phi + sd*eps[k-1], with
phi = exp(-kappa dt), sd = sigma*sqrt((1-phi^2)/(2 kappa)),
eps = np.random.default_rng(seed).standard_normal(n - 1).
Raise ValueError unless kappa > 0, sigma >= 0, dt > 0.
"""
raise NotImplementedError
def fit_ar1(x: np.ndarray) -> tuple[float, float, float]:
"""OLS of x[1:] on (1, x[:-1]). Return (a, phi, s), s = residual std with n-2 degrees of freedom."""
raise NotImplementedError
def half_life(phi: float) -> float:
"""h = -ln 2 / ln phi for 0 < phi < 1, in sampling periods. Return inf if phi >= 1.
Raise ValueError if phi <= 0 (oscillating or degenerate decay has no half-life).
"""
raise NotImplementedError
def ou_from_ar1(a: float, phi: float, s: float, dt: float) -> tuple[float, float, float]:
"""Invert the exact AR(1) map. Return (kappa, theta, sigma):
kappa = -ln(phi)/dt, theta = a/(1-phi), sigma = s*sqrt(2 kappa/(1-phi^2)).
Raise ValueError unless 0 < phi < 1.
"""
raise NotImplementedError
def kendall_corrected_phi(phi_hat: float, n: int) -> float:
"""First-order bias correction: E[phi_hat] ~ phi - (1 + 3 phi)/n => phi ~ (n phi_hat + 1)/(n - 3).
n is the number of regression observations.
"""
raise NotImplementedError
def adf(x: np.ndarray, regression: str = "c", maxlag: int | None = None) -> tuple[float, float]:
"""Augmented Dickey-Fuller test via statsmodels.adfuller. Return (statistic, p-value). H0: unit root.
If maxlag is None use autolag='AIC'; otherwise use exactly maxlag lags (autolag=None).
"""
raise NotImplementedError
No runs yet
The stub's functions raise
NotImplementedError until you write them. Fill in one, press
Run tests, and watch its tests turn green.Reference solution
Available after your first run, with an account approved for code runs.