程序员量化交易实战 43:命令响应对象
程序员量化交易实战 43:命令响应对象
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。
第 41 篇有摘要,第 42 篇有 artifact。接下来要考虑命令行入口。
命令行不应该直接暴露 DailyRunPlan 的所有字段。它需要一个更贴近执行环境的对象:状态是什么,给用户看的消息是什么,artifact 在哪里,进程应该用什么 exit code 退出。

命令响应对象
第 43 章新增 app/daily_run_command.py。
@dataclass(frozen=True)
class DailyRunCommandResponse:
status: str
message: str
artifact_path: Path
exit_code: int
这层对象面向 CLI 和调度器,不面向策略逻辑。
| 字段 | 谁会用 |
|---|---|
status | 人和调度系统都要看 |
message | 命令行 stdout 或日志 |
artifact_path | 排查时打开完整上下文 |
exit_code | shell、cron、CI 或任务平台判断成功失败 |
exit code 规则
本章先采用三档:
def daily_run_exit_code(plan: DailyRunPlan) -> int:
if plan.result.status in {"ready", "dry_run_ready"}:
return 0
if plan.action_summary == "warning":
return 2
return 1
ready 和 dry_run_ready 都是命令成功完成。区别在于是否允许真实执行,这件事由后面的执行闸门判断。
warning 返回 2,是为了和 blocker 区分。这样调度系统可以选择“黄色告警”而不是直接按严重失败处理。
写 artifact 并返回响应
组合函数如下:
def write_daily_run_command_response(
*,
plan: DailyRunPlan,
artifact_dir: Path,
) -> DailyRunCommandResponse:
artifact = write_daily_run_artifact(plan, directory=artifact_dir)
return build_daily_run_command_response(plan=plan, artifact=artifact)
命令层只要调用它,就能同时得到:
- 一行摘要消息。
- 一个已落盘的 JSON artifact。
- 一个可用于进程退出的 exit code。
接到可运行示例
本章的命令响应可以通过章节示例命令直接复现:
uv run python -m scripts.chapter_examples paper-command
本章对应的输出如下:

这次示例的 status=blocked,所以命令响应给出 exit_code=1。这点很关键:任务平台、cron、CI 或自研调度器通常不读 Python 对象,只看进程退出码和 stdout。命令响应对象把领域状态翻译成了执行环境能理解的结果。
同一行里还带着 artifact=daily-run-2026-03-07.json。这避免了一个常见问题:告警里只写“运行失败”,但没有告诉值班的人去哪里看完整上下文。
message=... executable=false 则保留了第 41 篇的一行摘要。也就是说,命令层不重新拼业务字段,只复用摘要层给出的稳定文本。
测试
本章测试覆盖:
- ready 和 dry-run-ready 返回 exit code 0。
- blocker 返回 1。
- warning 返回 2。
- command response 能指向真实 artifact 路径。
运行命令:
uv run pytest tests/test_daily_run_command.py tests/test_daily_run_artifacts.py tests/test_daily_run_summary.py tests/test_daily_run_plan.py
本批次补充 paper-command 后,全量测试通过:
276 passed, 2 warnings
本章更新与代码仓库
本章更新内容:
- 新增
app/daily_run_command.py。 - 新增
DailyRunCommandResponse。 - 实现
daily_run_exit_code()。 - 实现
build_daily_run_command_response()。 - 实现
write_daily_run_command_response()。 - 新增
tests/test_daily_run_command.py,覆盖 exit code 和 artifact 路径。 - 在
scripts/chapter_examples.py中接入命令响应输出,覆盖状态、exit code、artifact 和消息。
代码仓库:
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_command.py tests/test_daily_run_artifacts.py 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。
本篇小结
第 43 篇没有急着写 CLI 参数解析,而是先把命令响应对象补齐。
这个顺序更稳:先让领域层给出明确响应,再把它接到真正的入口。否则命令行代码很容易混进状态判断、文件写入和日志拼接。