0%

新手如何搭一个完整的量化分析系统——五层骨架与踩坑复盘

我业余在做一个 A 股量化分析系统:自动拉数据、算因子、做因果推断、生成个股分析报告。它从最初十几个互相调用的脚本,长成了一个有数据层、因子层、模型层、决策层、复盘层的系统。这篇是写给”想做量化系统、但还停在写脚本阶段”的新手的复盘——不讲怎么调参赚钱,只讲怎么把系统的骨架搭对。 因为我越做越确信:量化里真正难的不是策略,是工程。

先有骨架:一个完整的量化系统分五层

新手最容易陷入的误区,是一上来就钻进”用什么指标、什么模型能赚钱”。但一个能持续迭代的量化系统,赚钱的策略只是最上面薄薄一层,底下要有四层地基撑着。完整骨架长这样:

1
2
3
4
5
6
7
8
9
10
11
┌─────────────────────────────────────────────┐
│ 5. 复盘层 回测 / 模拟盘 / IC评估 / 跨日对比 │ ← 验证前四层有没有用
├─────────────────────────────────────────────┤
│ 4. 决策层 多信号融合 → 评级 / 报告 / 操作清单 │ ← 人在这里介入
├─────────────────────────────────────────────┤
│ 3. 模型层 因子合成 / 因果推断 / 资金博弈 / 异常检测 │ ← 把数据变成判断
├─────────────────────────────────────────────┤
│ 2. 因子层 技术 / 基本面 / 量价因子,计算并落库 │ ← 可复现的特征
├─────────────────────────────────────────────┤
│ 1. 数据层 行情 / 财报 / 资金面,采集 + 统一访问 │ ← 一切的地基
└─────────────────────────────────────────────┘

数据自下而上流动,每层只对相邻层负责。把这张图刻在脑子里,后面 80% 的架构决策都有了依据。下面逐层讲,每层都附上我真实踩过的坑。

第 1 层 · 数据层:地基,也是最容易偷懒的地方

数据层干三件事:采集(从外部源拉行情/财报/资金面)、落库(存进本地数据库)、统一访问(给上层提供干净的读接口)。

新手最容易在”统一访问”上偷懒——每个脚本要数据就自己 connect() 一下。我就是这么干的,结果欠下两笔债:

坑一:31 个模块各自连库,字段口径乱成一锅粥。 同一张 K 线表,有的模块记得字段叫 amt,有的写成 amount;日线 type 标准值是 '1d',某次 bug 让它存成了 '60m',下游全查空;数据库路径 "db_file" 硬编码在十几个文件里。后来我把所有”读数据”收口到一个 data_access.py,字段口径只定义一次,顺手加了个 compute_technicals() 把每次都要重算的 MA/RSI/MACD 一次算全。地基不统一,上面每盖一层都在重复试错。

坑二:外部数据源一定会在你最需要时挂掉。 我的”个股资金流”接口稳定跑了大半年后,某天整个路径被服务端拒绝——直连、走代理都是 Empty reply。依赖它的那块报告瞬间全空。这件事教会我一套”外部源生存法则”:

  • 重试要克制:原来 3 次重试 ×15 秒,挂的时候白等 45 秒;改成 1 次 ×8 秒,从”卡死”变”秒跳过”。重试是为了扛抖动,不是硬刚宕机。
  • 要有兜底源,但兜底数据的口径必须对得上。这是最隐蔽的坑:原接口是”超大单”口径,兜底源是”主力(超大+大单)”口径,同一只股票原口径显示 -70 亿、兜底口径 +0.7 亿,方向完全相反(”大单买、超大单卖”的派发)。所以兜底只补它对应的那一格,原口径拿不到就诚实标”不可用”,绝不拿另一个口径冒充。
  • 降级要能自愈:原接口恢复后自动不再走兜底。

给新手:数据层是你唯一不能省工的地方。先写一个”唯一的读数据入口”,再把每个外部源的”挂了怎么办”想清楚。这两件事越晚做越痛。

第 2 层 · 因子层:让特征”可复现 + 可追溯”

因子层把原始 K 线/财报,加工成一个个数值特征——动量、波动率、估值(PE/PB/PEG)、财务质量(F-Score)、量价(振幅/量比)等等。我的系统现在有 29 维因子。

这层新手常犯的错,是把因子算在内存里用完就扔。正确做法是:因子要落库,带上日期和计算时间戳。 原因有三:

  1. 可复现:三个月后你想知道”那天为什么给这只股 60 分”,能查到当天每个因子的值。
  2. 可批量:横截面排名(这只股的动量在全市场排第几)必须有全市场当天的因子快照才能算。
  3. 可校验:因子算错了(比如某次我把”资产负债率”的单位算错,0.5 存成了 0.005),落库后能一眼看出异常。

还有一条:新增因子时,所有相关入口要同步。我加了 6 个新因子后,忘了同步因子评估模块,导致评估时报错——因为评估那边的因子列表是另一处硬编码的。任何”因子清单”这种东西,都该有唯一来源,而不是 copy 在多个文件里。

第 3 层 · 模型层:把数据变成判断,但要留余地

这是量化系统的”大脑”,把因子加工成可决策的信号。我这层有几个互相独立的模块:因子合成评分、因果推断(R-Learner)、资金博弈(6 类资金角色)、财务异常检测、市场状态识别。这层有两条最重要的原则:

原则一:单一信号会骗你,必须多路交叉验证。 我的综合评分给过一只股 63 分、全市场第 6,看着是顶级标的。但把其他信号摆一起:主力在净流出、散户融资暴增 60%(拥挤)、因果模型偏空、PE 接近 500 倍、利息都覆盖不了。一个”全市场第 6”的高分股,底下藏着”主力跑、散户接、估值畸高”。 只信评分就追在山顶了。所以我刻意让各路信号保持输入独立——它们集体矛盾时,矛盾本身就是最值钱的信息。

最典型的是财务异常里一条规则:经营性现金流持续低于净利润——账面利润飞涨但现金没回来,利润是应收账款堆的。光看净利润增速你会很兴奋,加上这条交叉验证才看见风险。

原则二:再好的模型都有边界,要给它装”门控开关”。 我的因果推断模型在大部分环境有效,但在”趋势向上+高波动”的市场状态下会失效(多空夏普 -0.33)。新手直觉是”失效了去调模型”,更聪明的做法是承认它有适用域,并在系统层面门控——我做了个市场状态识别模块,处在失效象限时自动停用这个模型的评级修饰与其追求一个万能模型,不如做一个”知道自己什么时候不该说话”的系统。

第 4 层 · 决策层:机器出数据,人做判断

决策层把模型信号融合成最终产物:评级、风险收益测算、分析报告、操作清单。这层我踩过、也想明白了一件关于人机边界的事。

我曾经每分析一只股票都手工拼 8 个数据源、手敲 300 行报告,一只 15 分钟,还容易抄错数字。做到第十只我才反应过来:这件事的”数据部分”是确定性的,该让机器做。 于是写了个报告生成器:输入代码,自动把所有数据源串成报告骨架,只在三处留 <!-- 待人工填写 -->:业务面、风险收益、最终结论。单股分析从 15 分钟压到 3 分钟。

但我故意没让它自动出结论。因为实战时验证了一件事:生成器看不到的,恰恰最需要人判断。 有次它给”建议 3 星”,我手工降成 2 星——因为当时核心看空信号(超大单流出)因数据源挂了拿不到,生成器没看见所以”乐观”了。这个分歧本身就证明:人工复核不能省。

所以我的决策层这么切:

  • 机器负责:拉数、算指标、跑模型、组装骨架、确定性的交叉验证——又快又不累。
  • 人负责:解读业务、判断口径异常、权衡矛盾信号、对”模型看不见的东西”兜底——需要上下文和常识。

给新手:自动化不是取代人,是把人从确定性劳动里解放出来专注判断。好的设计会清楚标出”这里需要人”,而不是假装全知。

第 5 层 · 复盘层:没有它,前四层都是自嗨

这是新手最容易完全跳过的一层,但它决定你的系统是”科学”还是”玄学”。复盘层回答一个问题:前四层产出的判断,到底有没有用?

我的复盘层有几件套:

  • 回测:策略在历史数据上跑一遍,看收益/回撤/夏普。注意要做 Walk-Forward(滚动训练-测试)+ 防过拟合,别用未来数据。
  • IC 评估:每个因子和未来收益的相关性(IC/ICIR),定期算,淘汰失效因子。我就靠这个发现”财报披露窗口”因子是强负 alpha(ICIR -2.36)。
  • 模拟盘:每天用真实行情结算虚拟持仓,跟踪策略真实表现。
  • 跨日对比:今天的评级清单 vs 昨天,看谁新晋、谁掉队。

复盘层的产出要反哺前四层:IC 评估淘汰因子(反哺因子层)、回测验证模型门控的有效性(反哺模型层)、模拟盘暴露决策偏差(反哺决策层)。没有复盘闭环,你永远不知道自己是真有 alpha 还是在过拟合噪声。

必须单独拎出来的头号杀手:过拟合

如果说前面五层是”怎么把系统搭起来”,那这一节是”怎么不让系统骗你自己”。过拟合是量化新手的头号死因,它致命在于:你的回测曲线越漂亮,你越得意,而它很可能只是把历史噪声背了下来。

为什么量化特别容易过拟合?因为金融数据信噪比极低(真实规律微弱,随机波动巨大)、样本有限(A 股有效历史就十几年)、而人特别擅长事后找规律(任何一段历史你都能编出一个”完美”策略)。三者叠加,新手几乎必然会做出一个”回测年化 50%、实盘亏钱”的东西。

我在系统里专门用了几道防线,每一道都建议你抄走:

防线一:严格样本外 —— Walk-Forward 滚动验证。 别用全部历史训练再用全部历史测试(那叫”开卷考试”)。要滚动:用 2020-2022 训练、2023 测试,再用 2020-2023 训练、2024 测试……只在”模型没见过的未来”上验证。我所有回测都走 Walk-Forward,一个策略只有在多个滚动窗口都稳定,才算数。

防线二:防标签泄漏 —— Purged k-fold + embargo。 这是新手最容易忽略的细节。我的收益标签是”未来 20 天的超额收益”,意味着 6 月 1 日这条样本的标签,要用到 6 月底的数据。如果训练集里有 6 月 1 日、测试集里有 6 月 10 日,它们的标签窗口重叠了——测试集的”未来”泄漏进了训练集。做法是在训练/测试之间设一个 embargo(隔离带),把窗口会重叠的样本剔掉。任何用到”未来 N 天”做标签的模型,都必须处理这个泄漏。

防线三:防假数据 —— 源头校验。 过拟合有时不是模型的错,是数据的错。我加了一个合成/假数据检测(几条规则:价格是否过度平滑、成交量是否异常恒定、是否有可疑的等差数列填充等),因为某些降级数据源会用插值/合成数据填补缺口,用假数据训练出来的”规律”百分百是过拟合。 数据进模型前先验真。

防线四:因子层面持续淘汰 —— 别靠回测好看就留。 一个因子在回测里有效,可能只是运气。我用 IC 评估(因子和未来收益的滚动相关性)定期体检,失效的因子就淘汰,哪怕它曾经回测很美。我就靠这个发现某个因子是强负 alpha,果断剔除。

防线五:系统层面承认边界 —— 模型门控。 前面讲过的市场状态门控,本质也是防过拟合的一种——不在模型已知失效的环境里硬用它的输出,就是承认”我的模型只在某些条件下成立”,而不是假装它放之四海皆准。

最该建立的是一种心态:回测好看是默认应该怀疑的事,不是值得高兴的事。每看到一条漂亮的曲线,先问”我是不是哪里泄漏了未来、用了假数据、或者把噪声当成了信号”。对自己的结果保持敌意,是量化能活下来的前提。

贯穿五层的横切原则

有些原则不属于某一层,但每层都要遵守,决定系统的长期健康:

  • 根因排查,别打补丁。 我有个模型预测表冻结了 6 周,修了三次才到底:第一次改”触发日终点”没用 → 第二次发现真卡点是”数据加载终点”参数写死 → 第三次发现刷新流程漏了一个数据版本。改了你以为是原因的东西却没解决,是宝贵信号——说明你对根因的理解还不对,继续挖,别叠补丁。
  • 配置/常量唯一来源。 “股票池名称”枚举最初散在 12 个文件的命令行参数里,加一个新池要改 12 处必然漏。抽成一个常量,一处定义处处引用。copy-paste 过第二次的魔法值,都该收敛。
  • 文档和代码同步。 我的文档一度还写”23 维因子”,代码已经 29 维。文档落后于代码,三个月后的你自己都会被误导。
  • 诚实面对盲区。 做大盘研判时北向连续数据拿不到、估值只有横截面没有历史分位,我没假装有,而是专门写一节”数据盲区”列清楚。会说”我不知道”的系统,比什么都敢答的可信得多。

结语:给新手的搭建顺序

如果你正要从零搭一个量化系统,严格自下而上,别跳级:

  1. 先把数据层做扎实——统一读取入口 + 外部源降级。这步占你 40% 的工作量,但省下后面 80% 的麻烦。
  2. 再做因子层——可复现、落库、唯一清单。
  3. 然后是模型层——多信号交叉验证 + 模型门控。
  4. 接着决策层——工具化数据、人工补判断。
  5. 最后务必补上复盘层——没有它,前面全是自嗨。

注意,这张清单里没有一条是关于”什么策略能赚钱”。因为我越做越确信:量化新手的瓶颈从来不是策略,而是这套关于数据、降级、验证、边界、诚实的工程能力。 策略会失效、会过时,但一个工程扎实的系统,能让你快速试错、诚实复盘、持续迭代——这才是长期活下来的底气。

一个顺手的数据底座

最后留个彩蛋。上面反复提到”数据层是地基””外部源会挂、要多源兜底”——这些采集和降级的脏活,我抽出了一部分做成了一个开源的金融数据技能集,覆盖行情、财报、资金面(龙虎榜/北向/融资融券/大宗交易/股东户数)、研报、公告等全链条 A 股数据,自带多源降级:

👉 github.com/ghyghoo8/mx-skill-cc

如果你正在搭自己的量化系统、不想从零造数据层的轮子,可以拿它当第 1 层的起点,把精力省下来花在上面四层的判断逻辑上。欢迎 star / issue / PR。

共勉。