FIX Session

For basic information about FIX Session refer to the Session description section.

Session identifier

In earlier versions of FIX Antenna (2.10.14 and earlier) any session object could be uniquely identified by SenderCompId/TargetCompId pair. There were number of methods in external interface of FIX Antenna like V12.FIXAntenna.FixEngine.create_session() which took SenderCompId and TargetCompId parameters to identify session.

Starting from version 2.10.15.5 extra string identifier - SessionQualifier has been introduced in addition to SenderCompId/TargetCompId pair. The idea is to give user ability to create several sessions with the same SenderCompId and TargetCompId and to give ability to address these sessions by unique ID. To achieve this goal, V12.FIXAntenna.SessionId structure was introduced. The structure consists of three string properties - sender, target and qualifier. If user needs to create session with or without the same SenderCompId/TargetCompId pair they first need to create V12.FIXAntenna.SessionId structure by passing SenderCompId, TargetCompId and optionally unique Session Qualifier to its constructor, and then call method, which takes V12.FIXAntenna.SessionId structure.

For example:

ssn = engine.create_session(v12.SessionId("TEST1", "TEST2", "Qualifier1"), "FIX44", v12.FIXVersion.FIX44)

To establish several sessions with the same SenderCompId and TargetCompId, both Initiator and Acceptor should create several session objects, which differ from each other by SessionQualifier property. SessionQualifier property on Initiator side must be the same as SessionQualifier property of the corresponding session on acceptor side. When Initiator connects to Acceptor, it sends SessionQualifier along with SenderCompId and TargetCompId in logon message. The SessionQualifier tag in logon message is optional and can be configured in engine.properties file. You can find more details on how to configure the library in chapter Configuration. When Acceptor receives logon message with the SessionQualifier it searches for registered session with SessionId corresponding to received TargetCompId, SenderCompId and SessionQualifier. If the session is found it is associated with the incoming connection, otherwise connection is rejected.

If user creates session by passing only SenderCompId and TargetCompId parameters (without SessionQualifier), the V12.FIXAntenna.SessionId structure is created and stored internally with empty qualifier property. If Acceptor registers a session without session qualifier it won’t accept any incoming connection with session qualifier defined in logon message. And vice versa, if Acceptor has registered a session or several sessions with qualifiers, it won’t accept connections from Initiators without SessionQualifier.

The FIX engine will automatically insert SessionQualifier tag into logon message if user creates session with qualifier on initiator side and SessionQualifier tag is appropriately configured in engine.properties. To configure SessionQualifier tag user needs to add the lines like below to config file (see chapter Configuration for more details)

Session.Default.LogonMessageSessionQualifierTag = 9012

User can also overload LogonMessageSessionQualifierTag property for any particular session like below

Session.Sender1/Target1.LogonMessageSessionQualifierTag = 9015

If user wish to define or overload some other properties for any session with session qualifier they can add a configuration line like in example below (see also Session configuration).

Session.Sender1/Target1/Q1.StorageType=null

Wherever possible, if SessionQualifier is defined for a session, the string representation of the session’s identifier will consist of Sender, Target and SessionQualifier (separated by a delimiter). If SessionQualifier is not defined, it will be omitted in any output related to session identifier. This is done for backward compatibility. The possible affected places are log files (names and content), admin protocol messages, keys of message storage and so on.

External acceptor applications

If Acceptor application doesn’t use FIX Antenna library it may define its own rules on how to determine correspondence between sessions on initiator and acceptor side. For example, it may distinguish sessions based on TCP port, which they are connected to. In this case, passing Session Qualifier in Logon message is not necessary and may even lead to rejection by acceptor side.

To disable passing Session Qualifier in Logon Message, it’s enough just do not add the LogonMessageSessionQualifierTag parameter to configuration file. If user wants to disable passing Session Qualifier in Logon Message only for some particular session, they may add lines like below to configuration file. See chapter Configuration for more details on configuration parameters.

Session.Default.LogonMessageSessionQualifierTag = 9012
Session.Sender1/Target1.LogonMessageSessionQualifierTag = 0

In this example, all sessions except “Sender1/Target1” will pass Session Qualifier as tag 9012 in Logon message.

Session configuration

Session configuration is one of the most important part of the FIX Antenna. Configuration allows to enable or disable functionality. Configuration influences on performance (see Performance tuning). Please pay attention on how your session is configured.

There are two approaches to configure Session:

  1. Using engine.properties file (see Configuration)

  2. FIX Antenna API

Approaches can be combined. E.g. part of settings can be configured in engine.properties file, other settings can be configured using FIX Antenna API.

Session settings are being applied in the following order:

  1. Hardcoded defaults. Each parameter has hardcoded default value. See parameter description for details.

  2. Settings defined in the engine.properties file in the section “Session.Default”.

    #
    # Settings for all sessions
    #
    Session.Default.StorageType = transient
    Session.Default.ConnectAddress = 10.0.0.1
    
  3. Settings defined in the engine.properties file in the section “Session.<Sender/Target>”.

    #
    # Settings for sessions which have SenderCompID = Sender1 and TargetCompID = Target1
    #
    Session.Sender1/Target1.StorageType = transient
    Session.Sender1/Target1.ConnectAddress = 10.0.0.1
    
  4. Settings defined in the engine.properties file in the section Session.<Sender/Target/SessionQualifier> if session has been created with SessionQualifier.

    #
    # Settings for sessions which have SenderCompID = Sender1, TargetCompID = Target1 and
    # SessionQualifier = Q1.
    #
    Session.Sender1/Target1/Q1.StorageType = transient
    Session.Sender1/Target1/Q1.ConnectAddress = 10.0.0.1
    
  5. FIX Antenna API.

    params = v12.SessionParameters()
    params["Validation.IsEnabled"] = "true"
    params["Validation.CheckRequiredGroupFields"] = "true"
    
    ssn = engine.create_session(v12.SessionId("TEST1", "TEST2"), "FIX50FIXT11", v12.FIXVersion.FIX50, params)
    

FIX Antenna API has highest priority. Settings set by C/C++/NET/Python code cannot be changed by engine.properties file.

Note

Defining session settings in the engine.properties file does not create session itself. Settings in the engine.properties file are applied upon V12.FIXAntenna.FixEngine.create_session() method call.

Example

If engine.properties file contains following settings:

#
# Settings for all sessions
#
Session.Default.StorageType = transient

#
# Settings for all sessions Sender1@Target1
#
Session.Sender1/Target1.StorageType = persistent
Session.Sender1/Target1.ConnectAddress = 10.0.0.1

#
# Settings for session Sender1@Target1@Q1
#
Session.Sender1/Target1/Q1.Validation.LogIncomingMessages = false

and code looks like this:

params = v12.SessionParameters()
params["Validation.IsEnabled"] = "true"

ssn1 = engine.create_session(v12.SessionId("Sender2", "Target2"), "FIX44")
ssn2 = engine.create_session(v12.SessionId("Sender1", "Target1", "Q1"), "FIX44")
ssn3 = engine.create_session(v12.SessionId("Sender1", "Target1", "Q2"), "FIX44")
ssn4 = engine.create_session(v12.SessionId("Sender1", "Target1", "Q3"), "FIX44", v12.FIXVersion.FIX44, params)

then sessions will be configured in the following way:

Session

StorageType

Connect Address

Message validation

LogIncomingMessages

session1 (Sender2/Target2)

transient

0.0.0.0 (NIC will be chosen by OS)

disabled

true

session2 (Sender1/Target1/Q2)

persistent

10.0.0.1

disabled

true

session3 (Sender1/Target1/Q1)

persistent

10.0.0.1

disabled

false

session4 (Sender1/Target1/Q3)

persistent

10.0.0.1

enabled

true

Persistent session

Persistent session is a session with persistent storage. According to the FIX protocol session is responsible for outgoing message flow. This means that any time counterparty may request retransmission of the previously sent messages. In the result session must store all sent messages to some storage. In case of persistent session messages are stored to the file. This guarantees that session can recover its state (sent messages and latest sequence numbers) after failure (e.g. after crash) by the cost of performance. To guarantee consistency the store and forward approach is used (refer to the Store-and-forward section for more details).

Session state is stored on a disk and can be restored after failure. The following information is stored for a session:

  • Session parameters (SenderCompID, TargetCompID, FIX version, etc.)

  • Session incoming and outgoing sequence numbers

  • Incoming messages (optional)

  • Outgoing messages

Transient session

Transient session is a session with transient storage i.e. in contrast to persistent session (refer to the Persistent session section) messages are stored in memory. This type of session is faster however all information about session will be lost in case of failure.

This session type is recommended when recovery after failure is not required i.e. when every time session is connected from scratch. This applicable for market data sessions, when client has to subscribe and request snapshot on every logon and hence recovery is not required. Another example is when persistent already exists in application so having yet another storage of recovery information is redundant. In the latter case application is responsible to restore session state after creation and before connect (refer to the V12.FIXAntenna.Session.set_in_seq_num() and V12.FIXAntenna.Session.set_out_seq_num() methods).

Session state

Session state is a set of parameters that defines session behavior. The most important session state’s parameter is session status. Session changes its state based on the event, which can be originated from the FIX messages flow, timer or user actions. The session state can be obtained using the V12.FIXAntenna.Session.get_state() method, which returns V12.FIXAntenna.SessionState.

Below is the list of session statuses with explanations.

  • INITIAL - The session has been created, but has not been connected yet

  • WAIT_FOR_CONNECT - The session is initialized TCP connection process and waits for completion.

  • WAIT_FOR_FIRST_LOGON - The session has been connected as an Acceptor and is waiting for the first Logon message

  • WAIT_FOR_CONFIRM_LOGON - The session has been connected as an Initiator, the first Logon message has been sent and it is waiting for the confirming Logon message

  • SWITCH_CONNECTION - The session is in process of changing connection from primary to backup (or back)

  • ESTABLISHED - The session is established

  • WAIT_FOR_CONFIRM_LOGOUT - The Session is terminating and waiting for Logout confirmation.

  • RECONNECT - The session-initiator has detected the telecommunication link error and is trying to re-establish the link

  • CORRECTLY_TERMINATED - The session has been correctly terminated

  • NON_GRACEFULLY_TERMINATED - The session has been non-gracefully terminated

Below is the basic static finite state machine for Session.

../_images/session_states.png

Sequence number handling

The session is always assigned with two separated sequence numbers:

  • Incoming sequence number is a counter for incoming message

  • Outgoing sequence number is a counter for outgoing message

Incoming and outgoing sequence numbers start from 1 when the session is created from scratch. After the correct session termination sequence numbers are reset to 1. If connection is terminated non-gracefully sequence numbers will continue after it is restored.

Both sides must maintain these two values and ensure that they are in sync.

There are two types of sequence numbers desync:

Resetting sequence number

To reset message sequence numbers on each Logon following approach should be used:

import V12.FIXAntenna as v12

SENDER = "f_sender"
TARGET = "f_target"
#
# Start of the day as usual like in daily reset case
#
engine = v12.FixEngine()

params = v12.SessionParameters()
params["IntradayLogoutToleranceMode"] = "true"
params["ForceSeqNumReset"] = "true"
params["UseAsyncConnect"] = "true"

ssn = engine.create_session(v12.SessionId(SENDER, TARGET), "FIX44", v12.FIXVersion.FIX44, params)
#
# Start of the day
#

ssn.connect( 30, "localhost", 9900 )

#
# ... receive and process market data
#
#
# End of day
#
ssn.disconnect()

FIX Antenna also supports resetting message sequence numbers once per 24 hour of continuous work. This feature can be enabled using ResetSeqNumAfter24hours configuration option.

Late delivery vs rejecting

When session connection is lost, the initiator tries to reconnect, which may take some time (or even infinity), and the acceptor waits for reconnect. For both sides message delivery is impossible. FIX Antenna provides two different approaches to message handling in this case:

  • Late delivery (default mode) means that all outgoing messages are stored in outgoing queue and sent once connection is reestablished (utilizing resend request logic).

  • Message rejecting means that after some reasonable period of time messages are rejected i.e. they are removed from outgoing queue and reject message is sent to the message originator.

The EnableMessageRejecting parameter controls if message rejecting is enabled or not (by default it is disabled). The MessageTimeToLive property specifies how long the session waits for connection restore (i.e. before rejecting the message). If the connection is not restored during the MessageTimeToLive interval - the session starts rejecting messages by calling V12.FIXAntenna.Application.on_msg_reject_event() for each rejected message.

Message validation

V12.FIXAntenna.Session supports automatic incoming/outgoing message validation. Validation can be switched on/off. If validation is on, all incoming messages will be validated and reject message will be sent on invalid incoming message. On invalid outgoing message an exception will be raised by V12.FIXAntenna.Session.put(). Following are available validation options:

  • Empty field values validation. If enabled, engine rejects messages with empty field values. Empty means field value is defined but it equals to empty string.

  • Field value format validation. If enabled, engine validates field value according to field type and list of possible values.

  • Check for unknown fields. If enabled, engine rejects messages with undefined fields inside.

  • Check for repeating group leading tag value. If enabled, engine compares passed repeating group leading tag value with actual group size.

  • Required field validation. If enabled, engine rejects messages which have fields with undefined value required by protocol.

  • Check required field in the repeating group. Enables required field validation inside repeating group.

By default validation is disabled. There are two ways to enable/configure it:

  • Using API

    params = v12.SessionParameters()
    params["Validation.IsEnabled"] = "true"
    params["Validation.CheckRequiredGroupFields"] = "true"
    params["Validation.ProhibitDuplicatedTags"] = "true"
    params["Validation.ProhibitTagsWithoutValue"] = "true"
    params["Validation.ProhibitUnknownTags"] = "true"
    params["Validation.VerifyRepeatingGroupBounds"] = "true"
    params["Validation.VerifyTagsValues"] = "true"
    
  • Using FIX Engine configuration file (engine.properties). Refer to Configuration for more details.

    # Enable validation by default for all sessions
    Session.Default.Validation.IsEnabled = true
    Session.Default.Validation.ProhibitTagsWithoutValue = true
    Session.Default.Validation.VerifyTagsValues = true
    Session.Default.Validation.ProhibitUnknownTags = true
    Session.Default.Validation.VerifyReperatingGroupBounds = true
    Session.Default.Validation.CheckRequiredGroupFields = true
    
    # Enable validation for Session Sender1/Target1
    Session.Sender1/Target1.Validation.IsEnabled = true
    Session.Sender1/Target1.Validation.ProhibitTagsWithoutValue = true
    Session.Sender1/Target1.Validation.VerifyTagsValues = true
    Session.Sender1/Target1.Validation.ProhibitUnknownTags = true
    Session.Sender1/Target1.Validation.VerifyReperatingGroupBounds = true
    Session.Sender1/Target1.Validation.CheckRequiredGroupFields = true
    

Note

For back compatibility old-style properties are also supported. Following properties enable validation for all session:

#Enable validation
MessageMustBeValidated = true
# Configure validation
Validation.CheckRequiredGroupFields = true
AllowEmptyFieldValue = false
ProhibitUnknownTags = true
VerifyReperatingGroupBounds = true
VerifyTagsValues = true

Note

Settings configured by API override settings configured by engine.properties file.