Skip to content

fix: encode halt/resume via official SecurityStatus_3 semantics - #588

Closed
pedrosakuma wants to merge 2 commits into
mainfrom
fix/583-halt-security-status-3
Closed

fix: encode halt/resume via official SecurityStatus_3 semantics#588
pedrosakuma wants to merge 2 commits into
mainfrom
fix/583-halt-security-status-3

Conversation

@pedrosakuma

Copy link
Copy Markdown
Owner

Fixes #583

Problem

Halt/resume UMDF encoding used out-of-domain securityTradingEvent marker values (1/2) not present in the vendored B3 market-data schema (schemas/b3-market-data-messages-2.2.0.xml). Additionally, a late subscriber joining mid-session while an instrument was halted had no way to learn its current trading status from the snapshot channel — only future incrementals carried it.

Fix

  1. Encode fix (UmdfFrameBuilder.cs, ChannelDispatcher.Sinks.cs):
    • Halt → securityTradingStatus=FORBIDDEN(18), securityTradingEvent=SECURITY_STATUS_CHANGE(101).
    • Resume → restored pre-halt securityTradingStatus, securityTradingEvent=SECURITY_REJOINS_SECURITY_GROUP_STATUS(102).
  2. Halt persistence across restarts: already implemented in feat(host): single-stock halt/resume HTTP API + UMDF status frame #322 (EngineStateSnapshot.Halts). No changes needed; verified via existing tests.
  3. Snapshot/recovery publication (SnapshotPacketBuilder.cs, ISnapshotBookSource.cs, SnapshotRotator.cs): every snapshot now always emits a trailing SecurityStatus_3 packet after the header/orders packets, reporting the instrument's current status (FORBIDDEN if halted, else current TradingPhase) with securityTradingEvent=NULL(255) since it's a point-in-time report, not a transition event.

Testing

  • Updated all existing wire-encoder / core / persistence tests for the new WriteSnapshot/GetPacketCount contract (trailing packet always present).
  • Added HaltedInstrument_TrailingStatusPacket_ReportsForbidden (SnapshotRotatorTests.cs) — dedicated round-trip test asserting a halted instrument's snapshot trailing packet reports FORBIDDEN.
  • Full solution build/test in Release: all projects pass (isolated runs; two flaky cross-project-parallelism failures unrelated to this change, confirmed pre-existing and pass individually/in full Host.Tests-only run).
  • dotnet format --verify-no-changes clean.

No changes to schemas/ or generated SBE bindings — this only fixes usage of already-defined official enum values.

pedrosakuma and others added 2 commits July 27, 2026 22:23
Halt/resume UMDF encoding previously used out-of-domain marker values
(securityTradingEvent=1/2) that are not defined in the vendored B3
market-data schema. This replaces them with the official semantics:

- Halt: securityTradingStatus=FORBIDDEN(18),
  securityTradingEvent=SECURITY_STATUS_CHANGE(101).
- Resume: restored pre-halt securityTradingStatus,
  securityTradingEvent=SECURITY_REJOINS_SECURITY_GROUP_STATUS(102).

Also closes the snapshot/recovery gap identified in #583: a late
subscriber joining mid-session previously had no way to learn an
instrument's current trading status (e.g. FORBIDDEN while halted) from
the snapshot channel alone. SnapshotPacketBuilder now always emits a
trailing SecurityStatus_3 packet after every snapshot's header/orders
packets, using securityTradingEvent=NULL(255) since it's a
point-in-time report, not a transition event. ISnapshotBookSource
gained GetSecurityTradingStatus(securityId), backed by
MatchingEngineSnapshotSource (FORBIDDEN while halted, else the current
TradingPhase).

Halt state persistence across engine restarts already existed (added
in #322 via EngineStateSnapshot.Halts) and required no further changes.

Updated all affected wire-encoder and core tests for the new
WriteSnapshot/GetPacketCount contract, and added a dedicated
HaltedInstrument_TrailingStatusPacket_ReportsForbidden test asserting
the FORBIDDEN byte is present on a halted instrument's snapshot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gpt-5.5 review of PR #588 caught: the new trailing snapshot status
packet was passing lastRptSeq as SecurityStatus_3.rptSeq, but the
vendored schema explicitly documents this field as "Sequence number
per instrument update. (Zeroed in snapshot feed)". Fixed to always
write rptSeq=0 in the trailing packet, and added a test asserting this
holds even when the header's LastRptSeq is non-null.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pedrosakuma
pedrosakuma marked this pull request as ready for review July 27, 2026 22:36
@pedrosakuma

Copy link
Copy Markdown
Owner Author

Superseded by #589, which was merged and already resolved issue #583 (SecurityStatus_3 halt/resume semantics + snapshot recovery publication). Closing to avoid duplicate/conflicting work.

@pedrosakuma
pedrosakuma deleted the fix/583-halt-security-status-3 branch July 28, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(umdf): encode administrative halt with official SecurityStatus_3 semantics

1 participant