General
Introduction
The FIX5 Market Data Gateway enables clients to anonymously receive order book market data in real time. The interface is a point-to-point service based on the technology and industry standards TCP/IP, FIXT and FIX. The session and application event models and messages are based on versions 1.1 and 5.0 (Service Pack 2) of the FIXT and FIX protocols respectively.
Purpose
The purpose of this document is to provide a technical description of the FIX Market Data Gateway. This document outlines the service, its logic, and message types and fields involved.
Key
Usage | Meaning |
Req | Required? |
Y | Yes |
N | No |
C | Conditional |
Log
Nr | Date | Changes |
1 | 30 Oct 2019 | First Edition |
2 | 19 Apr 2021 | Added a separate service sending snapshots |
3 | 04 Jun 2021 | Added an empty snapshot on a subscription to updates |
Service Overview
Market data consists of snapshots, increments, and trades. Trades are sent in the same messages as increments.
A snapshot is the current state of the order book for some specific trading pair and depth. Snapshots are sent periodically for all trading pairs and for different depths.
An increment is an incremental update from the previous state of the order book, based on the last snapshot. On the sending side, increments are buffered into a batch. Increments can be sent from this batch under the below conditions:
Periodically, at an internally configured interval of time. The cut-off for this interval occurs for all trading pairs of a given depth at the same time.
When the batch buffer has filled to an internally configured size limit. The limit cut-off occurs independently of trading pairs and depths.
This means that, if interval = 40ms and limit = 100, an increment would be sent to the client either after 40ms, or after the 100th update to the market (e.g. 100 new orders were placed), whichever comes first.
Snapshots and increments are sent independently of each other by separate services and both may contain market data for the same time frame. Changes in Market data are indicated by a sequence number increased by 1 after any snapshot or increment.
Connectivity
CompIDs
The CompID of each client must be registered before FIX communications can begin. A single client may have multiple connections to the server (i.e. multiple FIX sessions, each with its own CompID).
The CompID of the server is ME. The messages sent to the server should contain the CompID assigned to the client in the field SenderCompID (49) and ME in the field TargetCompID (56). The messages sent from the server to the client will contain ME in the field SenderCompID (49) and the CompID assigned to the client in the field TargetCompID (56).
Passwords
Each new CompID will be assigned a username and a password on registration.
Message Rate Throttling
A scheme for throttling message traffic is implemented, where each CompID is only permitted to submit up to a specified number of messages per second.
Every message which exceeds the maximum rate of a CompID will be rejected via a Business Message Reject (with BusinessRejectReason (380) of ThrottleLimitExceeded (8)).
Please note that client Heartbeat messages, reject messages and any other client-initiated administrative messages are not counted towards the throttling limits.
FIX connections and sessions
Establishing a FIX connection
FIX connections and sessions between the client and server are maintained as specified in the FIX protocol.
Each client will use the assigned IP address and port to establish a TCP/IP session with the server. The client will initiate a FIX session by sending the Logon (A) message. The client will identify itself using the SenderCompID (49) field. At each connection MsgSeqNum (34) is reset to 1, the client should set ResetSeqNumFlag (141) to "Y". The server will validate the CompID, password and IP address of the client. Once the client is authenticated, the server will respond with a Logon message.
The client must wait for the server’s Logon response before sending additional messages. If the client sends messages prior to sending the Logon message or prior to receiving the Logon response, the server will break the TCP/IP connection with the client without sending any message.
If a logon attempt fails because of an invalid SenderCompID, invalid TargetCompID, invalid IP address, invalid password or not having the appropriate privileges to login to the gateway, or if the user sends a Logon message with duplicated tags, the server will break the TCP/IP connection with the client without sending a Logout or Reject message.
If during a logon of a SenderCompID, the server receives a second connection attempt while a valid FIX session is already underway for that same SenderCompID, the server will break the TCP/IP connection with the second connection without sending a Logout or Reject message.
Maintaining a FIX session
Message sequence numbers
As outlined in the FIX protocol, the client and server will each maintain a separate and independent set of incoming and outgoing message sequence numbers. Sequence numbers should be initialized to 1 (one) at the start of the FIX session and be incremented throughout the session.
If any message sent by the client contains a sequence number that is less than what is expected and the PossDupFlag (43) is not set to “Y”, the server will send a Logout message and terminate the FIX connection. The Logout will contain the next expected sequence number as well as the received sequence number in the Text (58) field.
Heartbeats
The client and server will use the Heartbeat message to exercise the communication line during periods of inactivity and to verify that the interfaces at each end are available. The heartbeat interval will be the HeartBtInt (108) specified in the client’s Logon message.
The server will send a Heartbeat anytime it has not transmitted a message for the heartbeat interval. The client is expected to employ the same logic.
As a safety mechanism, the system will not allow the user to login if the HeartBtInt is set to 0.
If the server detects inactivity for a period longer than the heartbeat interval plus a reasonable transmission time, it will send a Test Request message to force a Heartbeat from the client. If a response to the Test Request is not received by a reasonable transmission time, the server will send a Logout and break the TCP/IP connection with the client. The client is expected to employ similar logic if inactivity is detected on the part of the server.
Handling Market Data
Clients can use the Market Data Request message to both subscribe to and unsubscribe from real-time receipt of Market Data from the exchange.
When making a Subscription Request, clients must supply the symbols they are requesting market data for and whether they want the entire order book or just the top of the book. Clients can request a one-time Snapshot, or a Snapshot plus ongoing streamed updates.
When unsubscribing, the client must pass the ID of the Subscription Request they wish to cancel.
A successful Market Data Subscription Request returns one or more Market Data (type W or type X) messages, each containing one or more Market Data Entries. Each Market Data Entry can be a Bid, an Offer or a Trade associated with a currency pair.
Requesting just the top of book will result in receipt of just the Best Bid and Best Offer. For a full book, the Bid and Offer side may each have several Market Data Entries.
A Snapshot causes the current state of the market to be sent. A Snapshot + Updates causes the current state of the market to be sent, and any updates as they occur, until the client requests that the Snapshot + Updates be disabled.
Each Market Data — Snapshot / Full Refresh (W) message contains a full order book for only one currency pair.
A Market Data Request Reject (message type Y) may be sent in response to a request that cannot be honoured.
Message Formats
Client-initiated:
Message | MsgType | Usage |
Market Data Request | V | A general request for market data (order book snapshot, order book updates, subscription/unsubscription). |
Server-initiated:
Message | MsgType | Usage |
Market Data Request Rejection | Y | A general request for market data (order book snapshot, order book updates, subscription/unsubscription). |
Market Data - Snapshot/Full Refresh | W | A response to a Market Data Request message (full order book or order book top level). |
Market Data - Incremental Refresh | X | A message contains order book updates and trades. |
Message Header and Trailer
Message Header
Tag | Field Name | Req | Description |
8 | BeginString | Y | FIXT.1.1 |
9 | BodyLength | Y | Number of characters after this field up to and including the delimiter immediately preceding the CheckSum. |
35 | MsgType | Y | Message type. |
49 | SenderCompID | Y | CompID of the party sending the message. |
56 | TargetCompID | Y | CompID of the party the message is sent to. |
34 | MsgSeqNum | Y | Sequence number of the message. |
43 | PossDupFlag | N | Whether the message was previously transmitted under the same MsgSeqNum (34). Absence of this field is interpreted as Original Transmission (N). |
52 | SendingTime | Y | Time the message was transmitted. |
122 | OrigSendingTime | C | Time the message was originally transmitted. If the original time is not available, this should be the same value as SendingTime (52). |
Message Trailer
Tag | Field Name | Req | Description |
10 | CheckSum | Y | CheckSum |
Market Data Messages
Market Data — Request
Tag | Field Name | Req | Type | Description |
Standard Header |
|
|
|
|
35 | MsgType | Y | String | V = Market Data Request |
Message Body |
|
|
|
|
262 | MDReqID | Y | String | Id of the request |
263 | SubscriptionRequestType | Y | Char | 0 = Snapshot |
264 | MarketDepth | Y | Int | 0 = full book depth |
265 | MDUpdateType | N | Int | 0 = FullRefresh (not supported) |
266 | AggregatedBook | N | Boolean | Y = Book entries to be aggregated (by default) |
267 | NoMDEntryTypes | Y | NumlnGroup | Must be 4, and group must contain 0,1,2,J |
269 | MDEntryType | Y | Char | 0 = Bid |
146 | NoRelatedSym | Y | NumlnGroup | Number of symbols. |
55 | Symbol | Y | String | Symbol for which Market Data is requested. |
Standard Trailer |
|
|
|
|
Market Data — Request Rejected
Tag | Field Name | Req | Description |
Standard Header |
|
|
|
35 | MsgType | Y | V = Market Data Request |
Message Body |
|
|
|
262 | MDReqID | Y | Id of the request. |
281 | MDReqRejReason | Y | 0 = UnknownSymbol |
58 | Text | N | Text specifying the reason for the rejection. |
Standard Trailer |
|
|
|
Market Data — Snapshot/Full Refresh
The Market Data Snapshot Full Refresh message (type W) is used as the response to a Market Data Request (type V) message.
A Snapshot is the current state of the order book at the time of the request; it contains only bids and offers for the depth specified in the request.
A Snapshot is always sent in response to a Market Data Request (V) message, where the message type is 0 = Snapshot or 1 = SnapshotAndUpdates. In the second case, after the Snapshot only the Market Data - Incremental Refresh (X) messages will come.
Tag | Field Name | Req | Description |
Standard Header |
|
|
|
35 | MsgType | Y | W = Market Data — Snapshot / Full Refresh |
Message Body |
|
|
|
262 | MDReqID | Y | Conditionally required if this message is in response to a MarketDataRequest (V). |
55 | Symbol | Y | Symbol for which Market Data is requested. |
779 | LastUpdateTime | Y | Timestamp of last update to data item. Date and time with nanosecond precision. |
268 | NoMDEntries | Y | Number of entries following. |
269 | MDEntryType | Y | 0 = Bid |
270 | MDEntryPx | Y | Price of the Market Data Entry. |
271 10020 | MDEntrySize MDSeqNum | Y N | Quantity represented by the Market Data Entry. Sequence number of the current Market data state. |
Standard Trailer |
|
|
|
Market Data — Incremental Refresh
The Market Data Incremental Refresh (X) message is used as the response to a Market Data Request (type V) message with SubscriptionRequestType (263) set to '1' = SnapshotAndUpdates. It contains trades and incremental updates for the order book, such as new, changed, or deleted order book levels. A single message may contain several updates, but it may contain data for only one symbol. Incremental updates may arrive before Snapshots. To handle this, accumulate Increments in a buffer and wait for the next Snapshot to arrive before appending them to the received Snapshot.
Subscription to incremental updates apart from snapshots may result in a situation when the client cannot determine if they missed any updates since the subscription and before requesting a snapshot because of, possibly, low trading activity. To avoid that, the server will immediately send an empty snapshot with zero sequence number as the response to a successful subscription.
Tag | Field Name | Req | Description |
Standard Header |
|
|
|
35 | MsgType | Y | X = Market Data — Incremental Refresh |
Message Body |
|
|
|
262 | MDReqID | Y | Conditionally required if this message is in response to a Market Data Request. |
779 | LastUpdateTime | Y | Date and time with nanosecond precision. |
268 | NoMDEntries | Y | Number of entries following. |
279 | MDUpdateAction | Y | 0 = New |
269 | MDEntryType | Y | 0 = Bid |
55 | Symbol | Y | Symbol for which Market Data is requested. |
270 | MDEntryPx | Y | Price of the Market Data Entry. |
271 | MDEntrySize | C | Quantity represented by the Market Data Entry. Trade size or final level size. It’s absent if MDUpdateAction (279) is '2' = Delete. |
1003 | TradeID | C | Unique ID of the trade entity. It takes place if MDEntryType(269) is '2' = Trade only. |
272 | MDEntryDate | C | Date of Market Data Entry. It takes place if MDEntryType(269) is '2' = Trade only. |
273 | MDEntryTime | C | Time of Market Data Entry. Date and time with nanosecond precision. It takes place if MDEntryType(269) is '2' = Trade only. |
2446
10020 | AggressorSide
MDSeqNum | C
N | 1 = Buy Sequence number of the current Market data state. |
Standard Trailer |
|
|
|
NOTE: Tags in the range from 10000 to 10100 are custom. Any of them may be ignored if it doesn’t occur in this specification
Security Status
The Security Status (type f ) message is used as the response to a Security Status
Request (type e) message or sent after trading on a symbol was started or
stopped.
Security Status Request (type e)
Security Status Request (type e) is being used for checking availability of trading on a symbol.
Tag | Field Name | Req | Description |
Standard Header |
|
|
|
35 | MsgType | Y | e = Security Status Request |
Message Body |
|
|
|
324 | SecurityStatusReqID | Y | Id of the request. |
55 | Symbol | Y | Symbol for which Security Status is requested. |
263 | SubscriptionRequestT ype | Y | 0 = Snapshot |
Standard Trailer |
|
|
|
Security Status Message (type f )
Tag | Field Name | Req | Description |
Standard Header |
|
|
|
35 | MsgType | Y | f = Security Status |
Message Body |
|
|
|
324 | SecurityStatusReqID | N | Conditionally required if UnsolicitedIndicator (325) is 'N' |
55 | Symbol | Y | Symbol for which Security Status is sent. |
326 | SecurityTradingStatus | N | 17 = Ready to trade (start of session) 18 = Not Available for trading (end of session) |
325 | UnsolicitedIndicator | Y | Y = sent by the gateway on a Flow message N = sent as the response to a Security Status Reques |
60 | TransactTime | Y | Time of a Flow message. Date and time with nanosecond precision. |
Standard Trailer |
|
|
|