"""Event window construction for event studies.""" from __future__ import annotations import numpy as np import pandas as pd def create_event_windows( prices: pd.DataFrame, event_dates: list, window: tuple[int, int] = (-5, 5), label: str = "event", ) -> pd.DataFrame: """Create event windows around each event date. Returns DataFrame with columns: [event_date, relative_day, market, price, return, abnormal_return] """ rows = [] idx = prices.index event_dates_ts = [pd.Timestamp(d) for d in event_dates] for col in prices.columns: series = prices[col].dropna() if series.empty: continue returns = series.diff() mean_return = returns.mean() for event_dt in event_dates_ts: loc = idx.get_indexer([event_dt], method="nearest")[0] if loc < 0 or loc >= len(idx): continue for rel_day in range(window[0], window[1] + 1): abs_idx = loc + rel_day if 0 <= abs_idx < len(idx): date = idx[abs_idx] price = series.iloc[abs_idx] if abs_idx < len(series) else np.nan ret = returns.iloc[abs_idx] if abs_idx < len(returns) else np.nan ar = ret - mean_return if not np.isnan(ret) else np.nan rows.append({ "event_date": event_dt, "relative_day": rel_day, "market": col, "price": price, "return": ret, "abnormal_return": ar, }) return pd.DataFrame(rows) def compute_car(event_windows: pd.DataFrame) -> pd.DataFrame: """Compute cumulative abnormal returns from event windows.""" result = [] for (event_date, market), group in event_windows.groupby(["event_date", "market"]): group = group.sort_values("relative_day") group = group.copy() group["CAR"] = group["abnormal_return"].cumsum() result.append(group) if result: return pd.concat(result, ignore_index=True) return pd.DataFrame()