Quant Trading for Programmers 34: Detect Market Data Gaps
· 14 min read · Views --
Last updated on

Quant Trading for Programmers 34: Detect Market Data Gaps

Author: Alex Xiang


Quant Trading for Programmers 34: Detect Market Data Gaps

In article 33, the paper-trading system started to judge stability from historical run archives.

Article 34 moves back to the input checks before a daily run. If a target stock is missing its latest price, the system should report that gap explicitly instead of allowing the strategy to keep running on None, 0, or stale data.

A ZiCode engineer checking market data gaps

Missing Prices Are Not Minor

The most dangerous bugs in a paper-trading system are often not the ones that crash immediately. They are the ones where data is missing, but the program keeps running.

If a stock does not have a current price, rebalance value, risk exposure, and equity snapshots can all become distorted. In the early version of this platform, I prefer to be conservative and mark this kind of issue as a blocker.

The Gap Object

Chapter 34 adds app/data_gaps.py.

@dataclass(frozen=True)
class DataGap:
    symbol: str
    trade_date: date
    field: str
    severity: str


@dataclass(frozen=True)
class DataGapPlan:
    gaps: tuple[DataGap, ...]
    severity: str

The first version only checks last_price. Later versions can extend the same structure to volume, adjustment factors, suspended status, and other fields.

Build The Gap Plan

The function takes a price snapshot and a list of required symbols:

def build_price_gap_plan(
    price_snapshot: PriceSnapshot,
    *,
    required_symbols: list[str],
) -> DataGapPlan:

The implementation deduplicates the required list first, then compares it with the symbols that already have prices in the snapshot.

required = list(dict.fromkeys(required_symbols))
missing = sorted(set(required) - set(price_snapshot.prices))

Each missing symbol becomes a blocker:

DataGap(
    symbol=symbol,
    trade_date=price_snapshot.trade_date,
    field="last_price",
    severity="blocker",
)

The design is plain, but it changes a data gap from “maybe there is a log line somewhere” into a testable, aggregatable structure that can feed an operations checklist.

Market data gaps are not limited to missing prices. Daily strategies may also hit missing volume, missing adjustment factors, missing suspended-status data, or delayed stock-universe updates. The first version focuses only on last_price because a missing price directly affects equity, positions, and rebalance value. It is the first category a paper-trading system should block.

Current Integrated Run

paper-ops-check intentionally creates a missing-price scenario. Required symbols include 000001.SZ and 600519.SH, while the price source only returns 000001.SZ.

uv run python -m scripts.chapter_examples paper-ops-check

Data-gap check output from the paper-ops-check command

The gap plan therefore returns severity=blocker and gap_symbols=['600519.SH']. This result goes directly into the operations checklist in article 35, stopping the system from running when market data is incomplete.

Test The Gap Output

In the test case, the price snapshot only contains 000001.SZ, while the required list also includes 600000.SH and 300001.SZ.

uv run pytest tests/test_data_gaps.py

The assertions are straightforward:

assert plan.severity == "blocker"
assert gap_symbols(plan) == ["300001.SZ", "600000.SH"]
assert plan.gaps[0].field == "last_price"

If all required prices are present, the function returns severity == "ok" and gaps == ().

Chapter Update And Repository

This chapter adds:

  • app/data_gaps.py.
  • DataGap and DataGapPlan.
  • A gap check between required symbols and the current price snapshot.
  • Blocker severity for missing prices.
  • gap_symbols() for tests and display output.
  • An integrated paper-ops-check example showing how a missing price becomes a blocker-level data gap.
  • Context for price, volume, adjustment factor, suspended-status, and stock-universe data gaps.
  • tests/test_data_gaps.py, covering both missing-price and complete-data scenarios.

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

Chapter 34 is commit 5c94461, tagged as chapter-34.

Summary

Market data gaps should become structured results as early as possible.

Article 34 turns missing prices from an implicit risk into DataGapPlan. The next article combines the run window, history summary, data gaps, and health report into a final operations checklist.