Summary
BookClear carries a Clear Reason. We decode it into the struct and then never read it, so the one field on the market-data path that distinguishes a permanent removal from a temporary one is discarded.
What the spec defines
Market-by-Price spec v3.0.0, 0x41 BookClear, Clear Reason at offset 32:
| Value |
Name |
Meaning |
| 0 |
Unspecified |
No reason given |
| 1 |
Halt |
Instrument halted; book withdrawn |
| 2 |
SessionEnd |
Trading session closed |
| 3 |
VenueReset |
Venue cleared the book |
| 4 |
Settled |
Instrument settled or expired; book is permanently gone |
| 255 |
Other |
Venue-specific; documented out of band |
Settled is the strongest statement the protocol lets a publisher make about an instrument — the spec describes it as the claim a conforming subscriber never has to take back.
What we do with it
Decoded: src/ingest/codec_mbp.rs:374 parses it into BookClear.clear_reason (:175).
Dropped: the BookClear arm in src/ingest/processor.rs builds its BookDelta::Clear from clear_side, scope and from_price_raw only. clear_reason appears nowhere in the production path of that file — its only two occurrences are test fixtures, both setting it to 0.
So a publisher can tell us an instrument is permanently gone and we will apply the level removal and discard the reason.
Why it matters
Without it, the only removal signal we can act on is the manifest epoch change, which is coarser in two ways:
- Later. A departure is not observable until the publisher bumps
Manifest Seq and a definition cycle elapses (recommended 30s), where BookClear names it at the moment it happens.
- Weaker. Manifest absence says "not in the active set." It does not distinguish a settled instrument from one halted, closed for the session, or dropped for an operational reason.
Clear Reason does, and those cases warrant different handling: Settled can retire the entry, SessionEnd/Halt should keep it and mark it inactive.
Suggested direction
Consume clear_reason in the BookClear handler and route on it — Settled retires the instrument, SessionEnd/Halt mark it inactive without retiring, VenueReset/Unspecified/Other keep current behaviour. Receivers must accept any u8, so unknown values fall through to current behaviour rather than being treated as terminal.
Depends on #139 for where retirement state would live — that issue makes manifest-driven removal work at all; this one makes it prompt and lets it name a cause. Sequencing #139 first is probably right.
Note that the value of routing on this is bounded by publishers populating it accurately; a publisher that reports every departure under one reason gives us nothing to route on. Worth a conformance check on what actually arrives before building behaviour that assumes the distinction is real.
Summary
BookClearcarries aClear Reason. We decode it into the struct and then never read it, so the one field on the market-data path that distinguishes a permanent removal from a temporary one is discarded.What the spec defines
Market-by-Price spec v3.0.0,
0x41 BookClear,Clear Reasonat offset 32:Settledis the strongest statement the protocol lets a publisher make about an instrument — the spec describes it as the claim a conforming subscriber never has to take back.What we do with it
Decoded:
src/ingest/codec_mbp.rs:374parses it intoBookClear.clear_reason(:175).Dropped: the
BookCleararm insrc/ingest/processor.rsbuilds itsBookDelta::Clearfromclear_side,scopeandfrom_price_rawonly.clear_reasonappears nowhere in the production path of that file — its only two occurrences are test fixtures, both setting it to0.So a publisher can tell us an instrument is permanently gone and we will apply the level removal and discard the reason.
Why it matters
Without it, the only removal signal we can act on is the manifest epoch change, which is coarser in two ways:
Manifest Seqand a definition cycle elapses (recommended 30s), whereBookClearnames it at the moment it happens.Clear Reasondoes, and those cases warrant different handling:Settledcan retire the entry,SessionEnd/Haltshould keep it and mark it inactive.Suggested direction
Consume
clear_reasonin theBookClearhandler and route on it —Settledretires the instrument,SessionEnd/Haltmark it inactive without retiring,VenueReset/Unspecified/Otherkeep current behaviour. Receivers must accept anyu8, so unknown values fall through to current behaviour rather than being treated as terminal.Depends on #139 for where retirement state would live — that issue makes manifest-driven removal work at all; this one makes it prompt and lets it name a cause. Sequencing #139 first is probably right.
Note that the value of routing on this is bounded by publishers populating it accurately; a publisher that reports every departure under one reason gives us nothing to route on. Worth a conformance check on what actually arrives before building behaviour that assumes the distinction is real.