ConformalWrapper¶
Defined in fynance.models.conformal
- class ConformalWrapper(model, alpha=0.1, window=252)[source]
Bases:
objectCausal split-conformal prediction interval around a point model.
Wraps a
modelexposingfit(X, y)/predict(X)(theSignalModelcontract).fittrainsmodelon the leadingT - windowbars only and calibrates the interval half-widthq_haton the absolute residuals of the trailingwindowbars – bars the wrapped model never saw during its own fit, so the calibration is honest (no in-sample residuals).- Parameters:
- modelSignalModel
Any regressor exposing
fit(X, y)(returns anything,selfis conventional) andpredict(X) -> array-like.- alphafloat, optional
Miscoverage level in
(0, 1); the interval targets marginal coverage1 - alpha. Default 0.1 (90% interval).- windowint, optional
Number of trailing bars held out for calibration. Must be strictly less than the number of observations passed to
fit. Default 252 (one trading year of daily bars).
- Attributes:
- q_hat_float or None
Calibrated half-width, set by
fit;Nonebefore fitting.
See also
rolling_conformal,fynance.core.protocols.SignalModel
Examples
A closed-form linear model (OLS), fit/calibrated on noiseless-ish synthetic data – the interval should be tight and cover the held-out calibration residuals by construction:
>>> import numpy as np >>> from fynance.models.conformal import ConformalWrapper >>> class LinearModel: ... ''' Closed-form ordinary least squares. ''' ... def fit(self, X, y): ... self.coef_ = np.linalg.lstsq(X, y, rcond=None)[0] ... return self ... def predict(self, X): ... return X @ self.coef_ >>> rng = np.random.default_rng(0) >>> T, F = 500, 2 >>> X = rng.standard_normal((T, F)) >>> w_true = np.array([1.5, -0.5]) >>> y = X @ w_true + 0.1 * rng.standard_normal(T) >>> wrapper = ConformalWrapper(LinearModel(), alpha=0.1, window=100) >>> _ = wrapper.fit(X, y) >>> wrapper.q_hat_ > 0 True >>> interval = wrapper.predict_interval(X[-5:]) >>> interval.shape (5, 2) >>> bool((interval[:, 1] > interval[:, 0]).all()) True
- fit(X, y)[source]
Fit the wrapped model and calibrate the interval half-width.
Splits
(X, y)atT - window: the wrapped model is fit on the leading slice only; the trailingwindowbars are held out and never used for fitting, only to compute calibration residuals|y - model.predict(X)|and their split-conformal quantile (q_hat_).- Parameters:
- Xarray-like
Feature matrix, shape
(T, N), time-ordered.- yarray-like
Target, shape
(T,)or(T, 1), aligned withX.
- Returns:
- ConformalWrapper
self, to allow chaining (theSignalModelcontract).
- Raises:
- ValueError
If
windowis not strictly less than the number of observations inX/y(there would be no leading slice left to fit the wrapped model on).
- predict(X)[source]
Point predictions of the wrapped model.
- Parameters:
- Xarray-like
Feature matrix, shape
(T, N).
- Returns:
- numpy.ndarray
Point predictions, shape
(T,)(theSignalModelcontract).
- predict_interval(X)[source]
Constant-width prediction interval around the point prediction.
- Parameters:
- Xarray-like
Feature matrix, shape
(T, N).
- Returns:
- numpy.ndarray
Shape
(T, 2); column 0 is the lower bound (predict(X) - q_hat_), column 1 the upper bound (predict(X) + q_hat_). The width2 * q_hat_is the same for every row – see the module docstring’s note on the constant-width limitation under heteroskedasticity.
- Raises:
- RuntimeError
If called before
fit.