FIX PossDup / PossResend Duplicate-Suppression & Residual-Distortion Slippage Playbook

2026-04-07 · finance

FIX PossDup / PossResend Duplicate-Suppression & Residual-Distortion Slippage Playbook

Why this matters

A resend episode is not dangerous only because messages arrive late.

It is dangerous because the same economic event can now appear in multiple transport shapes:

If the execution stack collapses those possibilities with a naïve rule like:

then residual state becomes corrupted in subtle ways.

That corruption turns directly into slippage:

The operational problem is not merely “duplicate handling.” It is economic identity reconstruction under session uncertainty.


Failure mode in one line

During FIX resend/recovery, the application fails to distinguish transport duplicates from economically new events, so residuals drift away from truth and routing logic pays the difference as slippage.


Protocol facts that matter operationally

1) PossDupFlag (43) means possible retransmission on the same sequence-number identity

FIX defines PossDupFlag=Y as a possible retransmission of a message with that sequence number. It is not a license to ignore the message blindly. It means the receiver must decide whether the business event is already reflected locally.

2) PossResend (97) is different from PossDup

FIX distinguishes application-level possible resend from session-level retransmission. PossResend=Y means the message may contain information previously sent under another sequence number. So “new sequence number” does not imply “economically new event.”

3) OrigSendingTime (122) exists for a reason

When messages are resent, FIX carries the original send timestamp separately. That means the protocol expects receivers to reason about retransmission lineage rather than treating every arriving packet as new truth.

4) The receiver is responsible for duplicate handling

The FIX message-delivery model explicitly pushes duplicate interpretation to the receiving application. If the app cannot distinguish:

5) Duplicate ClOrdID can be valid or invalid depending on resend semantics

FIX order-state matrices explicitly show that a new order with a previously used ClOrdID plus PossResend=Y can require the broker to confirm the current order state, while a non-resend duplicate can be rejected as a duplicate order. That means duplicate-looking identifiers do not carry one universal meaning.

6) Ordered delivery assumptions break in messy real recovery paths

Engine implementations and session docs warn that during resend handling, messages may be queued, replayed, or even observed twice in different forms depending on configuration. A controller that assumes “first sighting wins” or “arrival order equals business order” will eventually mis-price its own residual.


Observable signatures

1) Residual jumps after resend windows with no corresponding market event

2) Fill totals disagree across hot path vs post-trade reconciliation

3) New sequence numbers produce no real economic change

4) PossDup=Y messages sometimes matter and sometimes do not

5) Duplicate-order rejects spike after session instability

6) TCA shows unexplained cleanup bursts after reconnects


Mechanical path to slippage

Step 1) A sequence gap, reconnect, or long-ack ambiguity happens

The session enters resend mode, or the application emits a PossResend=Y order because it is unsure whether the earlier order was processed.

Step 2) The same business event can now be represented more than once

For example:

Step 3) The application uses the wrong dedupe key

Common bad keys:

Step 4) Economic state diverges from transport state

The app starts to confuse:

Step 5) Residual control becomes wrong in one of two directions

Step 6) Router pays the tax

That tax appears as:


Core model

Define:

Then:

R_obs(t) = R_true(t) + epsilon_drop_real(t) - epsilon_double_apply(t) + epsilon_state_restate(t)

where:

A practical slippage decomposition is:

IS_dup ≈ D_miss + D_double + Q_churn + cleanup_cost + false_completion_cost

Interpretation:


Identity taxonomy: what must not be conflated

A) Transport identity

Questions like:

Useful fields:

B) Order identity

Questions like:

Useful fields:

C) Execution identity

Questions like:

Useful fields:

D) State-summary identity

Questions like:

Useful fields:

Most bugs happen when one layer is used as a substitute for another.


State ambiguity taxonomy

1) Blind PossDup discard

Every PossDup=Y message is thrown away.

Risk: a message not previously applied locally gets dropped, so real fills remain uncredited.

2) Fresh-sequence optimism

Any new MsgSeqNum is treated as new economic information.

Risk: PossResend=Y or status-style replay creates double application.

3) ClOrdID-only dedupe

Any repeated ClOrdID is treated as duplicate and invalid.

Risk: valid resend semantics are misread; current order state is reconstructed incorrectly.

4) ExecID-only dogmatism without correction/restatement rules

Everything with a repeated ExecID is dropped, regardless of context.

Risk: correction, restatement, or state-summary semantics get lost.

5) CumQty incrementalization bug

A summary message showing current CumQty is misread as “new fill of CumQty.”

Risk: fills are double-added from restated cumulative state.

6) Arrival-order literalism

First arrival is always believed; later replay/status confirmation is ignored.

Risk: local packet loss or partial pipeline failure leaves the system permanently wrong until batch reconciliation.


Feature set worth modeling

Session / recovery features

Duplicate-interpretation features

Residual-integrity features

Execution-impact features


Highest-risk situations

1) Manual or automated resend after long unacknowledged order windows

If the client suspects an order was not received and reissues with PossResend=Y, duplicate-order interpretation becomes economically critical.

2) Session recovery during active repricing

If fills, cancels, and replaces are already flowing, duplicate suppression errors compound quickly into residual distortion.

3) Multi-channel truth with hot path + drop copy

One channel may apply an event while another replays or restates it. If the ledger lacks clear economic identity, reconciliation becomes destructive rather than corrective.

4) Strategies that trade from cumulative state deltas

Anything that converts CumQty movement directly into new child urgency is vulnerable to summary-vs-incremental confusion.

5) Tight-deadline execution

A brief false residual near the end of a schedule can force aggressive cleanup flow.

6) Venues/brokers with uneven replay behavior

Different counterparties vary in how they replay application messages, use GapFill, or answer duplicate-order situations. One global dedupe policy is usually too crude.


Regime state machine

CLEAN

TRANSPORT_AMBIGUOUS

Trigger:

Actions:

ECONOMIC_ID_REBUILD

Trigger:

Actions:

SAFE_APPLY

Trigger:

Actions:

SAFE_IGNORE

Trigger:

Actions:

SAFE_SUMMARIZE

Trigger:

Actions:

SAFE_CONTAIN

Trigger:

Actions:


Control rules that actually help

1) Keep separate ledgers for transport events and economic events

A message can be new at the transport layer and old at the economic layer. Do not use one ledger to do both jobs.

2) Dedupe fills by economic identity, not just resend markers

PossDup=Y does not automatically mean “ignore,” and lack of PossDup does not automatically mean “apply.” Use ExecID / execution semantics / cumulative consistency checks.

3) Treat order-status summaries as summaries

If the message conveys current state rather than new execution, reconcile state without manufacturing incremental quantity.

4) Never use ClOrdID alone as the duplicate oracle

Duplicate ClOrdID may mean:

5) Add a residual-confidence score

When duplicate ambiguity rises, the system should reduce urgency confidence rather than respond with more aggression.

6) Quarantine ambiguous events instead of forcing binary apply/drop

If classification is incomplete, hold the event briefly and reconcile against cumulative state or secondary channels.

7) Attribute duplicate-suppression tax in TCA separately

Otherwise “random reconnect noise” keeps polluting volatility and venue-toxicity buckets.


TCA / KPI layer

Track these explicitly:

Segment by:


Validation approach

Replay / backtest questions

  1. How often did a PossDup=Y message represent an event not previously applied by the hot path?
  2. How often did a fresh sequence-number message with PossResend=Y carry no new economic information?
  3. How often were CumQty/LeavesQty summary fields accidentally converted into incremental fills?
  4. How much cleanup flow disappears if ambiguous events are quarantined and reconciled before urgency updates?
  5. Which counterparties produce the highest duplicate-order recovery tax?

Failure-injection drills

Simulate:

Shadow-mode comparator

Run the live controller against a shadow ledger that classifies messages into:

Compare residual drift and post-recovery markouts.


Common anti-patterns


Minimal implementation sketch

A robust stack usually needs:

  1. transport ledger

    • sequence number
    • resend markers
    • send-time lineage
    • replay window membership
  2. economic event ledger

    • canonical execution/state identities
    • exactly-once application markers
    • summary/restatement classification
  3. duplicate-order interpreter

    • understands PossResend context,
    • duplicate ClOrdID scenarios,
    • and status-confirm vs reject semantics
  4. residual-confidence model

    • discounts urgency when event classification confidence falls
  5. quarantine + reconcile path

    • short holding lane for ambiguous events,
    • resolved using cumulative state and secondary channels
  6. TCA hooks

    • measure dropped-real vs double-applied costs separately

Bottom line

Duplicate handling in FIX is not a parser detail.

PossDup, PossResend, OrigSendingTime, duplicate ClOrdID, and order-status confirmations together create a regime where transport novelty and economic novelty diverge. If the execution stack cannot tell them apart, it quietly corrupts residuals and then trades off that corrupted view.

That cost shows up as overfills, missed fills, retry churn, false completion, and cleanup aggression.

The fix is not “be stricter about duplicates.”

The fix is to separate transport identity from economic identity, classify summary vs incremental state correctly, and let residual confidence fall when the lineage is ambiguous.


References