from __future__ import annotations import numpy as np from .types import DensityEstimate, OptionSnapshot def compute_features( snapshot: OptionSnapshot, density: DensityEstimate ) -> dict[str, float]: k = density.strikes.to_numpy(dtype=float) rho = density.density.to_numpy(dtype=float) spot = float(snapshot.spot) mean_k = float(np.trapezoid(k * rho, k)) var_k = float(np.trapezoid((k - mean_k) ** 2 * rho, k)) std_k = float(np.sqrt(max(var_k, 1e-12))) skew = float(np.trapezoid(((k - mean_k) / std_k) ** 3 * rho, k)) tail_mass_left = ( float(np.trapezoid(rho[k < 0.9 * spot], k[k < 0.9 * spot])) if np.any(k < 0.9 * spot) else 0.0 ) return { "spot": spot, "mean_terminal": mean_k, "std_terminal": std_k, "skew_proxy": skew, "left_tail_mass": tail_mass_left, }