HAR-RV Forecast (rolling OLS)
Intuição
O HAR-RV clássico usa regressão (HAR) para prever volatilidade futura a partir de múltiplas escalas da volatilidade realizada.
Nesta feature, fazemos uma regressão rolling para produzir, em cada tempo t, uma previsão de log(RV_{t+horizon}) usando como regressoras:
log(RV_t)
mean(log(RV)) em janela semanal
mean(log(RV)) em janela mensal
Isso evita look-ahead: os coeficientes em t são ajustados apenas com dados até t-horizon.
Definição
Para cada t, ajustamos uma OLS em janela estimation_window e calculamos:
y_{t+h} = beta0 + beta1*x_d(t) + beta2*x_w(t) + beta3*x_m(t)
onde x_d, x_w, x_m são as features do HAR sobre log(RV).
Uso
from quantmaster.features.volatility import har_rv_forecast
df["har_rv_forecast_1_100"] = har_rv_forecast(df, horizon=1, estimation_window=100)
API
Source code in src/quantmaster/features/volatility.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 | def har_rv_forecast(
data: pd.DataFrame | pd.Series,
*,
price_col: str = "close",
horizon: int = 1,
estimation_window: int = 100,
weekly_window: int = 5,
monthly_window: int = 22,
log_rv: bool = True,
) -> pd.Series:
horizon = validate_positive_int(horizon, name="horizon")
estimation_window = validate_positive_int(estimation_window, name="estimation_window")
weekly_window = validate_positive_int(weekly_window, name="weekly_window")
monthly_window = validate_positive_int(monthly_window, name="monthly_window")
rv = realized_variance(data, price_col=price_col)
rv = rv.astype(float)
if log_rv:
base = np.log(rv.where(rv > 0))
else:
base = rv
x_d = base
x_w = base.rolling(weekly_window).mean()
x_m = base.rolling(monthly_window).mean()
y = base.shift(-horizon)
x = np.column_stack(
[
x_d.to_numpy(dtype=float),
x_w.to_numpy(dtype=float),
x_m.to_numpy(dtype=float),
]
)
y_arr = y.to_numpy(dtype=float)
n = len(rv)
out_arr = np.full(n, np.nan, dtype=float)
for i in range(n):
train_end = i - horizon
if train_end < 0:
continue
train_start = train_end - estimation_window + 1
if train_start < 0:
continue
x_win = x[train_start : train_end + 1]
y_win = y_arr[train_start : train_end + 1]
mask = np.isfinite(y_win)
mask &= np.isfinite(x_win).all(axis=1)
if mask.sum() < 4:
continue
a = np.column_stack([np.ones(mask.sum(), dtype=float), x_win[mask]])
beta, *_ = np.linalg.lstsq(a, y_win[mask], rcond=None)
x_i = x[i]
if not np.isfinite(x_i).all():
continue
out_arr[i] = float(beta[0] + np.dot(beta[1:], x_i))
out = pd.Series(out_arr, index=rv.index)
out.name = f"har_rv_forecast_{horizon}_{estimation_window}"
return out
|