Documentation of 8.4 flow

This commit is contained in:
2026-03-16 17:03:12 -03:00
parent e17675d973
commit 51ef6e182d

View File

@ -0,0 +1,216 @@
# Flow 8.4 — List Trading (Dealer Response)
## Overview
Flow 8.4 defines how a **dealer** responds to a client's Request for Quote (RFQ) through Tradeweb (TW) in a List Trading context. The key rule is:
> **The dealer NEVER sends an ExecutionReport (35=8). Only Tradeweb does.**
The dealer's role is limited to:
- Acknowledging messages (35=AI QuoteStatusReport, 35=BN ExecutionAck)
- Sending a price quote (35=S)
## Participants
| Abbreviation | Role |
|---|---|
| **TW** | Tradeweb — the platform that orchestrates the trade |
| **Dealer** | Us — responds to RFQs with quotes and acknowledges TW messages |
| **Client** | The counterparty requesting a quote (we never communicate with them directly) |
## Message Flow
```
TW Dealer
│ │
│ 1. QuoteRequest (35=R) │
│ ─────────────────────────────────────────> │
│ │
│ 2. QuoteStatusReport (35=AI) [ACK] │
│ <───────────────────────────────────────── │
│ │
│ 3. Quote (35=S) [price] │
│ <───────────────────────────────────────── │
│ │
│ 4. QuoteAck (35=CW) [ACCEPTED] │
│ ─────────────────────────────────────────> │
│ │
│ 5. QuoteResponse (35=AJ) [Hit/Lift] │
│ ─────────────────────────────────────────> │
│ │
│ 6. QuoteStatusReport (35=AI) [TRDREQACK] │
│ <───────────────────────────────────────── │
│ │
│ 7. ExecutionReport (35=8) [_LISTEND] │
│ ─────────────────────────────────────────> │
│ │
│ 8. ExecutionAck (35=BN) │
│ <───────────────────────────────────────── │
│ │
│ 9. ExecutionReport (35=8) [_TRDEND] │
│ ─────────────────────────────────────────> │
│ │
│ 10. ExecutionAck (35=BN) │
│ <───────────────────────────────────────── │
│ │
│ 11. ExecutionReport (35=8) [_TRDSUMM] │
│ ─────────────────────────────────────────> │
│ │
│ 12. ExecutionAck (35=BN) │
│ <───────────────────────────────────────── │
│ │
```
## Step-by-Step Detail
### Step 1 — QuoteRequest (35=R) — TW → Dealer
TW sends an RFQ on behalf of the client. Key fields:
| Tag | Field | Example | Notes |
|-----|-------|---------|-------|
| 131 | QuoteReqID | `LST_20260316_BYMA_CORI_NY1567246.1_1` | Always starts with `LST_` for List Trading |
| 66 | ListID | `NY1567246.1` | Identifies the list/inquiry |
| 48 | SecurityID | `040114HT0` | Bond identifier |
| 22 | SecurityIDSource | `1` (CUSIP) | Could also be `4` (ISIN) |
| 54 | Side | `2` (SELL) | The client's side — if client sells, dealer buys |
| 38 | OrderQty | `10000` | Quantity requested |
| 15 | Currency | `USD` | Settlement currency |
| 64 | SettlDate | `20260317` | Settlement date |
| 20073 | NegotiationType | `RFQ` | Must be RFQ for this flow |
**Validation:** The dealer must verify `LST_` prefix, non-empty `ListID`, and `NegotiationType=RFQ` before proceeding.
### Step 2 — QuoteStatusReport (35=AI) — Dealer → TW
The dealer acknowledges receipt of the QuoteRequest.
| Tag | Field | Value |
|-----|-------|-------|
| 131 | QuoteReqID | Same as received |
| 117 | QuoteID | Same as QuoteReqID |
| 297 | QuoteStatus | `0` (ACCEPTED) |
### Step 3 — Quote (35=S) — Dealer → TW
The dealer sends a price quote.
| Tag | Field | Example | Notes |
|-----|-------|---------|-------|
| 117 | QuoteID | Same as QuoteReqID | |
| 131 | QuoteReqID | Same as received | |
| 132 | BidPx | `99.60000000` | Set when client side is SELL (dealer bids) |
| 133 | OfferPx | `99.60000000` | Set when client side is BUY (dealer offers) |
| 44 | Price | `99.60000000` | The quote price |
| 423 | PriceType | `1` (Percentage) | |
| 537 | QuoteType | `211` (SEND_QUOTE) | |
### Step 4 — QuoteAck (35=CW) — TW → Dealer
TW confirms the quote was accepted.
| Tag | Field | Value |
|-----|-------|-------|
| 1865 | QuoteAckStatus | `1` (ACCEPTED) |
**Note:** If status is not ACCEPTED, the dealer should log a warning — the quote may have been rejected.
### Step 5 — QuoteResponse (35=AJ) — TW → Dealer
The client has decided to trade (Hit/Lift the quote).
| Tag | Field | Value | Notes |
|-----|-------|-------|-------|
| 694 | QuoteRespType | `1` (Hit/Lift) | `2` would be Counter — that's flow 8.5, not handled here |
| 693 | QuoteRespID | `..._TRDREQ` | Always ends with `_TRDREQ` |
### Step 6 — QuoteStatusReport (35=AI) — Dealer → TW
The dealer acknowledges the trade request (TRDREQACK).
| Tag | Field | Value |
|-----|-------|-------|
| 131 | QuoteReqID | Same as received |
| 693 | QuoteRespID | Same as received |
| 297 | QuoteStatus | `0` (ACCEPTED) |
### Step 7 — ExecutionReport (35=8) `_LISTEND` — TW → Dealer
TW signals that the due-in window for the list has closed.
| Tag | Field | Value | Notes |
|-----|-------|-------|-------|
| 17 | ExecID | `..._LISTEND-{timestamp}` | Contains `_LISTEND` |
| 150 | ExecType | `A` (PendingNew) | |
| 39 | OrdStatus | `A` (PendingNew) | |
**Dealer action:** Send ExecutionAck only. **Do NOT send an ExecutionReport back.**
### Step 8 — ExecutionAck (35=BN) — Dealer → TW
| Tag | Field | Value |
|-----|-------|-------|
| 37 | OrderID | Same as received |
| 17 | ExecID | Same as received |
| 1036 | ExecAckStatus | `1` (ACCEPTED) |
### Step 9 — ExecutionReport (35=8) `_TRDEND` — TW → Dealer
TW sends the trade result.
| Tag | Field | Value | Notes |
|-----|-------|-------|-------|
| 17 | ExecID | `..._TRDEND-{timestamp}` | Contains `_TRDEND` |
| 150 | ExecType | `F` (Trade) | The trade was executed |
| 39 | OrdStatus | `2` (Filled) | |
| 44 | Price | `99.6` | Final execution price |
**Dealer action:** Send ExecutionAck. Clean up internal trade tracking state.
### Step 10 — ExecutionAck (35=BN) — Dealer → TW
Same format as Step 8.
### Step 11 — ExecutionReport (35=8) `_TRDSUMM` — TW → Dealer
TW sends the full trade summary with additional details (parties, settlement info, trade IDs).
| Tag | Field | Value | Notes |
|-----|-------|-------|-------|
| 17 | ExecID | `..._TRDSUMM-{timestamp}` | Contains `_TRDSUMM` |
| 150 | ExecType | `F` (Trade) | |
| 39 | OrdStatus | `2` (Filled) | |
| 453 | NoPartyIDs | Party information | Counterparty details |
| 526 | SecondaryClOrdID | `TRD_...` | Tradeweb trade reference |
| 1003 | TradeID | `20260316.BYMA.CORI.230` | Unique trade identifier |
**Dealer action:** Send ExecutionAck. Log the summary for audit/reconciliation.
### Step 12 — ExecutionAck (35=BN) — Dealer → TW
Same format as Step 8.
## Code Reference
The implementation lives in `src/client/fix/manager.go`:
| Handler | Triggers on | Action |
|---------|------------|--------|
| `handleQuoteRequest` | 35=R | Sends 35=AI (ack) + 35=S (quote) |
| `handleQuoteAck` | 35=CW | Logs status |
| `handleQuoteResponse` | 35=AJ | Sends 35=AI (TRDREQACK) |
| `handleExecutionReport` | 35=8 | Sends 35=BN (ack) + routes by ExecID suffix |
| `sendQuoteStatusReport` | — | Builds 35=AI for QuoteRequest ack |
| `sendTradeRequestAck` | — | Builds 35=AI for TRDREQACK |
| `sendExecutionAck` | — | Builds 35=BN for ExecutionReport ack |
### ExecID Routing in `handleExecutionReport`
```
ExecID contains "_LISTEND" → Log only, await trade result
ExecID contains "_TRDEND" → Log + cleanup trade from memory
ExecID contains "_TRDSUMM" → Log trade summary
ExecType = F (fallback) → Log generic trade result
```
The order matters: ExecID suffix checks run before ExecType checks, because `_TRDEND` and `_TRDSUMM` both have `ExecType=F`.