1. Introduction
1.1. Scope
This document contains descriptions of all the functionalities, even if some of them are not available for client’s users. That must be taken into account during communicating with users.
1.2. Overview
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.
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:
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 = 40 ms and limit = 100, an increment would be sent to the client either after 40 ms, or after the 100th update to the market (e.g., 100 new orders were placed), whichever comes first.
Snapshots and increments, sent independently of each other by separate services, 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.
1.3. Conventions
Required key:
Key | Description |
Y | Required |
N | Not required |
C | Conditionally required. For conditions, refer to the test in Conditions inside the field description. |
Field properties:
Property | Description |
Conditions | Conditions for:
All items listed under this category are mutually exclusive options. If occurrence of a parameter or a field depends on a combination of conditions, those will be placed in a single item with "AND" conjunction. |
Format | Standard, pattern or a custom type that the value must satisfy. It may include the following:
|
Default | Default value of a parameter. May be specified if it has |
Values | Accepted values of a parameter or possible values of a response (message) including the only possible value. |
Placeholders:
Placeholder | Description |
| User exchange account identifier. Format: integer |
All placeholders are series of upper case letters with words separated by underscores (_
). For example: in user_ACCOUNT_ID
pattern, user_
is the constant part and ACCOUNT_ID
is a placeholder.
1.4. Data Types
Type | Description |
String | Alpha-numeric free format strings. It can include any character or punctuation except the delimiter. All String fields are case-sensitive. |
> Currency | String field representing a currency code. |
> LocalMktDate | String field representing a Date of Local Market (as opposed to UTC) in Format: |
> MultipleCharValue | String field containing one or more space delimited single character values. |
> UTCDateOnly | String field representing a date in UTC format in Format: |
> UTCTimestamp | String field representing date and time combination represented in UTC in either Format:
|
char | Single character value, can include any alphanumeric character or punctuation except the delimiter. All char fields are case-sensitive. The following fields are based on char. |
> Boolean | Char field containing a boolean. Values:
|
float | Sequence of digits with optional decimal point and sign character. The absence of the decimal point within the string will be interpreted as the float representation of an integer value. Format: NOTE: Fields which are derived from float may contain negative values unless explicitly specified otherwise. The following data types are based on float. |
> Amt | Amount in quote currency. |
> Percentage | Float field representing a percentage (e.g., 0.0001 represents 0.01%). |
> Price | Price in quote currency. |
> Qty | Quantity in lots. |
int | Sequence of digits without commas or decimals and optional sign character. Format: NOTE: int values may contain leading zeros. The following data types are based on int. |
> Length | int field representing the length in bytes. Values: ≥ |
> NumInGroup | int field representing the number of entries in a repeating group. Values: ≥ |
> SeqNum | int field representing a message sequence number. Values: ≥ |
2. Connectivity
2.1. CompID
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, or logins, 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). The client may also specify ME_MD
in the field TargetCompID(56) in order to differentiate connections between FIX5 Trading Gateway and FIX5 Market Data Gateway. In that case, requests with TargetCompID(56) = ME
will be processed on FIX5 Trading Gateway only and with TargetCompID(56) = ME_MD
—on FIX5 Market Data Gateway or otherwise rejected. Once chosen the same TargetCompID(56) value must be used in all request throughout the entire session.
2.2. Password
Each new CompID will be assigned a username and a password on registration.
2.3. 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)).
Client Heartbeat messages, reject messages and any other client-initiated administrative messages are not counted towards the throttling limits.
3. Connections and Sessions
3.1. Establishing 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 addresses and ports to establish TCP/IP sessions with the server. Subscription to market data is available after establishing connection via ports according to the table below.
Market data feed | Port |
Incremental refresh |
|
Full refresh |
|
These ports must be used by default if there were no specific ports assigned.
System supports sending increments independently of snapshots, so incoming snapshots would not affect the intensity of increments' publication. In order to access this functionality per symbol, the client performs the following steps:
Subscribe to incremental refresh updates feed with SubscriptionRequestType(263) =
50
(Updates) via port4503
.Wait for an empty full refresh message as a marker of a successful subscription.
Collect increments in a buffer.
Subscribe to full refresh feed with subscription type SubscriptionRequestType(263) =
0
(Snapshot) via port4513
.Clear the buffer from all Increments with MDSeqNum(10020) up to the sequence number of the snapshot arrived.
Append remaining Increments with a higher sequence number to the Snapshot.
Continue receiving increments.
The client will initiate a FIX session by sending the Logon(35=A) message. The client will identify themselves using the SenderCompID(49) field. At each connection MsgSeqNum(34) is reset to 1
, the client should set ResetSeqNumFlag(141) = 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(49), invalid TargetCompID, invalid IP address, invalid password or not having the appropriate privileges to log in 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(49), the server receives a second connection attempt while a valid FIX session is already underway for that same SenderCompID(49), the server will break the TCP/IP connection with the second connection without sending a Logout or Reject message.
3.2. Maintaining Session
3.2.1. Message Sequence Numbers
The client and server will use the Heartbeat(35=0) 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 Logon(35=A) message.
The server will send a Heartbeat(35=0) 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 HeartBtInt(108) = 0
.
If the server detects inactivity for a period longer than the heartbeat interval plus a reasonable transmission time, it will send a TestRequest(35=1) message to force a Heartbeat(35=0) from the client. If a response to the TestRequest(35=1) is not received by a reasonable transmission time, the server will send a Logout(35=5) 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.
3.2.2. Heartbeats
The client and server will use the Heartbeat(35=0) 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 Logon(35=A) message.
The server will send a Heartbeat(35=0) 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 HeartBtInt(108) = 0
.
If the server detects inactivity for a period longer than the heartbeat interval plus a reasonable transmission time, it will send a TestRequest(35=1) message to force a Heartbeat(35=0) from the client. If a response to the TestRequest(35=1) is not received by a reasonable transmission time, the server will send a Logout(35=5) 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.
4. Market Data Management
Clients can use the MarketDataRequest(35=V) 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 identifier of the subscription request they wish to cancel.
A successful MarketDataRequest(35=V) returns one or more market data messages, each containing one or more market data entries. Each market data entry can be a bid, an ask or a trade associated with a currency pair.
Requesting just the top of the book will result in receipt of just the "best" bid and "best" ask. For a full book, the bid and ask 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 MarketDataSnapshotFullRefresh(35=W) message contains a full order book for only one currency pair.
A MarketDataRequestReject(35=Y) may be sent in response to a request that cannot be honored.
5. Messages
5.1. Message Types
5.1.1. Market Data
Client-initiated:
MsgType(35) | Name | Description |
| MarketDataRequest | A request for market data (order book snapshot, order book updates subscription/unsubscription, futures, and market price information). |
Server-initiated:
MsgType(35) | Name | Description |
| MarketDataSnapshotFullRefresh | A response to a MarketDataRequest(35=V) message (full order book or order book top level). |
| MarketDataIncrementalRefresh | A message containing order book updates, trades, futures and market price information. |
| MarketDataRequestReject | A message sent if the MarketDataRequest(35=V) was incorrect. Indicates that the request cannot be processed. |
5.1.2. Securities Reference Data
Client-initiated:
MsgType(35) | Name | Description |
| SecurityStatusRequest | A request for trading status and funding information. |
Server-initiated:
MsgType(35) | Name | Description |
| SecurityStatus | A message containing trading status and funding information. |
5.1.3. Message Format
A standard message includes message header, message body, and message trailer. Fields inside the header, body, and trailer consist of TAG
=VALUE
pairs, and, unless otherwise noted, these fields can be defined in any order.
During formation of a request message, it is necessary to follow the order of tags exactly as given in this specification.
Tags in the range from 10000
to 10100
are custom. Any of them may be ignored if it doesn’t occur in this specification.
5.1.4. Message Body
The message body fields can be defined in any order, except NoFIELD
tags (where FIELD
is a field being counted). These tags start repeating data groups. The fields inside these groups must be defined in the order specified in this document.
5.1.5. StandardHeader
The message header fields are given in the table below. The first three fields in the header must be BeginString(8), BodyLength(9) and MsgType(35). Other fields can be defined in any order.
Tag | Name | Type | Req | Description |
| BeginString | String | Y | Identifies beginning of new message and protocol version. Values: Conditions:
|
| BodyLength | Length | Y | Message length, in bytes, forward to the CheckSum(10) field. Conditions:
|
| MsgType | String | Y | Message type. A Conditions:
Values: refer to Message Types |
| SenderCompID | String | Y | CompID of the party the message is sent from. Values:
|
| TargetCompID | String | Y | CompID of the party the message is sent to. Values:
|
| MsgSeqNum | SeqNum | Y | Integer message sequence number. |
| PossDupFlag | Boolean | N | Flag indicating possible retransmission of a message with this MsgSeqNum(34) Default: Values:
|
| SendingTime | UTCTimestamp | Y | Time of message transmission. |
| OrigSendingTime | UTCTimestamp | C | Original time of message transmission when transmitting orders as the result of a resend request. If the original time is not available, this should be the same value as SendingTime(52). Conditions: PossDupFlag(43) = |
5.1.6. StandardTrailer
The message trailer described in the table below.
Tag | Name | Type | Req | Description |
| CheckSum | String | Y | Three byte, simple checksum. Format: 3 characters Conditions:
|
5.2. Market Data
5.2.1. MarketDataRequest
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| MDReqID | String | Y | Unique identifier for MarketDataRequest(35=V). |
| SubscriptionRequestType | char | Y | Subscription request type. Values:
|
| MarketDepth | int | Y | Depth of market for book snapshot/incremental updates. Values:
|
| MDUpdateType | int | N | Specifies the type of market data update. Values:
Default: |
| AggregatedBook | Boolean | N | Flag indicating whether book entries should be aggregated. Values:
Default: |
Component | MDReqGrp | Y | Market data request details. |
|
| NoMDEntryTypes | NumInGroup | Y | Number of MDEntryType(269) fields requested. Values:
|
> | MDEntryType | char | Y | Type market data entry. Values:
|
Component | InstrmtMDReqGrp | Y | The symbols for which market data is requested. |
|
| NoRelatedSym | NumInGroup | Y | Specifies the number of repeating symbols specified. |
> | Symbol | char | Y | Ticker symbol. |
Component | Y |
|
|
5.2.2. MarketDataRequestReject
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| MDReqID | String | Y | Unique identifier for MarketDataRequest(35=V). |
| MDReqRejReason | char | Y | Reason for the rejection of a MarketDataRequest(35=V). Values:
|
| Text | String | N | Text specifying the reason for the rejection. If MDReqRejReason(281) = |
Component | Y |
|
|
5.2.3. MarketDataSnapshotFullRefresh
The MarketDataSnapshotFullRefresh(35=W) is used as the response to a MarketDataRequest(35=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 MarketDataRequest(35=V) message, where SubscriptionRequestType(263) = 0
(Snapshot), 1
(Snapshot + Updates). In the second case, after the Snapshot only the MarketDataIncrementalRefresh(35=X) messages will come.
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| MDReqID | String | C | Unique identifier for MarketDataRequest(35=V). Conditions: reply to MarketDataRequest(35=V) |
| Symbol | char | Y | Ticker symbol. |
| LastUpdateTime | UTCTimestamp | Y | Timestamp of last update to data item (or creation if no updates made since creation). Format: nanosecond precision |
| MDFeedType | String | Y | The type of the market data feed. Values:
|
Component | MDFullGrp | Y | Full refresh market data entries. |
|
| NoMDEntries | NumInGroup | Y | Number of entries following. |
> | MDEntryType | char | Y | The type of market data entry. Values:
|
> | MDEntryPx | Price | Y | The price of the market data entry. |
> | MDEntrySize | Qty | Y | Quantity represented by the market data entry. |
| MDSeqNum | SeqNum | N | Sequence number of the current market data state. |
Component | Y |
|
|
5.2.4. MarketDataIncrementalRefresh
The MarketDataIncrementalRefresh(35=X) message is used as the response to a MarketDataRequest(35=V) message with SubscriptionRequestType(263) = 1
(Snapshot + Updates), 50
(Updates). 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.
In the case of subscription to Snapshots and Updates via separate feeds (refer to Establishing Connection), Updates arrive before a Snapshot and must be collected in a buffer for the purposes of preserving data continuity. They will share the same MDSeqNum(10020) with the upcoming Snapshot. After Snapshot arrives, clear the buffer from the Increments up to this sequence number inclusively. Then append Increments with higher sequence numbers to the received Snapshot.
Subscription to incremental updates with SubscriptionRequestType(263) = 50
(Updates) 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 MarketDataSnapshotFullRefresh(35=W) with zero sequence number in response to a successful subscription.
An additional info message is sent after the futures contract expiration: in this case mark price and index price will be equal to the settlement price, and the open interest will be 0
.
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| MDReqID | String | C | Unique identifier for MarketDataRequest(35=V). Conditions: reply to MarketDataRequest(35=V) |
| LastUpdateTime | UTCTimestamp | Y | Timestamp of last update to data item (or creation if no updates made since creation). Format: nanosecond precision |
| MDFeedType | String | Y | The type of the market data feed. Values:
|
Component | MDIncGrp | Y | Incremental refresh of market data entries. |
|
| NoMDEntries | NumInGroup | Y | Number of entries following. |
> | MDUpdateAction | char | Y | Type of the market data update action. Values:
|
> | MDEntryType | char | Y | The type of market data entry. Values:
|
> | Symbol | char | Y | Ticker symbol. |
> | MDEntryPx | Price | C | The price of the market data entry. Conditions: omitted if MDEntryType(269) = |
> | MDEntrySize | Qty | C | Quantity represented by the market data entry including:
Conditions: omitted if MDUpdateAction(279) = |
> | TradeID | String | C | The unique identifier assigned to the trade entity once it is received or matched by the exchange or central counterparty. Conditions: MDEntryType(269) = |
> | MDEntryDate | UTCDateOnly | C | Date of the market data Entry. Conditions: MDEntryType(269) = |
> | MDEntryTime | UTCDateOnly | C | Time of the market data entry. Conditions: MDEntryType(269) = Format: nanosecond precision |
> | AggressorSide | char | C | Side of aggressive order or quote resulting in match event. Conditions: MDEntryType(269) = Values:
|
| MDSeqNum | SeqNum | N | Sequence number of the current market data state. |
Component | Y |
|
|
MDEntryType(269) =
3
(Index value) stands for the contract’s index price.MDEntryType(269) =
6
(Settlement price) stands for the contract’s mark price.MDEntryType(269) =
C
(Open interest) stands for the total number of futures contracts in circulation.MDEntryType(269) =
W
(Fixing price) stands for a contract’s estimated settlement price. It may be emitted only within the last 30 minutes prior to the expiration.
5.3. Securities Reference Data
5.3.1. SecurityStatusRequest
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| SecurityStatusReqID | String | Y | Unique identifier of a SecurityStatusRequest(35=e) message. |
| Symbol | char | Y | Ticker symbol. |
| SubscriptionRequestType | char | Y | Subscription request type. Values:
|
Component | Y |
|
|
5.3.2. SecurityStatus
The Security Status (type f) message is used as the response to a Security Status Request (type e) message or sent after the Flow emits a message with updated funding information including the following parameters:
funding rate (FundingRate(10018));
next funding period (NextFundingTS(10017));
indicative funding rate (IndicativeFundingRate(10019)).
A message is also sent after the symbol configuration was changed. In that case, FundingRate(10018), NextFundingTS(10017), and IndicativeFundingRate(10019) fields will be omitted.
Tag | Name | Type | Req | Description |
Tag | Name | Type | Req | Description |
Component | Y | MsgType(35) = |
| |
| Symbol | char | Y | Ticker symbol. |
| IndicativeFundingRate | Percentage | N | Estimated value of FundingRate(10018) in the next funding period calculated at the moment. |
| FundingRate | Percentage | N | Percentage of contract mark value paid after the end of current funding interval. |
| NextFundingTS | UTCTimestamp | N | Timestamp of the next funding interval. Format: nanosecond precision. |
| SecurityTradingStatus | int | N | The trading status applicable to the transaction. Values:
|
| UnsolicitedIndicator | Boolean | Y | Values:
|
| SecurityStatusReqID | String | Y | Unique identifier of a SecurityStatusRequest(35=e) message. Conditions: UnsolicitedIndicator(325) = |
| TransactTime | UTCTimestamp | Y | Time of a Flow message. Date and time with nanosecond precision. |
Component | Y |
|
|
6. Version History
Version | Date | Description |
1.0 | 2019/10/30 | First edition. |
1.1 | 2021/04/19 | Added a separate service sending snapshots. |
1.2 | 2021/04/06 | Added an empty snapshot on a subscription to updates. |
1.3 | 2021/04/19 | Added security status message. |
1.4 | 2021/12/21 | Added a new |