Quant Trading for Programmers 17: Generate Paper-Trading Account Snapshots
· 12 min read · Views --
Last updated on

Quant Trading for Programmers 17: Generate Paper-Trading Account Snapshots

Author: Alex Xiang


Quant Trading for Programmers 17: Generate Paper-Trading Account Snapshots

Article 16 added the paper-trading ledger. The ledger is good for updating state, but it is not the best structure for risk controls and display.

Article 17 adds account snapshots, organizing cash, positions, market value, floating PnL, and weights into one structure.

A ZiCode engineer taking a paper-trading equity snapshot

What The Snapshot Solves

Paper trading will later have three consumers:

  • The risk module needs cash ratio and single-stock weight.
  • The rebalance module needs the gap between current weights and target weights.
  • The notification module needs to turn account state into a readable summary.

If every module calculates these values separately, definitions will easily drift.

The distinction between ledger and snapshot matters. The ledger answers “how the account reached the current state.” The snapshot answers “what the account looks like right now.” Both should be kept for reviews. With only the ledger, readers must calculate market value and weights themselves. With only the snapshot, it is hard to explain how the account got there.

Snapshot Object

Chapter 17 adds app/paper_snapshots.py.

@dataclass(frozen=True)
class PaperAccountSnapshot:
    trade_date: date
    cash: float
    market_value: float
    total_equity: float
    cash_ratio: float
    positions: tuple[PaperPositionSnapshot, ...]

Each position snapshot contains latest price, market value, cost, floating PnL, and weight.

Build The Snapshot

The entry point is build_paper_account_snapshot():

snapshot = build_paper_account_snapshot(
    account,
    trade_date=date(2026, 1, 9),
    last_prices={"000001.SZ": 11.0},
)

There is no hidden market-data query here. The caller must pass last_prices explicitly. That means tests do not need to mock an external data source, and production integration can still clearly show where prices come from.

Handling Missing Prices

The current version treats a missing price as 0.

This is not the final production strategy, but it has one benefit for early paper trading: it exposes the “missing market data” problem instead of silently continuing with stale prices. When real market data is connected later, missing-price alerts can be added.

Current Mainline Integrated Run

The same paper-flow command generates an account snapshot after ledger execution:

uv run python -m scripts.chapter_examples paper-flow

Real output:

Real account snapshot output for article 17

The screenshot shows total equity of 105031.28, cash ratio of 19.26%, 000001.SZ position weight of 80.74%, and floating PnL of 5031.28. Later risk controls no longer recalculate these definitions. They consume this snapshot directly.

Chapter Update And Repository

This chapter adds:

  • app/paper_snapshots.py.
  • Account snapshots and position snapshots.
  • Cash ratio, position market value, total equity, floating PnL, and position-weight calculations.
  • tests/test_paper_snapshots.py, covering multi-position snapshots and missing-price handling.
  • A real current-mainline screenshot for the account snapshot integrated example.
  • The responsibility boundary between the ledger and snapshots.

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-17
uv sync --extra dev
uv run pytest tests/test_paper_snapshots.py

Chapter 17 is commit 8d53e39, tagged as chapter-17.

Summary

The ledger is responsible for state changes. The snapshot is responsible for shared definitions.

Article 17 turns the paper-trading account into a readable, testable, reusable snapshot object. The next article builds the first version of paper-trading risk checks on top of that snapshot.