Placing Orders
Place, follow, amend, and cancel a FIX order, and reconcile fills and commissions.
Start with a ticker from Discovering Markets and complete the order-entry logon described in FIX Sessions and Recovery. See Order Entry for the trading concepts and Markets and Trading for YES-side pricing and units.
The examples show decoded FIX fields. Your FIX engine encodes the numeric tags and raw values and supplies the header and trailer. Replace <ticker> and <account-id> with your market ticker and account ID. In reports and later requests, <order-id> means the exchange-assigned ID from the order’s first acceptance; execution ID placeholders represent distinct exchange-assigned IDs. The example follows a buy order through partial fills, an amendment, and cancellation of the remainder. Its fills and fee amounts illustrate accounting, not a fee schedule or an expected trading outcome.
Place an Order
Send NewOrderSingle(D) to buy 100 contracts at a limit price of $0.55. This example is post-only: choose a price on the market’s tick that will rest rather than cross the current offer.
MsgType(35)=NewOrderSingle(D)
ClOrdID(11)=order-1
Account(1)=<account-id>
Symbol(55)=<ticker>
Side(54)=BUY(1)
OrderQty(38)=100
OrdType(40)=LIMIT(2)
Price(44)=0.55
TimeInForce(59)=GOOD_TILL_CANCEL(1)
ExecInst(18)=PARTICIPATE_DONT_INITIATE(6)
ClOrdID(11) is the ID you assign to a request. Use a distinct value for each new order, amendment, and cancellation. Keep ClOrdID(11) alongside the exchange-assigned OrderID(37) as reports arrive; later requests identify the order by OrderID(37).
The exchange answers with ExecutionReport(8). Sending the request does not establish acceptance. On acceptance, save OrderID(37) and confirm the reported OrderQty(38), Price(44), and TimeInForce(59).
| Placement result | Next step |
|---|---|
ExecType(150)=NEW(0) |
Record the accepted order and continue following its reports. Acceptance does not establish that anything filled. |
ExecType(150)=REJECTED(8) |
Match ClOrdID(11) to the request and inspect OrdRejReason(103) and Text(58) before correcting and retrying. A rejection before an order is assigned uses OrderID(37)=NONE. |
| No confirmed outcome after connection loss | Recover the session and reconcile reports before sending another order; follow FIX Sessions and Recovery. |
To size a new order by a dollar budget, replace OrderQty(38)=100 with CashOrderQty(152)=55; send exactly one quantity form. The exchange converts the budget into contracts, and the report’s OrderQty(38) states the resulting contract quantity. Do not treat the cash budget as a contract count.
For an order that must execute completely on arrival, use TimeInForce(59)=FILL_OR_KILL(4) and omit the post-only instruction. A fill-or-kill order that cannot fill completely is canceled. For an order that may trade on arrival and rest any remainder, use TimeInForce(59)=GOOD_TILL_CANCEL(1) and omit the post-only instruction.
Self-trade prevention remains active in either case. SelfMatchPreventionInstruction(8000)=CANCEL_INCOMING(N), also the default when omitted, rejects an incoming order that would self-trade. SelfMatchPreventionInstruction(8000)=CANCEL_RESTING(O) instead cancels the conflicting resting order and lets the incoming order continue matching.
Follow the Order and Its Fills
Read ExecType(150) as the action reported and OrdStatus(39) as the resulting order state. Both partial and complete fills use ExecType(150)=TRADE(F).
| Report | Next step |
|---|---|
ExecType(150)=TRADE(F) with OrdStatus(39)=PARTIALLY_FILLED(1) |
Record the fill; the order still has an unfilled remainder. |
ExecType(150)=TRADE(F) with OrdStatus(39)=FILLED(2) |
Record the fill and mark the order complete. |
ExecType(150)=CANCELED(4) |
Stop treating the unfilled remainder as working. Retain earlier fills. |
ExecType(150)=EXPIRED(C) |
Stop treating the unfilled remainder as working. Retain earlier fills. |
For example, a 40-contract fill at $0.55 can leave the order in this state:
MsgType(35)=ExecutionReport(8)
OrderID(37)=<order-id>
ClOrdID(11)=order-1
ExecID(17)=<execution-id-1>
ExecType(150)=TRADE(F)
OrdStatus(39)=PARTIALLY_FILLED(1)
Account(1)=<account-id>
Symbol(55)=<ticker>
Side(54)=BUY(1)
OrderQty(38)=100
Price(44)=0.55
TimeInForce(59)=GOOD_TILL_CANCEL(1)
LeavesQty(151)=60
CumQty(14)=40
AvgPx(6)=0.55
LastQty(32)=40
LastPx(31)=0.55
Commission(12)=0.20
CommType(13)=ABSOLUTE(3)
LastCommission(8001)=0.20
Use LastQty(32) and LastPx(31) for this execution. CumQty(14) and AvgPx(6) describe the order’s fills so far, while LeavesQty(151) describes its remaining quantity. Update the order from those totals instead of adding each cumulative quantity again. The report’s OrderQty(38) and Price(44) are the order’s terms, not this execution’s quantity and price.
Use ExecID(17) to correlate executions. When no execution ID is available, the report uses ExecID(17)=NONE; that value is not a unique fill ID. Apply the recovery and duplicate-handling rules before recording a retransmitted execution as another fill.
Amend the Order
If the order remains open after the illustrated fill, reduce its total quantity to 80 with OrderCancelReplaceRequest(G):
MsgType(35)=OrderCancelReplaceRequest(G)
OrigClOrdID(41)=order-1
ClOrdID(11)=order-2
OrderID(37)=<order-id>
Symbol(55)=<ticker>
Side(54)=BUY(1)
OrdType(40)=LIMIT(2)
OrderQty(38)=80
ExecInst(18)=PARTICIPATE_DONT_INITIATE(6)
The new quantity is the total, including contracts already filled. If nothing else fills before this amendment takes effect, 40 contracts remain. Omit Price(44) to retain the current limit; a price-only amendment can instead omit OrderQty(38). Restate ExecInst(18)=PARTICIPATE_DONT_INITIATE(6) to retain post-only protection: omission drops that protection. An amendment does not change the order’s time in force.
OrderID(37) identifies the order. OrigClOrdID(41) is optional correlation, not an alternative lookup key. When you send it, use the order’s most recently accepted ClOrdID(11).
Once the amendment is accepted, its ClOrdID(11) replaces the order’s previous ClOrdID(11). In this example, the order changes from ClOrdID(11)=order-1 to ClOrdID(11)=order-2, while OrderID(37) stays the same. Subsequent fill reports carry ClOrdID(11)=order-2; use OrigClOrdID(41)=order-2 on the next amendment or cancellation. Wait for the acceptance report before updating your stored identifier.
| Amendment result | Next step |
|---|---|
ExecutionReport(8) with ExecType(150)=REPLACED(5) |
Update the order’s current ClOrdID(11) and record the reported terms and quantities. OrdStatus(39) describes the resulting state; it does not use a separate replaced state. |
| OrderCancelReject(9) | Match ClOrdID(11)=order-2, inspect CxlRejReason(102) and Text(58), and retain the last confirmed order state. |
| A fill while the amendment is in flight | Record the fill and use the amendment’s eventual answer to determine the remaining working quantity. |
On an accepted amendment or cancellation, OrigClOrdID(41) reports the actual previous ClOrdID(11), even if your request omitted it or supplied a stale value. On OrderCancelReject(9), it echoes the value you supplied, or is omitted if you supplied none.
Reconcile Fill Commissions
Suppose another 20 contracts fill after the amendment. The order now has 60 filled and 20 remaining, and the fill’s report carries ClOrdID(11)=order-2. For illustrative fees of $0.20 on the first fill and $0.10 on the second:
| Fill | This fill’s fee | Order’s cumulative fee |
|---|---|---|
| First 40 contracts | LastCommission(8001)=0.20 |
Commission(12)=0.20 |
| Next 20 contracts | LastCommission(8001)=0.10 |
Commission(12)=0.30 |
On this API, Commission(12) is the order’s running total. Replace your stored cumulative fee with the latest reported total; adding the two totals in this example would incorrectly produce $0.50. LastCommission(8001) is a custom field for the individual fill’s fee. Both figures are dollar amounts, not rates; CommType(13)=ABSOLUTE(3) accompanies the cumulative amount. A negative amount represents a rebate.
Fees appear only on fill reports. Either fee figure can be absent independently; absence does not mean zero. Preserve the last known cumulative total when it is omitted, and treat an omitted per-fill fee as unavailable. Do not substitute the cumulative amount for the missing individual fee. An acceptance, amendment, or cancellation report omits fee fields and does not reset the order’s accumulated fees.
Cancel the Remaining Order
If the remaining 20 contracts are still working, send OrderCancelRequest(F) using a new ClOrdID(11):
MsgType(35)=OrderCancelRequest(F)
OrigClOrdID(41)=order-2
ClOrdID(11)=order-3
OrderID(37)=<order-id>
Symbol(55)=<ticker>
Side(54)=BUY(1)
| Cancellation result | Next step |
|---|---|
ExecutionReport(8) with ExecType(150)=CANCELED(4) |
Mark the order canceled. With no intervening fills in this example, CumQty(14)=60 remains filled and LeavesQty(151)=0 means nothing remains working. |
| OrderCancelReject(9) | Match ClOrdID(11)=order-3 and inspect CxlRejReason(102) and Text(58). The rejection does not undo earlier fills or prove the order is still open; reconcile any other reports already received. |
| A fill while cancellation is in flight | Record it. Sending a cancellation does not establish that the remainder was canceled. |
OrderCancelReject(9) uses CxlRejResponseTo(434)=ORDER_CANCEL_REQUEST(1) for cancellation and CxlRejResponseTo(434)=ORDER_CANCEL_REPLACE_REQUEST(2) for amendment. Its OrdStatus(39)=REJECTED(8) describes the rejected request; do not overwrite the order’s last confirmed state with that value.
There is no order-status request or bulk cancellation message on this FIX API. Follow FIX Sessions and Recovery to recover reports after disconnecting; contact support if the recovered reports leave an order’s state unresolved.