量化轮动系统建设手记(一):先把数据底座打牢
过去几周我在自建服务器上推进一件事:搭一套能自学习、带回测闭环的「板块轮动 + 选股」量化工具。不夸张地说,模型只是冰山一角,真正占掉时间的是看不见的水下部分——数据。这篇手记记录第一阶段的全部过程:怎么盘点家底、怎么设计数据分层、怎么补全 20 年历史,以及一次差点被忽略的「复权口径」核验。
一、先盘点家底:三套数据库
系统要用的数据散在三套自建库里,动手前先做了一次全量盘点(全部实测核验,不看文档看数据):
| 数据库 | 内容 | 规模与覆盖 |
|---|---|---|
| 行情主库 | 个股日线 / 财务三表 / 估值 / 指数 / 北向 | 个股日线 1500 万+行(2005 至今,5548 只);31 个申万一级行业指数 26 年 |
| 新闻事件库 | 财经新闻流、实体抽取、每日简报 | 多源实时采集,30 分钟级更新 |
| 宏观市场库 | 汇率 / 油价 / 贵金属 / 航运 / 央行利率 / 宏观指标 | 10 张表,部分回溯到 1990 年代 |
结论:价格与行业数据底子很硬(可以立刻开始回测),但有三处缺口——行业估值几乎没有历史、个股估值只有 2019 年之后、新闻历史几乎为零。这三处决定了后续补数据的优先级。
二、设计原则:只读 + 派生分离
给系统定了一条硬规矩:原始库永远只读,一切派生数据(特征、预测、回测、推荐记录)写进独立的「派生库」。这样做的好处:
- 采集程序与建模程序物理隔离,互不干扰,出问题可回滚;
- 派生数据可以随时删掉重建(幂等设计),大胆试错;
- 「数据只进不出」:所有处理在内网完成,外部数据源只做单向拉取。
三、全历史回填:一次 1500 万行的耐力赛
第一个硬活是个股技术指标全历史回填:5548 只股票 × 2005 年至今 × 20 多项指标(均线、MACD、RSI、KDJ、BOLL、ATR、量比、换手率等),合计约 1500 万行。
工程上做了三件事:分块处理(每 300 只一批,内存安全)、断点续跑(进度水位存库,中断可从任意位置续)、幂等写入(重跑不产生重复数据)。最终 77 分钟跑完,写入速率约 3300 行/秒,抽样复核与原数据完全一致。
第二个是估值补齐:行业估值从官方数据源回填到 2005 年(12 万行,含市盈率/市净率/股息率/换手率);个股估值的 2005-2018 年段用公开证券数据接口逐只补齐(690 万行 / 3338 只,2019 年前已上市股票覆盖率 100%)。这类低频接口通常严格限频(有的接口每小时只能调一次),所以脚本按「慢速 + 断点续跑」设计,跑了一整晚。「耐心」是数据工程的第一美德。
四、差点被忽略的一课:复权口径核验
行情数据用「前复权」还是「不复权」,直接决定回测收益率的对错。这件事没有文档可查,我们用两种独立方法做了交叉核验:
- 成交均价法:「成交额 ÷ 成交量」是当日的实际成交均价(不受复权处理影响)。把它与存储的收盘价比值画成时间序列——如果数据是前复权,比值应从近期 1.00 平滑增长到早年数倍(对应累计分红送转)。实测样本全部吻合:某白酒龙头 2005 年比值 5.5 倍、某消费电子公司 2010 年 34 倍,与各自的分红送转史精确对应。
- 市值交叉法:用独立来源的总市值 ÷ 总股本反推实际价,与收盘价对比,近期完全一致。
结论:数据是干净的前复权口径,收益率可以直接用。过程中还顺带发现了一处数据质量问题(历史估值表的市值字段存在单位混用)——只有真的去核验,才会发现这类藏在角落里的问题。
五、让数据自己盯自己:每日质量巡检
最后给系统配了一个「值班员」:每天自动检查 11 项关键数据的更新状态(最新日期、滞后天数),异常自动记录。上线第一周就抓到一个真实问题:北向资金数据因采集频率设置不当出现缺口——值班员发现、自动修复、次日复核通过。
阶段小结
- 全部数据资产:行情 2005-2026、行业估值 2005-2026、个股估值 2005-2026、技术指标全历史、新闻/事件实时;
- 工程纪律沉淀:只读分离、幂等写入、断点续跑、质量巡检、复权核验;
- 下一步:新闻与事件数据的建设(下一篇),然后是因子验证与回测。
免责声明:本系列为个人技术研究记录,所述系统为个人研究工具,历史数据与回测结果不代表未来表现,不构成任何投资建议。