Download preprocessing/splits.py from oyi77/openmedallion-fints: direct link, hf CLI and curl.
- Browser
- Download file 3.54 kB
-
https://huggingface.co/oyi77/openmedallion-fints/resolve/main/preprocessing/splits.py
- Command line
-
hf download hf://oyi77/openmedallion-fints/preprocessing/splits.py
-
curl -L -o splits.py https://huggingface.co/oyi77/openmedallion-fints/resolve/main/preprocessing/splits.py
3.54 kB
| """ | |
| Temporal walk-forward splitting for time-series validation. | |
| No random shuffle — strict chronological order only. | |
| """ | |
| import pandas as pd | |
| from typing import List, Tuple | |
| from datetime import datetime | |
| def walk_forward_split( | |
| df: pd.DataFrame, | |
| train_size: int, | |
| test_size: int, | |
| step: int = None | |
| ) -> List[Tuple[pd.DataFrame, pd.DataFrame]]: | |
| """ | |
| Generate walk-forward train/test splits. | |
| Args: | |
| df: DataFrame with datetime index (sorted chronologically) | |
| train_size: Number of rows for training window | |
| test_size: Number of rows for test window | |
| step: Step size between splits (default: test_size) | |
| Returns: | |
| List of (train_df, test_df) tuples | |
| Example: | |
| If train_size=252, test_size=63 (1 year train, 1 quarter test): | |
| Split 1: rows 0-251 train, 252-314 test | |
| Split 2: rows 63-314 train, 315-377 test | |
| ... | |
| """ | |
| if not isinstance(df.index, pd.DatetimeIndex): | |
| raise ValueError("DataFrame must have DatetimeIndex") | |
| if not df.index.is_monotonic_increasing: | |
| raise ValueError("Index must be sorted chronologically") | |
| if step is None: | |
| step = test_size | |
| splits = [] | |
| total_rows = len(df) | |
| start = 0 | |
| while start + train_size + test_size <= total_rows: | |
| train_end = start + train_size | |
| test_end = train_end + test_size | |
| train_df = df.iloc[start:train_end] | |
| test_df = df.iloc[train_end:test_end] | |
| splits.append((train_df, test_df)) | |
| start += step | |
| return splits | |
| def expanding_window_split( | |
| df: pd.DataFrame, | |
| initial_train_size: int, | |
| test_size: int, | |
| step: int = None | |
| ) -> List[Tuple[pd.DataFrame, pd.DataFrame]]: | |
| """ | |
| Generate expanding window splits (train set grows over time). | |
| Args: | |
| df: DataFrame with datetime index (sorted chronologically) | |
| initial_train_size: Initial training window size | |
| test_size: Test window size | |
| step: Step size between splits (default: test_size) | |
| Returns: | |
| List of (train_df, test_df) tuples | |
| """ | |
| if not isinstance(df.index, pd.DatetimeIndex): | |
| raise ValueError("DataFrame must have DatetimeIndex") | |
| if not df.index.is_monotonic_increasing: | |
| raise ValueError("Index must be sorted chronologically") | |
| if step is None: | |
| step = test_size | |
| splits = [] | |
| total_rows = len(df) | |
| train_end = initial_train_size | |
| while train_end + test_size <= total_rows: | |
| test_end = train_end + test_size | |
| train_df = df.iloc[:train_end] | |
| test_df = df.iloc[train_end:test_end] | |
| splits.append((train_df, test_df)) | |
| train_end += step | |
| return splits | |
| def single_train_test_split( | |
| df: pd.DataFrame, | |
| train_ratio: float = 0.8 | |
| ) -> Tuple[pd.DataFrame, pd.DataFrame]: | |
| """ | |
| Simple train/test split maintaining temporal order. | |
| Args: | |
| df: DataFrame with datetime index (sorted chronologically) | |
| train_ratio: Fraction of data for training | |
| Returns: | |
| (train_df, test_df) | |
| """ | |
| if not isinstance(df.index, pd.DatetimeIndex): | |
| raise ValueError("DataFrame must have DatetimeIndex") | |
| if not df.index.is_monotonic_increasing: | |
| raise ValueError("Index must be sorted chronologically") | |
| split_idx = int(len(df) * train_ratio) | |
| return df.iloc[:split_idx], df.iloc[split_idx:] | |