Providing Quotes
Answer FIX RFQs as a maker, follow quote acceptance, and confirm or cancel during last look.
This walkthrough covers the maker’s side of an RFQ. See RFQs for the trading concepts and Requesting Quotes for the taker’s side. Start with an order-entry session established through FIX Sessions and Recovery.
The examples show decoded FIX fields; your FIX engine supplies the header and trailer. Copy <rfq-id> and <ticker> from the RFQ solicitation, replace <account-id> with your account ID, and copy <quote-id> from the exchange’s answer to your quote. Example timestamps illustrate the FIX timestamp format; use the actual deadlines received. Prices and quantities follow Markets and Trading.
Read an RFQ Solicitation
An RFQ soliciting your session arrives as QuoteRequest(R). For a taker seeking to buy 100 contracts, the maker is asked to sell:
MsgType(35)=QuoteRequest(R)
QuoteReqID(131)=<rfq-id>
NoRootPartyIDs(1116)=1
RootPartyID(1117)=<requester-id>
RootPartyIDSource(1118)=PROPRIETARY(D)
RootPartyRole(1119)=ENTERING_TRADER(36)
NoRelatedSym(146)=1
Symbol(55)=<ticker>
Side(54)=SELL(2)
OrderQty(38)=100
QuoteType(537)=TRADEABLE(1)
ValidUntilTime(62)=20261103-21:01:00.000
For an ad-hoc multi-leg RFQ, the solicitation carries both the exchange-generated combination ticker and the component legs:
MsgType(35)=QuoteRequest(R)
QuoteReqID(131)=<rfq-id>
NoRootPartyIDs(1116)=1
RootPartyID(1117)=<requester-id>
RootPartyIDSource(1118)=PROPRIETARY(D)
RootPartyRole(1119)=ENTERING_TRADER(36)
NoRelatedSym(146)=1
Symbol(55)=<combination-ticker>
Side(54)=SELL(2)
OrderQty(38)=100
QuoteType(537)=TRADEABLE(1)
ValidUntilTime(62)=20261103-21:01:00.000
NoLegs(555)=2
LegSymbol(600)=<first-leg-ticker>
LegSide(624)=AS_DEFINED(B)
LegSymbol(600)=<second-leg-ticker>
LegSide(624)=OPPOSITE(C)
<combination-ticker> names the whole combination; the leg placeholders identify its component markets. NoLegs(555) is a message-level group, outside NoRelatedSym(146). Leg directions are relative to the combination: LegSide(624)=AS_DEFINED(B) follows its direction and LegSide(624)=OPPOSITE(C) takes the opposite direction.
QuoteReqID(131) is the exchange-assigned RFQ identifier. Use it in every quote, confirmation, and cancellation for this RFQ. Side(54) is the side you are asked to quote, opposite the taker’s intended trade. If the solicitation omits the side, it invites either side; create separate single-sided Quote(S) messages to quote both.
When present, RootPartyID(1117) identifies the requester by an opaque participant ID. It does not disclose the taker’s user or account ID. The solicitation omits the taker’s account and initial request identifier.
| RFQ shape | Next step |
|---|---|
OrderQty(38) |
Price the requested contract quantity. |
CashOrderQty(152) |
Read it as a dollar budget and choose the contract quantity you will quote at your price. |
NoLegs(555) |
Read every leg and its relative direction. Copy the generated ticker from the solicitation into your quote, even if that market is not yet in the catalog. |
The solicitation’s ValidUntilTime(62) is the RFQ deadline. Quote while it remains open, and use the quote deadline the exchange returns for the live price you create. A request near its deadline can be rejected rather than given a usable quoting window.
Create a Quote
Send Quote(S) for the illustrated sell side:
MsgType(35)=Quote(S)
QuoteReqID(131)=<rfq-id>
QuoteMsgID(1166)=maker-quote-1
Symbol(55)=<ticker>
Side(54)=SELL(2)
OfferPx(133)=0.55
OfferSize(135)=100
Account(1)=<account-id>
QuoteType(537)=TRADEABLE(1)
QuoteMsgID(1166)=maker-quote-1 is the identifier you assign to this quote. The exchange assigns a separate QuoteID(117). Keep the two together: your Quote(S) and QuoteStatusReport(AI) copies echo your assigned identifier, while the taker’s copies omit it. Multiple quotes can be live on the same RFQ and side, so the RFQ ID alone does not identify the quote you created.
For a buy quote, use Side(54)=BUY(1) with BidPx(132) and BidSize(134). For a sell quote, use Side(54)=SELL(2) with OfferPx(133) and OfferSize(135). Each Quote(S) describes one side; do not include the other side’s price or size. You can supply OrderQty(38) instead of the side’s size field; if you include both, their quantities must agree.
| Quote answer | Next step |
|---|---|
QuoteStatusReport(AI) with QuoteStatus(297)=PENDING(10) |
Record the exchange quote ID and correlate it with your QuoteMsgID(1166). Pending does not establish that the quote is available to the taker. |
| Quote(S) from the exchange | The quote is live. Confirm its side, price, contract quantity, and deadline; follow its later statuses. |
QuoteStatusReport(AI) with QuoteStatus(297)=REJECTED(5) |
Inspect Text(58) and the echoed identifiers. Do not assume the quote became live. A rejected quote can lack an exchange quote ID. |
Use the exchange quote ID for later actions, not your QuoteMsgID(1166). QuoteStatus(297)=PENDING(10) acknowledges receipt of your quote; Quote(S) from the exchange confirms that the quote is live.
Respond During Last Look
When the taker accepts your quote, the exchange sends QuoteStatusReport(AI) with QuoteStatus(297)=PENDING_END_TRADE(19):
MsgType(35)=QuoteStatusReport(AI)
QuoteID(117)=<quote-id>
QuoteReqID(131)=<rfq-id>
QuoteMsgID(1166)=maker-quote-1
QuoteStatus(297)=PENDING_END_TRADE(19)
Symbol(55)=<ticker>
Side(54)=SELL(2)
ValidUntilTime(62)=20261103-21:00:13.000
ValidUntilTime(62) now states the last-look deadline, replacing the earlier quote deadline. Decide promptly: confirm if you will proceed or cancel the quote if you will not. Do not wait for the RFQ’s original deadline, and do not send a confirmation before a taker acceptance has opened last look.
To confirm, send QuoteResponse(AJ) with QuoteRespType(694)=ACCEPT(11):
MsgType(35)=QuoteResponse(AJ)
QuoteRespID(693)=maker-confirm-1
QuoteRespType(694)=ACCEPT(11)
QuoteID(117)=<quote-id>
QuoteReqID(131)=<rfq-id>
Symbol(55)=<ticker>
The maker confirms the identified quote; it does not create the taker’s acceptance order or choose a new trade size here. The taker opens last look using QuoteRespType(694)=HIT_LIFT(1), while the maker confirms using QuoteRespType(694)=ACCEPT(11).
| Last-look result | Next step |
|---|---|
QuoteStatus(297)=ACCEPTED(0) |
Last look is complete. Read ExecutionReport(8) for fills or a rejection to determine the trading outcome. |
QuoteStatus(297)=CANCELED(17) |
Last look ended without a trade. Remove the quote from your live quotes; no ExecutionReport(8) is sent for this attempt. |
QuoteStatus(297)=REJECTED(5) with Text(58)=no lift is awaiting confirmation on this quote |
The quote is not awaiting confirmation. Check its latest reported status before acting again; this rejection does not cancel the quote. |
After a canceled last look, the RFQ can solicit again while its deadline permits. The exchange does not repeat the RFQ solicitation, and other quotes can remain live.
Cancel a Quote
Use QuoteCancel(Z) to cancel your identified quote, whether it is still live or already in last look:
MsgType(35)=QuoteCancel(Z)
QuoteID(117)=<quote-id>
QuoteReqID(131)=<rfq-id>
QuoteCancelType(298)=CANCEL_QUOTE_SPECIFIED_IN_QUOTEID(5)
Symbol(55)=<ticker>
| Cancellation result | Next step |
|---|---|
QuoteStatusReport(AI) with QuoteStatus(297)=CANCELED(17) |
Remove the quote from your live state. Both sides receive its canceled status. |
QuoteStatusReport(AI) with QuoteStatus(297)=REJECTED(5) or QuoteStatus(297)=QUOTE_NOT_FOUND(9) |
Inspect Text(58) and reconcile its latest status; sending a cancellation is not confirmation that it ended. |
To change a live price or size, cancel the old quote and create another with a new QuoteMsgID(1166). Sending another Quote(S) creates a separate quote; it does not amend the existing exchange quote ID.
Reconcile the Execution
QuoteStatusReport(AI) with QuoteStatus(297)=ACCEPTED(0) confirms the maker’s decision, not a completed trade. Follow ExecutionReport(8) for the resulting order and its fills. A trade uses ExecType(150)=TRADE(F); a rejected execution means the attempted order did not trade. Execution can fail after confirmation, including for insufficient credit or an expired execution deadline.
For an order originating from your quote, both QuoteMsgID(1166)=maker-quote-1 and ClOrdID(11)=maker-quote-1 identify its origin. Save the report’s separate exchange-assigned OrderID(37). The maker confirmation’s QuoteRespID(693)=maker-confirm-1 does not replace those order identifiers.
The taker can accept less than your quoted quantity; execution reports state the quantity actually traded. A completed partial acceptance ends the RFQ and does not leave the unused quoted quantity live. Follow your own order’s reports rather than inferring your fill from the accepted quote status: a confirmed negotiated order can also trade against better-priced resting liquidity, leaving the quoted maker’s order canceled.
Placing Orders explains how to read execution quantities and handle retransmissions. Reconcile Fill Commissions explains cumulative and per-fill fees; a quote status carries neither proof of a fill nor a fee amount.
Retire Quotes and Recover a Session
The exchange reports these quote endings in QuoteStatusReport(AI). Use QuoteReqID(131) and QuoteID(117) to identify the affected quote:
| Quote status | Next step |
|---|---|
QuoteStatus(297)=EXPIRED(7) |
Stop treating the quote as executable. |
QuoteStatus(297)=PASS(11) |
The taker passed. Retire that quote; the RFQ can still accept another quote while open. |
QuoteStatus(297)=REMOVED_FROM_MARKET(6) |
Another quote’s confirmation ended this quote’s availability. |
Disconnecting does not cancel your quotes. Order-entry cancel-on-disconnect applies to orders, so send QuoteCancel(Z) for each live quote when you intend to stop quoting.
After reconnecting, follow FIX Sessions and Recovery to recover missed QuoteStatusReport(AI) and ExecutionReport(8) messages. A recovered QuoteStatusReport(AI) with QuoteStatus(297)=PENDING_END_TRADE(19) can describe a last-look deadline that has already passed; reconcile later reports before acting on it.