Quant Trading for Programmers 34: Detect Market Data Gaps
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.

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

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.DataGapandDataGapPlan.- 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-checkexample 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.
Follow ZiCode on WeChat
If this post was useful, you can follow later updates on WeChat as well.
X / Twitter
Follow @ax2_zicode
Faster technical notes, short thoughts, and new-post alerts are posted on X.
More in this column
- Quant Trading for Programmers 38: Index Daily Report Archives
- Quant Trading for Programmers 37: Generate Daily Run Results
- Quant Trading for Programmers 36: Shape The Daily Run Request
- Quant Trading for Programmers 35: Generate An Operations Checklist
- Quant Trading for Programmers 33: Summarize Paper-Trading Run History
- Quant Trading for Programmers 32: Archive Daily Run Results As JSON
- Quant Trading for Programmers 31: Add A Run Window To Daily Jobs
- Quant Trading for Programmers 30: Generate A Daily Run Health Report