Download preprocessing/features.py from oyi77/openmedallion-fints: direct link, hf CLI and curl.
- Browser
- Download file 3.74 kB
-
https://huggingface.co/oyi77/openmedallion-fints/resolve/main/preprocessing/features.py
- Command line
-
hf download hf://oyi77/openmedallion-fints/preprocessing/features.py
-
curl -L -o features.py https://huggingface.co/oyi77/openmedallion-fints/resolve/main/preprocessing/features.py
3.74 kB
| """ | |
| Feature engineering for time-series forecasting. | |
| Technical indicators + lag features. | |
| """ | |
| import pandas as pd | |
| import numpy as np | |
| def log_returns(df: pd.DataFrame, col: str = 'close') -> pd.Series: | |
| """Log returns: log(price_t / price_{t-1})""" | |
| return np.log(df[col] / df[col].shift(1)) | |
| def rolling_volatility(df: pd.DataFrame, window: int = 20, col: str = 'close') -> pd.Series: | |
| """Rolling standard deviation of log returns""" | |
| returns = log_returns(df, col) | |
| return returns.rolling(window).std() | |
| def rsi(df: pd.DataFrame, window: int = 14, col: str = 'close') -> pd.Series: | |
| """Relative Strength Index""" | |
| delta = df[col].diff() | |
| gain = (delta.where(delta > 0, 0)).rolling(window).mean() | |
| loss = (-delta.where(delta < 0, 0)).rolling(window).mean() | |
| rs = gain / loss | |
| return 100 - (100 / (1 + rs)) | |
| def macd(df: pd.DataFrame, fast: int = 12, slow: int = 26, signal: int = 9, col: str = 'close') -> pd.DataFrame: | |
| """MACD indicator: returns DataFrame with macd, signal, histogram""" | |
| ema_fast = df[col].ewm(span=fast, adjust=False).mean() | |
| ema_slow = df[col].ewm(span=slow, adjust=False).mean() | |
| macd_line = ema_fast - ema_slow | |
| signal_line = macd_line.ewm(span=signal, adjust=False).mean() | |
| histogram = macd_line - signal_line | |
| return pd.DataFrame({ | |
| 'macd': macd_line, | |
| 'macd_signal': signal_line, | |
| 'macd_hist': histogram | |
| }) | |
| def volume_zscore(df: pd.DataFrame, window: int = 20) -> pd.Series: | |
| """Volume z-score relative to rolling window""" | |
| if 'volume' not in df.columns: | |
| return pd.Series(0, index=df.index) | |
| mean = df['volume'].rolling(window).mean() | |
| std = df['volume'].rolling(window).std() | |
| return (df['volume'] - mean) / (std + 1e-8) | |
| def lag_returns(df: pd.DataFrame, lags: list[int], col: str = 'close') -> pd.DataFrame: | |
| """Lagged returns for multiple periods""" | |
| returns = log_returns(df, col) | |
| return pd.DataFrame({ | |
| f'return_lag_{lag}': returns.shift(lag) | |
| for lag in lags | |
| }) | |
| def build_features(df: pd.DataFrame) -> pd.DataFrame: | |
| """ | |
| Build complete feature set from OHLCV data. | |
| Returns: | |
| DataFrame with all engineered features | |
| """ | |
| features = pd.DataFrame(index=df.index) | |
| # Price-based features | |
| features['log_return'] = log_returns(df) | |
| features['volatility_20'] = rolling_volatility(df, window=20) | |
| features['rsi_14'] = rsi(df, window=14) | |
| # MACD | |
| macd_df = macd(df) | |
| features = pd.concat([features, macd_df], axis=1) | |
| # Volume | |
| features['volume_zscore'] = volume_zscore(df) | |
| # Lagged returns | |
| lag_df = lag_returns(df, lags=[1, 2, 3, 5, 10]) | |
| features = pd.concat([features, lag_df], axis=1) | |
| # Price momentum | |
| features['momentum_5'] = df['close'].pct_change(5) | |
| features['momentum_20'] = df['close'].pct_change(20) | |
| return features | |
| def make_target(df: pd.DataFrame, horizon: int = 1, col: str = 'close') -> pd.Series: | |
| """ | |
| Create regression target: future log return. | |
| Args: | |
| df: OHLCV dataframe | |
| horizon: Prediction horizon in periods | |
| col: Column to predict | |
| Returns: | |
| Series of future log returns | |
| """ | |
| return np.log(df[col].shift(-horizon) / df[col]) | |
| def make_direction_target(df: pd.DataFrame, horizon: int = 1, col: str = 'close') -> pd.Series: | |
| """ | |
| Create classification target: future direction (up=1, down=0). | |
| Args: | |
| df: OHLCV dataframe | |
| horizon: Prediction horizon in periods | |
| col: Column to predict | |
| Returns: | |
| Series of binary direction labels | |
| """ | |
| future_return = make_target(df, horizon, col) | |
| return (future_return > 0).astype(int) | |