程序员量化交易实战 35:生成运维检查清单
原创 · 约 12 分钟阅读 · 阅读 --
Last updated on

程序员量化交易实战 35:生成运维检查清单

作者: Alex Xiang


程序员量化交易实战 35:生成运维检查清单

古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。

第 31-34 篇分别补了运行时间窗、日报归档、历史摘要和数据缺口计划。

第 35 篇把这些状态合起来,生成一张最小运维检查清单。每日流程真正执行前,先看这张清单,而不是靠人脑记住所有前置条件。

ZiCode 工程师查看模拟盘运维检查清单

检查清单应该少而准

检查项不是越多越好。

早期模拟盘最需要盯住四件事:

检查项输入失败含义
run_windowRunWindowStatus当前不在允许运行时间窗
history_readyRunHistorySummary没有可参考的历史归档
data_gapsDataGapPlan必需行情价格缺失
run_healthRunHealthReport最近运行健康状态是 blocker

这四项不讨论策略收益,只讨论系统今天能不能可信地运行。

清单对象

第 35 章新增 app/ops_checklist.py

@dataclass(frozen=True)
class OpsChecklistItem:
    name: str
    passed: bool
    detail: str


@dataclass(frozen=True)
class OpsChecklist:
    passed: bool
    items: tuple[OpsChecklistItem, ...]

detail 不做复杂结构,先保留一个简短字符串。对于日报、命令行和测试断言来说,这已经足够。

组合四类状态

构造函数只做组合,不重新计算业务状态。

items = (
    OpsChecklistItem("run_window", window_status.allowed, window_status.reason),
    OpsChecklistItem("history_ready", history_summary.report_count > 0, history_summary.latest_status),
    OpsChecklistItem("data_gaps", not gap_plan.gaps, gap_plan.severity),
    OpsChecklistItem("run_health", health_report.status != "blocker", health_report.status),
)

最后用所有检查项决定总结果:

return OpsChecklist(
    passed=all(item.passed for item in items),
    items=items,
)

这里故意不做“部分通过”的复杂状态。模拟盘运行前,第一版只需要一个清楚的 go/no-go 结果。

go/no-go 是运维里很常见的叫法。go 表示前置条件足够,可以继续执行;no-go 表示至少有一个关键条件失败,应该暂停、补数据或人工确认。它不回答策略是否优秀,只回答这次运行能不能可信地开始。

当前联动运行结果

第 35 篇收口同一条命令:

uv run python -m scripts.chapter_examples paper-ops-check

命令输出里,时间窗、历史摘要和运行健康都通过,但数据缺口没有通过:

paper-ops-check 命令生成的运维检查清单

最终 passed=False。这正是检查清单的价值:不是所有模块都成功就放行,而是只要关键前置条件失败,就给出明确的 no-go 结果。

测试通过和失败

测试覆盖两类输入。

健康输入下,清单整体通过,并且检查项顺序稳定:

assert checklist.passed is True
assert [item.name for item in checklist.items] == [
    "run_window",
    "history_ready",
    "data_gaps",
    "run_health",
]

失败输入下,测试确认失败项是时间窗、历史和健康报告:

failed = {item.name for item in checklist.items if not item.passed}
assert failed == {"run_window", "history_ready", "run_health"}

运行命令:

uv run pytest tests/test_ops_checklist.py tests/test_run_window.py tests/test_run_history.py tests/test_run_health.py

本章更新与代码仓库

本章更新内容:

  • 新增 app/ops_checklist.py
  • 实现 OpsChecklistItemOpsChecklist
  • 汇总运行时间窗、历史摘要、数据缺口和运行健康状态。
  • 输出稳定的 go/no-go 检查结果。
  • 增加 paper-ops-check 联动示例,展示真实 no-go 检查结果。
  • 补充 go/no-go 在每日模拟盘运行前的工程语义。
  • 新增 tests/test_ops_checklist.py,覆盖健康输入和失败输入。
  • 完成第 31-35 篇阶段 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-35
uv sync --extra dev
uv run pytest tests/test_ops_checklist.py tests/test_run_window.py tests/test_run_history.py tests/test_run_health.py

第 35 章提交为 fc242ec,tag 为 chapter-35

第 31-35 篇阶段 review

第七组五篇把模拟盘从“能生成单日报告”推进到“能被日常运维”。

第 31 篇给每日任务加运行时间窗,避免在错误时间运行。

第 32 篇把提醒、健康报告和复盘记录归档成稳定 JSON,让每日运行有证据。

第 33 篇读取归档目录,汇总运行历史、阻断次数和通知成功率。

第 34 篇识别行情数据缺口,把缺失价格变成 blocker 级别的结构化结果。

第 35 篇把前面几类状态合并成运维检查清单,给每日流程一个清楚的 go/no-go 判断。

这一组没有追求更复杂的策略,而是继续加固系统边界。运行时间、历史证据、行情完整性和健康状态都能被检查以后,后面接真实调度或更多数据源时,出问题更容易定位。

当前主线代码也补了一个跨章节命令:

uv run python -m scripts.chapter_examples paper-ops-check

它把第 31-35 篇串成一次可运行演示:先判断运行时间窗,再写入日报归档,随后汇总运行历史,识别价格缺口,最后生成运维检查清单。下一组文章如果接真实每日命令,就可以先调用这张清单决定是否继续执行。

本篇小结

运维检查清单是模拟盘运行前的一道门。

第 35 篇让系统在执行前先回答四个问题:现在能不能跑、历史是否存在、行情是否完整、最近健康状态是否阻断。下一步可以把这张清单接入真实每日命令,把模拟盘流程从函数组合推进到可执行任务。