Quant Trading for Programmers 40: Compose The Daily Run Plan
· 18 min read · Views --
Last updated on

Quant Trading for Programmers 40: Compose The Daily Run Plan

Author: Alex Xiang


Quant Trading for Programmers 40: Compose The Daily Run Plan

Articles 36-39 added the daily run request, run result, archive index, and failure-action policy.

Article 40 combines these parts into a daily run plan. At this point, the system is no longer just a set of independent functions. It has the shape of a clear runtime entry point.

ZiCode engineer composing a daily run plan

What The Run Plan Contains

DailyRunPlan groups four kinds of objects:

FieldSource
requestdaily run request from article 36
resultrun result from article 37
failure_actionsfailure handling actions from article 39
action_summaryfailure-action summary

This is not the final trading executor, but it is already sufficient as a return object for a CLI or scheduled job.

Plan Object

Article 40 adds app/daily_run_plan.py.

@dataclass(frozen=True)
class DailyRunPlan:
    request: DailyRunRequest
    result: DailyRunResult
    failure_actions: tuple[FailureAction, ...]
    action_summary: str

The plan keeps request so debugging can see the original input. Do not keep only the result; otherwise many production issues lose context.

Compose The Plan

The composition logic reuses functions from the previous articles.

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),
    )

There is no duplicated checking logic here. The run plan orchestrates; it does not copy business rules.

When Can It Execute?

plan_can_execute() is stricter than result_is_actionable().

def plan_can_execute(plan: DailyRunPlan) -> bool:
    return plan.result.status == "ready"

dry_run_ready can keep generating reports, but it cannot perform real actions. It is actionable, but not executable.

Current Linked Output

Article 40 closes this command:

uv run python -m scripts.chapter_examples paper-run-plan

The daily run plan is blocked by data_gaps:

Daily run plan generated by paper-run-plan

The key conclusion is can_execute=False. It means the current plan can be recorded, displayed, and archived, but must not enter the real execution phase. When a CLI or scheduler is added later, the entry layer can directly use this boolean to decide whether to continue.

Test Three Kinds Of Plans

Run the tests for this article:

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

The tests cover:

  • ready plan can execute and needs no failure actions;
  • blocked plan returns actions such as wait_next_window and repair_market_data;
  • dry-run-ready can continue observation, but plan_can_execute() returns false.

The full suite also passed:

251 passed, 2 warnings

Repository

This article adds:

  • app/daily_run_plan.py;
  • DailyRunPlan;
  • composition of daily request, operations checklist, run result, and failure actions;
  • plan_can_execute();
  • linked paper-run-plan example, showing how a blocked plan prevents real execution;
  • entry-layer semantics for actionable, executable, and can_execute;
  • tests/test_daily_run_plan.py, covering ready, blocked, and dry-run-ready;
  • stage review for articles 36-40.

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-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

The article 40 commit is f19a07d, and the tag is chapter-40. The current full suite passes with 251 passed, with only existing FastAPI deprecation warnings.

Review Of Articles 36-40

The eighth group of five articles combines the scattered operations capabilities into a daily runtime entry point.

Article 36 adds the daily run request, collecting trade date, generation time, required symbols, and dry-run flag.

Article 37 adds the run result, converting the checklist into ready, dry_run_ready, or blocked.

Article 38 indexes daily report archives so historical reports can be listed and queried reliably.

Article 39 maps failed checks to handling actions, making blocked states operational.

Article 40 combines request, checklist, run result, and failure actions into a daily run plan.

This group continues directly from the previous one. Articles 31-35 added pre-run checks. Articles 36-40 organize those check results into the entry layer. When CLI or scheduled jobs are added later, there is no need to reinvent runtime state; they can wrap execution around DailyRunPlan.

The main branch also adds a cross-chapter command:

uv run python -m scripts.chapter_examples paper-run-plan

It turns articles 36-40 into one runnable demo: construct a daily request, read the archive index, generate a blocked result, map failure actions, and compose the final daily run plan. The command deliberately keeps a missing market-data scenario to show how the plan object carries the no-go reason up to the entry layer.

Summary

The daily run plan is the first shape of a productionized paper-trading entry point.

After article 40, the system can split one run into input, checks, result, failure actions, and executable judgment. The next step is to connect this to a real command-line entry point so the daily paper-trading flow is driven by one shared plan object.