Quant Trading for Programmers 43: Command Response Object
· 15 min read · Views --
Last updated on

Quant Trading for Programmers 43: Command Response Object

Author: Alex Xiang


Quant Trading for Programmers 43: Command Response Object

Article 41 gave the daily run a summary. Article 42 gave it an artifact. The next step is the command-line entry point.

A CLI should not expose every field of DailyRunPlan directly. It needs an object closer to the execution environment: what the status is, what message should be shown to users, where the artifact is, and which exit code the process should use.

ZiCode engineer inspecting a daily-run command response

Command Response Object

Article 43 adds app/daily_run_command.py.

@dataclass(frozen=True)
class DailyRunCommandResponse:
    status: str
    message: str
    artifact_path: Path
    exit_code: int

This layer is for CLI and schedulers, not for strategy logic.

FieldWho uses it
statusHumans and schedulers
messageCLI stdout or logs
artifact_pathFull context for debugging
exit_codeshell, cron, CI, or job platform success/failure logic

Exit-Code Rules

This article starts with three levels:

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

Both ready and dry_run_ready mean the command completed successfully. Whether real execution is allowed is decided later by the execution guard.

warning returns 2 so it can be distinguished from a blocker. A scheduler can treat it as a yellow alert instead of a severe failure.

Write Artifact And Return Response

The composition function is:

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)

The command layer can call this function and receive:

  • one summary message;
  • one persisted JSON artifact;
  • one exit code for process termination.

Runnable Example

The command response can be reproduced with the chapter example:

uv run python -m scripts.chapter_examples paper-command

The output for this article is:

Daily-run command-response output

In this sample, status=blocked, so the command response returns exit_code=1. This is important: job platforms, cron, CI, and in-house schedulers usually do not read Python objects. They read process exit codes and stdout. The command response object translates domain status into something the execution environment understands.

The same line includes artifact=daily-run-2026-03-07.json. This avoids a common alerting problem: an alert says “run failed” but does not tell the on-call engineer where to inspect full context.

message=... executable=false reuses the one-line summary from article 41. The command layer does not rebuild business fields; it reuses the stable text produced by the summary layer.

Tests

The tests cover:

  • ready and dry_run_ready return exit code 0;
  • blocker returns 1;
  • warning returns 2;
  • command response points to a real artifact path.

Run:

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

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

276 passed, 2 warnings

Repository

This article adds:

  • 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, covering exit codes and artifact paths;
  • command-response output in scripts/chapter_examples.py, covering status, exit code, artifact, and message.

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

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

Article 43 does not rush into CLI argument parsing. It first fills in the command response object.

That order is steadier: let the domain layer produce a clear response first, then connect it to the real entry point. Otherwise CLI code easily starts mixing status decisions, file writes, and log formatting.