Quant Trading for Programmers 39: Turn Failed Checks Into Actions
· 13 min read · Views --
Last updated on

Quant Trading for Programmers 39: Turn Failed Checks Into Actions

Author: Alex Xiang


Quant Trading for Programmers 39: Turn Failed Checks Into Actions

Article 37 can already keep failed checks in DailyRunResult.failed_checks.

Article 39 continues by turning failures into actions. The system should not only say “failed.” It should also tell the operator whether to wait, repair data, or inspect health reports.

ZiCode engineer handling paper-trading failure actions

Failure Actions Are Not Automatic Repair

The actions here do not directly repair production issues.

The first version only performs routing: it maps failed checks to remediation suggestions and severity.

Failed checkActionSeverity
run_windowwait_next_windowinfo
history_readyinspect_archivewarning
data_gapsrepair_market_datablocker
run_healthinspect_run_healthblocker
Unknown checkmanual_reviewwarning

This table is small, but it lets daily reports, CLI output, and later automation speak the same language.

Failure Action Object

Article 39 adds app/failure_policy.py.

@dataclass(frozen=True)
class FailureAction:
    check_name: str
    action: str
    severity: str

check_name keeps the original check. action gives the handling direction. severity determines the summary status.

Mapping Policy

The policy table is written as a constant.

_ACTION_BY_CHECK = {
    "run_window": ("wait_next_window", "info"),
    "history_ready": ("inspect_archive", "warning"),
    "data_gaps": ("repair_market_data", "blocker"),
    "run_health": ("inspect_run_health", "blocker"),
}

Unknown checks fall back to manual review.

action, severity = _ACTION_BY_CHECK.get(
    check_name,
    ("manual_review", "warning"),
)

That way, if a new check is added and the policy is not updated yet, the system does not crash.

Action Summary

The summary rule stays simple:

if not actions:
    return "no_action_required"
if any(action.severity == "blocker" for action in actions):
    return "blocker"
return "warning"

If any blocker exists, the whole failure-action summary is blocker. No actions means nothing needs handling.

Runnable Example

paper-run-plan deliberately makes the price source miss 600519.SH, so the run result has data_gaps as the failed check:

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

Failure-action mapping generated by paper-run-plan

The system maps data_gaps to repair_market_data, with severity blocker. This is more useful than only printing “blocked,” because the operator can immediately tell that the next step is repairing market data, not checking the run window or notification channel.

Test Action Mapping

Run:

uv run pytest tests/test_failure_policy.py tests/test_run_result.py

Key assertions:

assert [(item.check_name, item.action, item.severity) for item in actions] == [
    ("run_window", "wait_next_window", "info"),
    ("data_gaps", "repair_market_data", "blocker"),
    ("run_health", "inspect_run_health", "blocker"),
]
assert failure_action_summary(actions) == "blocker"

Repository

This article adds:

  • app/failure_policy.py;
  • FailureAction;
  • mapping from failed checks to remediation actions;
  • fallback manual review for unknown checks;
  • failure_action_summary();
  • paper-run-plan linked example, showing data_gaps mapped to repair_market_data;
  • explanation of the difference between blocked status and handling actions;
  • tests/test_failure_policy.py, covering known checks, unknown checks, and empty actions.

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-39
uv sync --extra dev
uv run pytest tests/test_failure_policy.py tests/test_run_result.py

The article 39 commit is c05f77f, and the tag is chapter-39.

Summary

Failure actions make a blocked state operational.

Article 39 converts failed checks into remediation suggestions and severity. The next article combines request, checklist, run result, and failure actions into a daily run plan, closing this group of work.