程序员量化交易实战 41:把每日运行计划压成摘要
程序员量化交易实战 41:把每日运行计划压成摘要
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。
第 40 篇已经有了 DailyRunPlan,它包含请求、结果、失败动作和动作汇总。
但计划对象不适合直接打到日志里。生产环境里看日志时,我们通常只需要先知道一句话:今天能不能跑,跑的是哪天,有多少股票,失败了几项。

摘要对象
第 41 章新增 app/daily_run_summary.py。
@dataclass(frozen=True)
class DailyRunSummary:
trade_date: str
status: str
dry_run: bool
symbol_count: int
failed_check_count: int
action_summary: str
executable: bool
它不是替代 DailyRunPlan,而是从计划对象里提取一层“人第一眼要看的信息”。
| 字段 | 用途 |
|---|---|
trade_date | 确认这次运行对应哪个交易日 |
status | 快速判断 ready、dry-run-ready 或 blocked |
symbol_count | 观察本次覆盖的股票数量是否异常 |
failed_check_count | 不展开细节也能知道失败规模 |
action_summary | 判断是 warning、blocker 还是无需处理 |
executable | 是否允许真实执行 |
从计划构造摘要
摘要函数只读 DailyRunPlan,不重新计算业务规则。
def build_daily_run_summary(plan: DailyRunPlan) -> DailyRunSummary:
return DailyRunSummary(
trade_date=plan.result.trade_date,
status=plan.result.status,
dry_run=plan.result.dry_run,
symbol_count=len(plan.request.required_symbols),
failed_check_count=len(plan.result.failed_checks),
action_summary=plan.action_summary,
executable=plan_can_execute(plan),
)
这里继续复用 plan_can_execute()。如果后面执行标准变化,摘要层不用跟着复制判断逻辑。
一行日志
日志里最怕结构太散。第 41 章补了一个稳定格式:
def format_daily_run_summary(summary: DailyRunSummary) -> str:
return (
f"{summary.trade_date} "
f"status={summary.status} "
f"symbols={summary.symbol_count} "
f"failed_checks={summary.failed_check_count} "
f"actions={summary.action_summary} "
f"executable={str(summary.executable).lower()}"
)
blocked 示例输出:
2026-02-11 status=blocked symbols=1 failed_checks=1 actions=blocker executable=false
这行文字可以直接放进 CLI 输出、定时任务日志或告警消息。它不负责解释全部细节,只负责让人知道接下来要不要点开 artifact。
接到可运行示例
本章的摘要对象已经接入专栏代码仓库里的章节示例命令。为了让第 41-45 篇共用同一个真实场景,示例故意构造了一次 data_gaps 未通过的每日运行:运行窗口正常、历史归档正常、运行健康正常,只有行情数据检查失败。
运行命令:
uv run python -m scripts.chapter_examples paper-command
本章对应的输出如下:

这里最重要的是两段信息。
第一段是一行摘要:status=blocked、failed_checks=1、actions=blocker、executable=false。它适合放进日志和告警标题里,让人不用展开 JSON 就知道今天不能真实执行。
第二段是结构化字段:dry_run=False、symbol_count=2、failed_check_count=1。这类字段适合后续接入 CLI、任务平台或监控系统时继续拆分,而不是靠字符串解析。
摘要不是审计凭证。它只是入口层的“状态标题”。真正要排查为什么 blocked,需要看下一篇落盘的 artifact。
测试
本章测试覆盖两件事:
- ready 计划能正确统计去重后的股票数量。
- blocked 计划能输出稳定的一行摘要。
运行命令:
uv run pytest tests/test_daily_run_summary.py tests/test_daily_run_plan.py
本批次补充 paper-command 后,全量测试通过:
276 passed, 2 warnings
本章更新与代码仓库
本章更新内容:
- 新增
app/daily_run_summary.py。 - 新增
DailyRunSummary。 - 实现
build_daily_run_summary()。 - 实现
format_daily_run_summary()。 - 新增
tests/test_daily_run_summary.py,覆盖 ready 与 blocked 摘要。 - 在
scripts/chapter_examples.py中接入paper-command,可直接复现第 41-45 篇的运行链路。
代码仓库:
https://github.com/ax2/zi-quant-platform
本章代码:
git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-41-45-paper-command
uv sync --extra dev
uv run python -m scripts.chapter_examples paper-command
uv run pytest tests/test_daily_run_summary.py tests/test_daily_run_plan.py tests/test_chapter_examples.py
第 41-45 篇共用 tag chapter-41-45-paper-command。当前全量测试通过:276 passed,只有既有 FastAPI deprecation warning。
本篇小结
生产化不是只把核心逻辑写出来,还要让运行状态能被快速看懂。
第 41 篇把每日运行计划压缩成摘要。下一步要解决的是:摘要之外的完整上下文怎么落盘,出了问题以后能不能回放当时的请求、失败检查和处理动作。