| """Load market features from qlib.""" |
|
|
| from __future__ import annotations |
|
|
| from typing import Iterable |
|
|
| import pandas as pd |
| from qlib.data import D |
|
|
|
|
| QLIB_TO_GP_FIELD = { |
| "$open": "开盘价", |
| "$close": "收盘价", |
| "$high": "最高价", |
| "$low": "最低价", |
| "$volume": "成交量", |
| "$vwap": "vwap", |
| "$amount": "成交额", |
| } |
|
|
|
|
| def load_instruments(market: str = "csi300") -> dict: |
| return D.instruments(market) |
|
|
|
|
| def load_market_features( |
| instruments, |
| fields: Iterable[str], |
| start_time: str, |
| end_time: str, |
| freq: str = "day", |
| rename_for_gp: bool = True, |
| ) -> pd.DataFrame: |
| """ |
| Load OHLCV features via qlib D.features and optionally rename columns |
| to match the GP factor engine's Chinese field names. |
| """ |
| df = D.features( |
| instruments, |
| list(fields), |
| start_time=start_time, |
| end_time=end_time, |
| freq=freq, |
| ) |
| df = df.sort_index() |
| if rename_for_gp: |
| rename_map = {k: v for k, v in QLIB_TO_GP_FIELD.items() if k in df.columns} |
| df = df.rename(columns=rename_map) |
| return df |
|
|
|
|
| def pivot_to_symbol_time(df: pd.DataFrame, field: str) -> pd.DataFrame: |
| """Pivot multi-index (instrument, datetime) frame to symbols x time.""" |
| if field not in df.columns: |
| raise KeyError(f"Field {field} not in dataframe columns: {df.columns.tolist()}") |
| series = df[field] |
| if not isinstance(series.index, pd.MultiIndex): |
| raise ValueError("Expected MultiIndex with instrument and datetime levels") |
| return series.unstack(level="datetime") |
|
|