📐 题目4: 数据结构设计 —— OHLCV、DataFrame操作、时间序列索引、多标的DataFrame。掌握这些,回测框架就稳了一半。
| 字段 | 含义 | 类型 | 避坑注意 |
|---|---|---|---|
| Open | 开盘价 | float64 | 注意复权调整,前复权/后复权一致性 |
| High | 最高价 | float64 | 不可低于Close或Open (数据源异常) |
| Low | 最低价 | float64 | 不可高于Close或Open |
| Close | 收盘价 | float64 | 用于计算收益率,注意缺失值填充 |
| Volume | 成交量 | int64 / float | 单位统一(股/手),除权后调整 |
pandas 的 Float64 可保留空值,避免精度陷阱df.set_index('datetime', inplace=True) 或 pd.DatetimeIndexresample('1D').agg(...) 或 asfreq 避免非交易时段干扰rolling(window=20).mean() 注意 min_periodsffill() 或插值,但不可引入未来信息tz_localize 与 tz_convert 混淆🧪 常用操作速查
df['return'] = df['Close'].pct_change()
df['ma20'] = df['Close'].rolling(20).mean()
df_week = df.resample('W').agg({
'Open': 'first', 'High': 'max',
'Low': 'min', 'Close': 'last',
'Volume': 'sum'
})
| 方法 | 结构 | 适用场景 |
|---|---|---|
| MultiIndex 行 | (datetime, asset) | 长表,适合 groupby 操作 |
| MultiIndex 列 | asset1, asset2… 每列OHLCV | 宽表,方便截面分析 |
| 字典/panel | {asset: DataFrame} | 旧版pandas,不推荐 |
groupby('asset')reindex 统一索引pd.MultiIndex.from_productimport pandas as pd import numpy as np # 模拟多标的OHLCV数据 (长表MultiIndex) dates = pd.date_range('2023-01-01', periods=5, freq='D') assets = ['AAPL', 'GOOGL', 'MSFT'] index = pd.MultiIndex.from_product([dates, assets], names=['datetime', 'asset']) data = np.random.uniform(100, 200, (len(index), 5)) df = pd.DataFrame(data, index=index, columns=['Open','High','Low','Close','Volume']) df['Volume'] = (df['Volume'] * 1000).astype(int) # 操作:获取 AAPL 的 Close 序列 aapl_close = df.loc[(slice(None), 'AAPL'), 'Close'] print(aapl_close) # 避坑:统一索引 (不同标的交易日可能不同) df_wide = df.unstack('asset') # 转为宽表 df_wide = df_wide.reindex(pd.date_range('2023-01-01','2023-01-07', freq='D')) # 对齐
⚠️ 避坑重点: 多标的DataFrame 务必注意 sort_index(),否则切片可能失效;使用 stack/unstack 时注意层级顺序。