Quant Trading for Programmers 41: Summarize The Daily Run Plan
Quant Trading for Programmers 41: Summarize The Daily Run Plan
Article 40 already introduced DailyRunPlan, which contains the request, result, failure actions, and action summary.
But a plan object is not suitable for direct logging. In production logs, the first thing we usually need is one sentence: can today’s run proceed, which trade date is it for, how many symbols are involved, and how many checks failed?

Summary Object
Article 41 adds 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
It does not replace DailyRunPlan. It extracts the information humans need at first glance.
| Field | Purpose |
|---|---|
trade_date | Confirm which trading day this run belongs to |
status | Quickly distinguish ready, dry-run-ready, or blocked |
symbol_count | Notice whether the symbol coverage looks abnormal |
failed_check_count | Know the failure scale without expanding details |
action_summary | Judge whether it is warning, blocker, or no action needed |
executable | Whether real execution is allowed |
Build Summary From Plan
The summary function only reads DailyRunPlan; it does not recompute business rules.
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),
)
It reuses plan_can_execute(). If execution criteria change later, the summary layer does not need to duplicate judgment logic.
One Log Line
Logs become hard to scan when structure is scattered. Article 41 adds a stable format:
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()}"
)
A blocked example prints:
2026-02-11 status=blocked symbols=1 failed_checks=1 actions=blocker executable=false
This line can go directly into CLI output, scheduled-job logs, or alert messages. It does not explain every detail. It tells people whether they need to open the artifact next.
Runnable Example
The summary object is connected to the chapter example command. To let articles 41-45 share one real scenario, the sample deliberately constructs a daily run where data_gaps fails: the run window is normal, historical archive is normal, run health is normal, and only market-data checking blocks execution.
Run:
uv run python -m scripts.chapter_examples paper-command
The output for this article is:

Two parts matter most.
The first is the one-line summary: status=blocked, failed_checks=1, actions=blocker, executable=false. It fits logs and alert titles, letting people know without expanding JSON that today’s run cannot execute for real.
The second is structured fields: dry_run=False, symbol_count=2, failed_check_count=1. These fields can be split later when integrating with a CLI, job platform, or monitoring system instead of parsing strings.
The summary is not an audit record. It is only the “status title” at the entry layer. To debug why a run is blocked, the next article persists the full artifact.
Tests
The tests cover two things:
- ready plan correctly counts deduplicated symbols;
- blocked plan outputs a stable one-line summary.
Run:
uv run pytest tests/test_daily_run_summary.py tests/test_daily_run_plan.py
After adding paper-command in this batch, the full suite passed:
276 passed, 2 warnings
Repository
This article adds:
app/daily_run_summary.py;DailyRunSummary;build_daily_run_summary();format_daily_run_summary();tests/test_daily_run_summary.py, covering ready and blocked summaries;paper-commandinscripts/chapter_examples.py, which reproduces the run chain for articles 41-45.
Repository:
https://github.com/ax2/zi-quant-platform
Code for this chapter:
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
Articles 41-45 share the tag chapter-41-45-paper-command. The current full suite passes with 276 passed, with only existing FastAPI deprecation warnings.
Summary
Production work is not only about writing core logic. Runtime state must also be easy to understand quickly.
Article 41 compresses the daily-run plan into a summary. The next step is to persist the full context beyond the summary so failures can be replayed with the original request, failed checks, and remediation actions.
Follow ZiCode on WeChat
If this post was useful, you can follow later updates on WeChat as well.
X / Twitter
Follow @ax2_zicode
Faster technical notes, short thoughts, and new-post alerts are posted on X.
More in this column
- Quant Trading for Programmers 45: Daily Run Runbook
- Quant Trading for Programmers 44: Execution Guard
- Quant Trading for Programmers 43: Command Response Object
- Quant Trading for Programmers 42: Persist Daily Run Artifacts
- Quant Trading for Programmers 40: Compose The Daily Run Plan
- Quant Trading for Programmers 39: Turn Failed Checks Into Actions
- Quant Trading for Programmers 38: Index Daily Report Archives
- Quant Trading for Programmers 37: Generate Daily Run Results