Documentation of 8.4 flow
This commit is contained in:
216
docs/FLOW_8_4_LIST_TRADING.md
Normal file
216
docs/FLOW_8_4_LIST_TRADING.md
Normal 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`.
|
||||
Reference in New Issue
Block a user