What FIX actually is
FIX (Financial Information eXchange) is the messaging protocol the institutional side of trading runs on. Plain text tag=value messages over a persistent TCP session, with strict ordering, sequence numbers and resend logic. Every bank, ECN and decent LP speaks it.
Most brokerage integrations use FIX 4.4. Newer FIX 5.0 SP2 exists but the LP universe has standardised on 4.4 for spot FX, metals, indices and CFDs. Don't let anyone sell you a custom binary protocol unless you have a very specific reason.
The two sessions you'll always provision
- Price (market data) session — one-way feed of top-of-book or full depth quotes for the symbols you're entitled to. High message rate, no orders.
- Trade (order) session — bi-directional. You send NewOrderSingle (35=D), the LP responds with ExecutionReports (35=8). Lower message rate, latency-critical.
Some setups split price further (one session per asset class) or add a separate post-trade session for confirmations and allocations. Ask your LP for their session topology upfront.
The message types that actually matter
- Logon (35=A) / Logout (35=5) — session lifecycle. Heartbeat interval (tag 108) is usually 30s.
- Heartbeat (35=0) / TestRequest (35=1) — keepalives. If you miss two heartbeats, assume the session is dead and reconnect.
- MarketDataRequest (35=V) — subscribe to symbols. Watch the symbol-count limits per session.
- MarketDataSnapshot/IncrementalRefresh (35=W / 35=X) — the actual quotes.
- NewOrderSingle (35=D) — your order. Get TimeInForce (59), OrdType (40) and ExecInst (18) right on day one.
- ExecutionReport (35=8) — fill, partial fill, reject, cancel-ack. Drive your ledger off this, not your own optimistic state.
- OrderCancelRequest (35=F) and OrderCancelReplaceRequest (35=G) — cancel and modify. Reject-handling is where bugs hide.
- BusinessMessageReject (35=j) — anything semantically wrong (unknown symbol, bad price). Log every one.
Latency: the number that gets oversold
"Sub-millisecond execution" in marketing copy usually means the LP's matching engine latency, not the round-trip you'll see. Measure end-to-end:
- Network leg — your gateway to the LP gateway. Cross-connect in the same data centre (Equinix LD4 for London FX, NY4 for US, TY3 for Tokyo) gets you single-digit ms. A VPN over public internet from Dubai to London is 80–120ms before anyone processes anything.
- LP processing — usually 0.1–2ms.
- Your bridge processing — risk checks, symbol mapping, persistence. Often the slowest leg.
Ask for histogram latency stats, not averages. The 99th percentile during the NFP minute is what kills you, not the median on a quiet Tuesday.
UAT, certification and go-live
This is a standard four-step path:
- Spec exchange — LP sends you their FIX rules of engagement (ROE). Read it cover to cover; the gotchas are always in the symbol mapping and the supported tags appendix.
- UAT connectivity — credentials, IPs whitelisted, TCP handshake, first Logon. Allow 1–2 weeks for firewall and security reviews on both sides.
- Functional certification — the LP runs a script of test orders against your gateway: market buy, limit sell, partial fill, reject, cancel, modify, mass-cancel on disconnect. They sign off when every scenario produces the expected ExecutionReport flow.
- Go-live — production credentials issued, low-limit trading window for the first day, then full limits. Always go live on a Monday or Tuesday — never Friday, never before a central-bank week.
From kick-off to live, a clean integration is 4–8 weeks. Add 50% if either side has compliance changes in flight.
Throttling, limits and disconnect behaviour
- Order rate limits — usually 50–200 orders/sec per session, but symbol-specific caps are common on illiquid CFDs.
- Symbol count per market data session — sometimes capped at 100–500. Plan multiple price sessions if you carry a wide instrument universe.
- Cancel-on-disconnect — does the LP auto-cancel resting orders if your trade session drops? Get the answer in writing. The default behaviour varies and the wrong answer costs real money during an outage.
- Sequence number reset policy — daily reset at a defined cutover, or persistent across days? Both work, but your engine has to match.
Contract clauses worth pushing on
- Last-look — disclosed, with hold-time and reject-rate published per symbol. "No last-look" sounds great but is rare in spot FX and not always to your benefit.
- Slippage policy — symmetric (both directions) or asymmetric (only against you). Symmetric is the only acceptable answer for a regulated brokerage downstream.
- Failover and DR — secondary gateway IPs, RTO/RPO commitments, planned-maintenance windows.
- Credit and margin — initial margin %, variation margin call timing, intra-day vs end-of-day netting.
- Termination and data portability — can you take your trade history and open positions to a new LP cleanly?
The pre-go-live checklist
- Sequence number persistence tested across forced disconnect.
- Heartbeat and TestRequest loop verified at the agreed interval.
- All ExecutionReport states (New, PartialFill, Fill, Cancelled, Rejected, Expired) handled in your ledger.
- Symbol map reconciled against the LP's master file, including pip size, tick size and minimum trade size.
- Reject reasons mapped to user-facing messages, not raw text codes.
- Reconciliation job comparing your end-of-day positions against the LP's daily statement.
- Monitoring: session up/down, message rate, latency percentile, reject rate, drift from quote feed.
- Runbook for the three common incidents: session drop, stale quote, mass reject.
Related reading
- A-book vs B-book vs hybrid: how brokers handle your flow
- Spreads, swaps, margins and slippage: the commercials checklist
- For brokers: covering, liquidity and FIX connectivity
Disclaimer: Educational only. I work for a regulated broker (Amana). FIX behaviour and contract terms vary between liquidity providers — confirm specifics with your counterparty.