| """Basic cleaning utilities for qlib feature frames.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| import pandas as pd | |
| def clean_feature_frame(df: pd.DataFrame, clip_return: float = 0.30) -> pd.DataFrame: | |
| """Replace inf, clip extreme returns if present, forward-fill within instrument.""" | |
| out = df.replace([np.inf, -np.inf], np.nan).copy() | |
| if isinstance(out.index, pd.MultiIndex): | |
| out = out.groupby(level="instrument", group_keys=False).apply(lambda x: x.ffill()) | |
| return out | |
| def filter_liquidity(df: pd.DataFrame, min_volume: float = 0.0) -> pd.DataFrame: | |
| """Drop rows with zero/NaN volume when volume column exists.""" | |
| volume_cols = [c for c in df.columns if c in ("$volume", "成交量", "volume")] | |
| if not volume_cols: | |
| return df | |
| vol = df[volume_cols[0]] | |
| mask = vol.notna() & (vol > min_volume) | |
| return df.loc[mask] | |