数据篇:期货数据获取与预处理
做量化交易,数据就是你的弹药库。没有数据,再好的策略也是空中楼阁。这一章,我带你搞定期货数据的获取、清洗和存储。这些都是我这些年踩坑踩出来的经验,希望能帮你少走弯路。
一、数据获取:三大主流工具
期货数据从哪里来?市面上工具很多,但我个人最常用的就三个:Tushare、AKShare 和 Wind。它们各有千秋,我分别说说。
1. Tushare:老牌稳定,适合历史研究
Tushare 是我最早接触的金融数据接口。它数据质量高,覆盖全面,但需要注册获取 token。说实话,它的文档写得有点绕,但用熟了就好。
import tushare as ts
# 设置 token(需要去官网注册)
ts.set_token('你的token')
pro = ts.pro_api()
# 获取期货日线数据
df = pro.fut_daily(
ts_code='RB2401.SHF', # 螺纹钢主力合约
start_date='20230101',
end_date='20231231',
fields='ts_code,trade_date,open,high,low,close,vol,amount'
)
print(df.head())
2. AKShare:开源免费,实时数据强
AKShare 是后来崛起的开源库,完全免费。它的实时数据接口特别多,适合做日内策略。不过,它的数据源来自各大财经网站,偶尔会有缺失或延迟。
import akshare as ak
# 获取期货实时行情
futures_zh_min = ak.futures_zh_minute_sina(
symbol='RB2401',
period='1' # 1分钟线
)
print(futures_zh_min.tail())
3. Wind:机构首选,但贵
Wind 是机构标配,数据最全最准。但一年几万块的费用,个人用户基本用不起。如果你在机构工作,直接用 Wind 就好,省心。
from WindPy import w
w.start()
# 获取期货数据
data = w.wsd(
"RB2401.SHF",
"open,high,low,close,volume",
"2023-01-01",
"2023-12-31"
)
print(data.Data)
二、数据清洗与预处理
数据拿到手,别急着用。我敢说,90% 的原始数据都有问题。缺失值、异常值、复权问题……不处理干净,策略回测就是自欺欺人。
1. 处理缺失值
期货数据经常有缺失,比如节假日、涨停跌停。我的处理原则是:
- 连续缺失不超过 3 个:用前向填充(ffill)
- 连续缺失超过 3 个:直接删除该行
- 开盘价缺失:用前一日收盘价替代
import pandas as pd
# 前向填充缺失值
df.fillna(method='ffill', inplace=True)
# 删除连续缺失超过3天的数据
df = df[df['close'].notna()]
2. 处理异常值
期货市场偶尔会出现极端行情,比如瞬间涨停或跌停。这些数据是真实的,但会干扰策略。我的做法是:
- 用 3 倍标准差法识别异常值
- 对于识别出的异常值,用前一日数据替代
- 保留涨跌停数据,但标记出来
# 3倍标准差法识别异常
mean = df['close'].mean()
std = df['close'].std()
df['is_outlier'] = (abs(df['close'] - mean) > 3 * std)
# 替代异常值
df.loc[df['is_outlier'], 'close'] = df['close'].shift(1)
3. 复权处理
期货有换月问题,不同合约的价格不连续。你需要做复权处理,把历史数据统一到当前合约上。我一般用后复权,简单实用。
# 简单后复权示例
def adjust_price(df):
# 找到换月点
roll_date = df[df['contract'] != df['contract'].shift(1)].index
for date in roll_date:
ratio = df.loc[date, 'close'] / df.loc[date-1, 'close']
df.loc[:date-1, 'close'] *= ratio
return df
三、数据存储:选对格式很重要
数据清洗完了,存哪里?我试过 CSV、HDF5 和数据库,各有适用场景。
1. CSV:简单但慢
CSV 是最简单的格式,适合小数据量。但如果你有几十个品种、几年数据,CSV 的读写速度会让你崩溃。
# 保存为 CSV
df.to_csv('futures_data.csv', index=False)
# 读取 CSV
df = pd.read_csv('futures_data.csv', parse_dates=['trade_date'])
2. HDF5:速度快,适合大数据
HDF5 是我最推荐的格式。它读写速度快,支持压缩,还能按索引查询。我个人的历史数据全部用 HDF5 存储。
# 保存为 HDF5
df.to_hdf('futures_data.h5', key='rb2401', mode='w')
# 读取 HDF5
df = pd.read_hdf('futures_data.h5', key='rb2401')
3. 数据库:适合团队协作
如果你在团队里做量化,或者数据量特别大(TB 级别),建议用数据库。MySQL 或 PostgreSQL 都行。我个人偏好 PostgreSQL,因为它支持时间序列扩展。
from sqlalchemy import create_engine
# 连接数据库
engine = create_engine('postgresql://user:password@localhost:5432/futures')
# 写入数据库
df.to_sql('futures_daily', engine, if_exists='replace', index=False)
# 从数据库读取
df = pd.read_sql('SELECT * FROM futures_daily WHERE trade_date > "2023-01-01"', engine)
四、知识体系总览
下面这张图,是我梳理的本章知识结构。你可以把它当作一个检查清单,看看自己有没有遗漏。
五、避坑指南
最后,分享几个我亲身踩过的坑:
- 不要相信任何数据源的 100% 准确率。我曾在 Tushare 和 Wind 之间发现 0.5% 的价差,查了半天才发现是复权方式不同。
- 数据清洗一定要写日志。我习惯记录每次清洗删了多少行、填充了多少值。这样出了问题能追溯。
- 存储格式不要频繁切换。我见过有人今天用 CSV,明天用 HDF5,后天又换数据库,结果数据对不上。选定一种格式,坚持用下去。
数据是量化交易的基石。这一章的内容,说白了就是帮你打好地基。地基稳了,后面的策略才能盖得高。