数据工程基础:金融数据的特点、Qlib数据目录结构、本地数据初始化、数据更新与维护
做量化交易这些年,我最大的感触就是:数据才是真正的护城河。策略模型再花哨,数据源出了问题,一切都是白搭。今天咱们就来聊聊Qlib的数据工程基础,这部分内容虽然看起来有点枯燥,但绝对是后续所有工作的根基。
金融数据的特点:跟普通数据不太一样
金融数据这东西,说白了就是「时间序列」的集合。但它有几个特别让人头疼的特点,我刚开始做量化时没少在这上面栽跟头。
- 非平稳性:股票价格今天涨明天跌,统计规律随时在变。你想想看,去年的波动率模型放到今年可能完全失效。
- 噪声极大:金融数据里充斥着各种随机波动。我曾经试过用高频数据做预测,结果发现大部分信号都是市场噪音。
- 时间依赖性强:今天的价格跟昨天、前天都有关系。不能像处理图片数据那样随便打乱顺序。
- 幸存者偏差:这是个大坑。如果你只拿现在还在交易的股票做回测,那些退市的股票带来的亏损就被忽略了。我早期的一个策略就是吃了这个亏,回测曲线漂亮得很,实盘直接崩了。
- 数据对齐问题:不同股票的交易时间、停牌复牌、除权除息,这些都会导致数据错位。嗯,这里要特别注意。
核心要点:金融数据工程的核心任务,就是把这些「脏乱差」的原始数据,清洗成干净、对齐、可用的因子矩阵。
Qlib数据目录结构:一张图看懂
Qlib的数据组织方式非常清晰。我个人习惯把它理解成一个「三层仓库」:最外层是市场,中间层是股票,最内层是字段。
下面这张图是我自己画的,帮你快速建立整体认知:
你看,每个市场目录下都有四个子目录:
- calendars:交易日历。A股有250个交易日左右,美股大概252个。这个文件告诉Qlib哪天开盘、哪天休市。
- features:因子数据。这是最核心的部分,每个字段一个二进制文件。比如 open.bin 存的是所有股票的开盘价。
- instruments:股票列表。哪些股票属于这个市场,什么时候上市、什么时候退市。
- labels:标签数据。就是你要预测的目标,比如未来5天的收益率。
小技巧:Qlib使用二进制格式存储数据,而不是CSV。这样做的好处是读取速度快、占用空间小。我实测过,同样的数据量,bin格式比CSV快10倍以上。
本地数据初始化:从零开始
好,理论说完了,咱们动手。初始化数据其实就两步:下载原始数据,然后转换成Qlib格式。
先安装Qlib:
pip install qlib
然后下载数据。Qlib官方提供了几个市场的示例数据,咱们用A股沪深300的:
# 下载并初始化数据
python -m qlib.run.get_data
--target_dir ~/.qlib/qlib_data/csi300
--region cn
这条命令会做三件事:
- 从网络下载原始CSV数据
- 清洗并检查数据完整性
- 转换成Qlib的bin格式
如果你有自己的数据源,也可以用Qlib提供的工具手动转换。我记得有一次客户给的数据格式特别乱,我写了个脚本先转成标准CSV,再用Qlib的 dump_bin 工具导入:
from qlib.data import D
from qlib.data.dataset import DatasetH
from qlib.contrib.data.handler import Alpha158
# 自定义数据导入
D.dump_bin(
symbol_to_path="my_stock_list.txt",
dirname="my_raw_data",
freq="day",
dump_interval=1
)
注意:数据初始化时,一定要检查交易日历是否完整。我曾经因为日历文件缺失了某个月的交易日,导致回测结果完全偏离实际。建议初始化后先跑一个简单的数据查询验证一下。
数据更新与维护:保持新鲜度
量化策略需要持续运行,数据也得不断更新。Qlib提供了增量更新的机制,不用每次都全量下载。
更新数据的命令很简单:
# 增量更新数据
python -m qlib.run.get_data
--target_dir ~/.qlib/qlib_data/csi300
--region cn
--interval 1d
这个命令会检查本地数据的最新日期,然后只下载缺失的部分。我一般把它放在crontab里,每天收盘后自动执行:
# 每天下午5点更新数据
0 17 * * 1-5 python -m qlib.run.get_data --target_dir ~/.qlib/qlib_data/csi300 --region cn --interval 1d
数据维护方面,有几个坑需要避开:
- 除权除息:股票分红送股后,价格会跳空。Qlib默认使用后复权数据,但如果你用的是前复权,记得在配置里指定。
- 停牌处理:停牌期间的数据是缺失的。我习惯用前向填充,或者干脆把停牌日的样本剔除掉。
- 数据一致性:不同数据源对同一只股票的价格可能不一样。我建议始终使用同一个数据源,不要混用。
避坑指南:我曾经在生产环境遇到过一个问题——数据更新脚本跑着跑着突然报错,原因是某只股票退市了,但股票列表没更新。从那以后,我每次更新数据前都会先同步最新的股票列表。
最后说一句,数据工程是个细致活。你花在数据清洗上的每一分钟,都会在后续的因子研究和模型训练中得到回报。别嫌麻烦,打好基础才能走得更远。