Quant Trading for Programmers 45: Daily Run Runbook
· 19 min read · Views --
Last updated on

Quant Trading for Programmers 45: Daily Run Runbook

Author: Alex Xiang


Quant Trading for Programmers 45: Daily Run Runbook

Article 44 introduced execution decisions, but alerts that only say repair_market_data are still not operator-friendly enough.

Article 45 turns execution decisions into a runbook: if the plan can run, what is the next step; if it cannot run, what should be checked or repaired first.

ZiCode engineer reading a daily-run runbook

Runbook Object

Article 45 adds app/ops_runbook.py.

@dataclass(frozen=True)
class RunbookStep:
    title: str
    command: str
    required: bool


@dataclass(frozen=True)
class OpsRunbook:
    trade_date: str
    status: str
    steps: tuple[RunbookStep, ...]

Here command is not an automatically executed shell command yet. It is an operations instruction. The reason is simple: repairing data, checking archives, and waiting for a run window may require human confirmation and should not be blindly automated.

Action Mapping

This article maps existing actions into readable steps.

_COMMAND_BY_ACTION = {
    "disable_dry_run": "rerun with dry_run=false after manual confirmation",
    "inspect_archive": "check report archive index for the previous successful run",
    "inspect_run_health": "inspect recent run health events and retry only after recovery",
    "repair_market_data": "reload missing market data and rerun checklist",
    "wait_next_window": "wait until the configured run window opens",
    "manual_review": "open the artifact and review the failed checklist item manually",
}

The mapping is simple, but it is already better for alerts than showing only action names.

Build Runbook From Execution Decision

The core function is:

def build_ops_runbook(plan: DailyRunPlan) -> OpsRunbook:
    decision = decide_execution(plan)
    if decision.allowed:
        steps = (
            RunbookStep("confirm artifact", "open the daily-run artifact before execution", True),
            RunbookStep("execute plan", "start the simulated trading daily run", True),
        )
    else:
        steps = tuple(
            RunbookStep(action, _COMMAND_BY_ACTION.get(action, _COMMAND_BY_ACTION["manual_review"]), True)
            for action in decision.required_actions
        )
    return OpsRunbook(trade_date=plan.result.trade_date, status=plan.result.status, steps=steps)

A ready plan produces “confirm artifact” and “execute plan.”

A blocked plan produces remediation actions, for example:

2026-02-15 status=blocked
- repair_market_data: reload missing market data and rerun checklist

Runnable Example

Article 45 uses the same chapter command:

uv run python -m scripts.chapter_examples paper-command

The output for this article is:

Daily-run runbook output

This runbook contains one step: repair_market_data. It is not a decorative suggestion. It is passed down through the checklist from article 35, the failure action from article 39, and the execution guard from article 44.

The runbook should not be too fine-grained. For example, “download which stock’s market data for which date” needs the data-repair module to provide more specific context. This article first translates the action into an operator-readable direction: reload missing market data, then rerun the checklist. The alert no longer contains only an English action name, but it also does not rush into automatic data repair.

Tests

The tests cover:

  • ready plan creates execution steps;
  • dry-run-ready plan requires manual confirmation before disabling dry run;
  • blocked plan follows failure actions;
  • runbook can be converted into multiline text for alerts.

Run:

uv run pytest tests/test_ops_runbook.py tests/test_execution_guard.py tests/test_daily_run_plan.py

After adding paper-command in this batch, the full test suite passed:

276 passed, 2 warnings

Repository

This article adds:

  • app/ops_runbook.py;
  • RunbookStep and OpsRunbook;
  • build_ops_runbook();
  • runbook_as_lines();
  • tests/test_ops_runbook.py, covering ready, dry-run-ready, blocked, and alert text;
  • stage review for articles 41-45;
  • runbook output in scripts/chapter_examples.py, forming a runnable loop 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_ops_runbook.py tests/test_execution_guard.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.

Review Of Articles 41-45

This group does not extend strategy logic. It pushes the daily-run entry point closer to production usability.

Article 41 adds DailyRunSummary, compressing the plan into a log-friendly and CLI-friendly one-line summary.

Article 42 adds DailyRunArtifact, writing daily-run context to JSON for debugging and archival.

Article 43 adds DailyRunCommandResponse, wrapping status, message, artifact path, and exit code for the command layer.

Article 44 adds ExecutionDecision, centralizing the judgment before real execution.

Article 45 adds OpsRunbook, turning the execution decision into operations steps.

Together, these five articles fill in the outer frame of the runtime system: summary, evidence, command response, guard, and runbook. They do not decide what to buy or sell, but they decide whether the system can run every day, be debugged by humans, and avoid accidental execution.

The runnable entry point added in this batch is:

uv run python -m scripts.chapter_examples paper-command

It deliberately constructs a data_gaps blocked scenario and walks through summary, artifact, command response, execution guard, and runbook. Readers can see the dependency chain across articles 41-45 from one command instead of reading five isolated modules.

Summary

A runbook translates system state into steps people can execute.

By article 45, the daily run has a loop from plan to summary, artifact, command response, execution decision, and operations steps. When CLI or scheduled jobs are added later, they can wrap this chain instead of scattering judgment logic across entry scripts.