"""Feature engineering for prediction market analysis.""" from __future__ import annotations import numpy as np import pandas as pd def compute_log_returns(prices: pd.Series) -> pd.Series: return np.log(prices / prices.shift(1)) def compute_realized_volatility(returns: pd.Series, window: int = 5) -> pd.Series: return (returns ** 2).rolling(window).sum().apply(np.sqrt) def compute_probability_changes(probs: pd.DataFrame) -> pd.DataFrame: return probs.diff() def compute_roll_spread(prices: pd.Series, window: int = 20) -> pd.Series: """Roll (1984) bid-ask spread estimator.""" dp = prices.diff() def _roll_cov(x: np.ndarray) -> float: if len(x) < 3: return np.nan return np.cov(x[:-1], x[1:])[0, 1] cov = dp.rolling(window).apply(_roll_cov, raw=True) return 2 * np.sqrt(np.maximum(-cov, 0)) def compute_amihud_illiquidity(returns: pd.Series, volume: pd.Series) -> pd.Series: return (returns.abs() / volume).replace([np.inf, -np.inf], np.nan) def compute_abnormal_volume(volume: pd.Series, window: int = 20) -> pd.Series: return volume / volume.rolling(window).mean() def engineer_features(prices_df: pd.DataFrame) -> pd.DataFrame: """Compute features for a panel of prices.""" features = pd.DataFrame(index=prices_df.index) for col in prices_df.columns: s = prices_df[col] features[f"{col}_return"] = s.diff() features[f"{col}_log_return"] = compute_log_returns(s) features[f"{col}_rv5"] = compute_realized_volatility(s.diff(), 5) features[f"{col}_roll_spread"] = compute_roll_spread(s) return features