Skip to main content

FIX Protocol Integration

FIX is how most institutional order flow and a large share of institutional market data moves. It is a stateful, sequenced, session-oriented protocol over raw TCP. The chart never speaks it. Your backend does, and publishes the result over the gateway.

Why FIX terminates server-side

A FIX session is a long-lived, ordered, resumable conversation between two named counterparties. Sequence numbers persist across reconnects and often across days. A browser tab cannot own that state, and a SenderCompID credential in a browser is a credential you have published.

One session is shared by every user of your product. Per-user identity is carried inside your gateway, not inside FIX.

Session layer

Before any business message flows, the session must be established and kept alive. Your engine handles this; you configure it.

The rules that matter operationally:

  • Every message carries MsgSeqNum (34). A gap is a protocol error, not a hint — the engine must issue a ResendRequest and stop processing until the gap is filled.
  • Sequence numbers reset only when both sides agree, usually at a scheduled daily session boundary or via ResetSeqNumFlag (141=Y) on logon.
  • The message store must be durable. An engine that loses its store cannot recover a session, and the counterparty will refuse the logon.
  • HeartBtInt (108) is negotiated at logon. A missed heartbeat plus an unanswered TestRequest means the session is dead and must be re-established.

Use a proven engine rather than parsing tag=value yourself: QuickFIX/J for the JVM, quickfix-go, QuickFIX/n for .NET, or a commercial engine where latency and support obligations justify it. Newer venues may offer SBE or FAST encodings instead of classic tag=value; the session semantics above are unchanged.

Market data over FIX

A market data session is a subscription conversation: you request, they snapshot, then they stream increments.

Request fields

TagFieldUse
262MDReqIDCorrelates every response with this subscription
263SubscriptionRequestType0 snapshot, 1 snapshot plus updates, 2 unsubscribe
264MarketDepth1 top of book, N levels, 0 full book
265MDUpdateType0 full refresh, 1 incremental
269MDEntryType0 bid, 1 offer, 2 trade, 4 open, 5 close, 7 high, 8 low

Mapping entries to SDK types

Each MDEntryType lands in a different chart contract.

MDEntryType (269)CarriesBecomes
0 Bid, 1 Offer with depth 1MDEntryPx (270), MDEntrySize (271)Quote.bid / Quote.ask
0 Bid, 1 Offer with depth > 1Price levels per sideSdkMarketDepth.bids / .asks as DepthLevel
2 TradePrint price, size, timeTimeAndSalesEntry, and the aggregated OHLCV bar
4, 5, 7, 8Session open, close, high, lowQuote.open, .previousClose, .high, .low

MDUpdateAction (279) drives book maintenance: 0 inserts a level, 1 changes its size, 2 deletes it. Apply deltas to a book you hold in the gateway and publish whole normalized frames to the chart — the SDK consumes book state, not FIX deltas.

Most FIX market data sessions publish trades, not bars. Aggregate prints into OHLCV in the gateway keyed on the bar's opening time, then serve them through loadBars and subscribeRealTimeBars like any other source. See Market data types.

Order routing over FIX

NewOrderSingle from a TradingOrderDraft

TagFIX fieldDraft field
11ClOrdIDYour generated id, unique per session-day
1AccountaccountId
55Symbolsymbol.brokerSymbol — the execution identity, never the display ticker
54Sideside: buy1, sell2
38OrderQtyquantity
40OrdTypetype: market1, limit2, stop3, stop-limit4
44Priceprice
99StopPxstopPrice
59TimeInForceduration: day → 0, GTC → 1, IOC → 3, FOK → 4
60TransactTimeSubmission time, UTC

ClOrdID is yours and immutable; OrderID (37) is the broker's. Keep both. A cancel or replace references OrigClOrdID (41) and carries a new ClOrdID, so a chain of amendments needs the full lineage to reconcile.

ExecutionReport to order state

ExecType (150) says what just happened; OrdStatus (39) says where the order now stands. Drive TradingOrder.status from OrdStatus.

OrdStatus (39)TradingOrderStatus
A Pending Newpre-submitted
0 Newworking
1 Partially filledpartially-filled
2 Filledfilled
6 Pending Cancelcancelling
E Pending Replacemodifying
4 Canceledcancelled
C Expiredexpired
8 Rejectedrejected

Every ExecType=F also produces a fill. Map LastPx (31), LastQty (32), ExecID (17), and TransactTime (60) into a TradingExecution, and let CumQty (14), LeavesQty (151), and AvgPx (6) update the order record. Text (58) and OrdRejReason (103) carry the rejection message the trader needs to see.

Emit each of these as a typed event so the chart updates without a reload:

import type { TradingEvent, TradingExecution, TradingOrder } from '@tradescript/pro/sdk';

export function onExecutionReport(
order: TradingOrder,
fill: TradingExecution | undefined,
emit: (event: TradingEvent) => void,
book: { orders: TradingOrder[]; executions: TradingExecution[] },
): void {
book.orders = [...book.orders.filter((o) => o.id !== order.id), order];
emit({ type: 'orders', orders: book.orders });

if (fill) {
book.executions = [...book.executions, fill];
emit({ type: 'executions', executions: book.executions });
}
}

Topologies

TopologyWhat you connect toTrade-off
Broker FIXYour broker's order-routing sessionSimplest institutional path; broker owns risk, clearing, and market access
Vendor FIX proxyA provider that normalizes many venues behind one sessionOne integration for many markets; adds a hop and a dependency
Direct venueThe exchange's own FIX or binary gatewayLowest latency; you own membership, certification, conformance, and risk controls

Direct venue access is a regulatory and operational commitment, not just a technical one — exchange membership or sponsored access, mandated pre-trade risk checks, conformance testing, and certification per venue. Most funds reach production faster through a broker or vendor session and move venue-direct only where latency demonstrably pays for it.

Colocation

When the session layer is colocated and the chart is not, split them. Run FIX engines in the venue's datacenter, publish normalized frames over your private network to a regional gateway tier, and let browsers connect to the gateway. The chart contracts are unchanged; only the hop count differs.

Drop copy

A drop-copy session is a separate read-only FIX feed of your own executions, independent of the order session. Use it as the authoritative source for TradingState.executions and position reconciliation. If the order session disconnects mid-fill, drop copy is how the chart still shows the truth.

Checklist

  • Durable, backed-up message store per session; sequence state survives restarts.
  • Scheduled session start and end times matching the counterparty's contract.
  • ResendRequest and PossDupFlag handling that never double-counts a fill.
  • ClOrdID uniqueness enforced per session-day, with the amendment chain retained.
  • Book snapshots sequence-matched before publication; a gap invalidates the book.
  • Separate certification and production credentials, and separate SenderCompIDs.
  • Every rejection surfaced with Text (58) intact — never swallowed into a generic failure.

Next steps