跑得快:把 Rust 判了缓刑
跑得快是四阶段最后一站。设计稿里它是最重的一站——Rust 回测核心、parquet 分区、DuckDB 查询引擎,都是为它准备的。但路线图的决策表写得很清楚:先 profiling,瓶颈在哪,优化哪。没有瓶颈,就不动。
profiling:先量化,再动手
把 pipeline 的每个环节都计时,结果出乎意料:
读数据 0.01 秒,因子 0.01 秒,信号 0.01 秒,因子 IC 0.06 秒,回测 0.3 秒,信号跟踪 0.11 秒,报告 0.23 秒。50 只股票、43K 行 bar、2478 笔成交,纯计算全流程不到 1 秒。回测摊到单票 0.006 秒——Python 的逐行撮合循环,比预想快得多。
规模外推
再往外推:沪深 300 大约 300 票,回测 1.8 秒;全市场 5000 票,回测 30 秒。当初设计 Rust 回测核心,理由之一是「不接受一次策略跑数小时」——现在有实测了:就算全市场,Python 也只要半分钟。
决策表判定:三个复杂度全部缓刑
按路线图的决策表逐个判:
- Rust:取消。设计稿里写过一条假设——「如果 Python 回测足够快,整个 Rust 取消」。它落地了。
- parquet 分区 + DuckDB:推迟。数据量 43K 行,全市场约 440 万行,离千万级的阈值很远。设计稿另一条假设也落地——「如果数据量远小于预估,整套存储简化」。实际上连 SQLite 都没用到。
- tj-web:推迟。浏览报告没有手动成本痛点。
唯一的耗时项是拉数,2 分 40 秒,卡在 Tushare 的 API 限流,不是存储。全市场拉数按限流估算约 40 分钟,盘后批处理可接受;真到那天,再写增量拉数。
触发阈值:把「什么时候优化」写下来
不做的决策,也要写清楚什么时候做,否则就是拍脑袋。触发阈值记在决策文档里:
单票回测超过 0.1 秒,或全市场回测超过 1 分钟,上 Rust;数据量超过千万行,迁 parquet 分区和 DuckDB;浏览报告真的费劲了,再上 tj-web。
这些阈值是给未来的自己留的判断标准——到了那天,不是重新争论要不要优化,而是直接对照阈值做决定。
收官
四阶段走完了。回看第 1 篇,设计稿里那些最重的复杂度——Rust、七包、11 页 UI、MCP——一个都没进第一批代码。能跑阶段证明循环转得起来,跑得准把数字弄可信,跑得稳让它不用盯,跑得快用实测告诉我不需要更快。
三个大复杂度被判了缓刑,不是偷懒。是每次决策都有依据:数据契约和 A 股语义是「做了才准」,必须做对;Rust 和 UI 是「不做也能跑」,等痛点出现再上。四阶段框架的完整闭环,就是让每一类复杂度都在它该出现的时候出现。
寒蝉 Hancic

