SPB Git

spb/wp41_uqo

Public
2.3 KB · 55 lines python
1"""HAR-RV at the intraday scale (Corsi 2009 adapted): log RV over the next H minutes regressed on log trailing RV over2the last 30 minutes, 390 minutes (one day) and 5 days (1,950 minutes), plus time-of-day seasonal log variance.3Fitted by OLS on training origins; predictive distribution Student-t with zero mean, scale from exp(fitted) and a4degrees-of-freedom estimated from standardised training residuals (method of moments, clipped to [2.5, 50])."""5from __future__ import annotations67import numpy as np89from ..data.windows import SymbolGrid, N_DAY10from .naive import _hist_returns111213def har_features(g: SymbolGrid, s: int, m: int, seas_prof: np.ndarray | None = None) -> np.ndarray:14    r, sl = _hist_returns(g, s, m, 6)15    if len(r) < 60:16        return None17    idx_today = np.flatnonzero(np.arange(len(r)) >= len(r) - m) if m > 0 else np.zeros(0, dtype=int)18    rv30 = np.mean(r[-30:] ** 2)19    rv390 = np.mean(r[-390:] ** 2)20    rv5d = np.mean(r ** 2)21    f = [np.log(rv30 + 1e-12), np.log(rv390 + 1e-12), np.log(rv5d + 1e-12)]22    return np.array(f)232425class HARRV:26    name = "har_rv"2728    def __init__(self):29        self.beta: dict[int, np.ndarray] = {}30        self.nu: dict[int, float] = {}31        self.sd: dict[int, float] = {}3233    @staticmethod34    def _design(X: np.ndarray, m: np.ndarray, H: int) -> np.ndarray:35        tod = (m + 1 + H / 2) / 389.036        return np.column_stack([np.ones(len(X)), X, tod, tod ** 2, np.log(H) * np.ones(len(X))])3738    def fit(self, X: np.ndarray, m: np.ndarray, rv: np.ndarray, cum: np.ndarray, H: int) -> None:39        A = self._design(X, m, H)40        y = np.log(rv + 1e-12)41        beta, *_ = np.linalg.lstsq(A, y, rcond=None)42        self.beta[H] = beta43        pred_var = np.exp(A @ beta)44        z = cum / np.sqrt(pred_var)45        k = float(np.mean(z ** 4) / np.mean(z ** 2) ** 2)   # kurtosis -> nu = 4 + 6/(k-3)46        nu = 4 + 6 / max(k - 3, 0.12)47        self.nu[H] = float(np.clip(nu, 2.5, 50))48        self.sd[H] = float(np.std(y - A @ beta))4950    def predict_batch(self, X: np.ndarray, m: np.ndarray, H: int) -> dict:51        A = self._design(X, m, H)52        var = np.exp(A @ self.beta[H] + 0.5 * self.sd[H] ** 2)   # log-normal mean correction53        nu = self.nu[H]54        return {"mu": np.zeros(len(X)), "scale": np.sqrt(var * (nu - 2) / nu), "nu": np.full(len(X), nu), "var": var}55
Files · main
Menu

Theme