程序员量化交易实战 40:组合每日运行计划
程序员量化交易实战 40:组合每日运行计划
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。
第 36-39 篇分别补了每日运行请求、运行结果、归档索引和失败动作策略。
第 40 篇把这几块组合成一个每日运行计划。到这里,系统已经不只是一些独立函数,而是有了一个清晰的运行入口形状。

运行计划包含什么
DailyRunPlan 把四类对象放在一起:
| 字段 | 来源 |
|---|---|
request | 第 36 篇的每日运行请求 |
result | 第 37 篇的运行结果 |
failure_actions | 第 39 篇的失败处理动作 |
action_summary | 失败动作汇总 |
这不是最终的交易执行器,但已经足够作为 CLI 或定时任务的返回对象。
计划对象
第 40 章新增 app/daily_run_plan.py。
@dataclass(frozen=True)
class DailyRunPlan:
request: DailyRunRequest
result: DailyRunResult
failure_actions: tuple[FailureAction, ...]
action_summary: str
计划对象里保留 request,是为了排查时能看到当时的输入。不要只保存结果,否则很多生产问题会丢上下文。
组合计划
组合逻辑复用前面两章的函数。
def build_daily_run_plan(*, request: DailyRunRequest, checklist: OpsChecklist) -> DailyRunPlan:
result = build_daily_run_result(request=request, checklist=checklist)
actions = build_failure_actions(result)
return DailyRunPlan(
request=request,
result=result,
failure_actions=actions,
action_summary=failure_action_summary(actions),
)
这里没有重新实现任何检查逻辑。运行计划只做编排,不把业务规则复制一遍。
什么情况下可以执行
plan_can_execute() 比 result_is_actionable() 更严格。
def plan_can_execute(plan: DailyRunPlan) -> bool:
return plan.result.status == "ready"
dry_run_ready 可以继续生成报告,但不能执行真实动作。因此它是 actionable,却不是 executable。
当前联动运行结果
第 40 篇收口这条命令:
uv run python -m scripts.chapter_examples paper-run-plan
这次运行计划因为 data_gaps 被阻断:

输出里的 can_execute=False 是最关键的结论。它说明当前计划可以被记录、展示和归档,但不能进入真实执行阶段。后续接 CLI 或定时任务时,入口层可以直接围绕这个布尔结果决定是否继续。
测试三种计划
运行本章测试:
uv run pytest tests/test_daily_run_plan.py tests/test_failure_policy.py tests/test_run_result.py tests/test_ops_checklist.py tests/test_run_request.py
测试覆盖:
ready计划可以执行,且不需要失败动作。blocked计划返回wait_next_window和repair_market_data等动作。dry_run_ready可以继续观察,但plan_can_execute()返回 false。
当前全量测试也通过:
251 passed, 2 warnings
本章更新与代码仓库
本章更新内容:
- 新增
app/daily_run_plan.py。 - 实现
DailyRunPlan。 - 组合每日请求、运维检查清单、运行结果和失败动作。
- 实现
plan_can_execute()。 - 增加
paper-run-plan联动示例,展示 blocked 计划如何阻止真实执行。 - 补充 actionable、executable 和
can_execute的入口层语义。 - 新增
tests/test_daily_run_plan.py,覆盖 ready、blocked 和 dry-run-ready。 - 完成第 36-40 篇阶段 review。
代码仓库:
https://github.com/ax2/zi-quant-platform
本章代码:
git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-40
uv sync --extra dev
uv run pytest tests/test_daily_run_plan.py tests/test_failure_policy.py tests/test_run_result.py tests/test_ops_checklist.py tests/test_run_request.py
第 40 章提交为 f19a07d,tag 为 chapter-40。当前全量测试通过:251 passed,只有既有 FastAPI deprecation warning。
第 36-40 篇阶段 review
第八组五篇把前面散落的运维能力组合成了每日运行入口。
第 36 篇新增每日运行请求,把交易日、生成时间、必需股票和 dry-run 收进一个对象。
第 37 篇新增运行结果,把检查清单转换成 ready、dry_run_ready 或 blocked。
第 38 篇给日报归档建立索引,让历史报告能被稳定列出和查询。
第 39 篇把失败检查项映射成处理动作,让 blocked 状态变得可操作。
第 40 篇把请求、检查清单、运行结果和失败动作组合成每日运行计划。
这一组和前一组是连续的:第 31-35 篇先补前置检查,第 36-40 篇把检查结果组织成入口层。后面再接 CLI 或定时任务时,不需要重新发明运行状态,只要围绕 DailyRunPlan 往外包一层执行即可。
当前主线代码也补了一个跨章节命令:
uv run python -m scripts.chapter_examples paper-run-plan
它把第 36-40 篇串成一次可运行演示:构造每日请求、读取归档索引、生成 blocked 结果、映射失败动作,并组合出最终每日运行计划。这个命令刻意保留一个缺行情场景,用来说明计划对象如何把 no-go 原因带到入口层。
本篇小结
每日运行计划是模拟盘生产化入口的雏形。
第 40 篇之后,系统已经能把一次运行拆成输入、检查、结果、失败动作和可执行判断。下一步可以把它接到真实命令行入口,让每天的模拟盘流程用同一套计划对象驱动。