Basic Concepts

Main components

The main FIX Antenna Python components are:

  • V12.FIXAntenna.FixEngine - Integral component. Responsible for FIX Antenna initialization, destruction, session creation, generic events, etc.

  • V12.FIXAntenna.FixMessage - FIX message class. Responsible for getting and setting FIX fields values, validation, repeating groups handling etc.

  • V12.FIXAntenna.Session - FIX Session class. Implements FIX session level protocol; responsible for sending and receiving FIX messages.

  • V12.FIXAntenna.Application - Observer for session level events and incoming messages. Incoming messages and events are delivered via call-back methods.

Engine description

The engine is represented by the V12.FIXAntenna.FixEngine class. This class is responsible for:

  • Initializing the engine

  • Creating sessions

  • Collecting statistics

  • Cleaning-up before exit

Engine initialization is performed using the V12.FIXAntenna.FixEngine.__init__() method. This method must be called before any other FIX Antenna methods.

For example:

import V12.FIXAntenna as v12

try:
    engine = v12.FixEngine()

    while True:
        s = input("input: 'q' to exit\n")
        if s == "q": break

except (Exception) as e:
    print(e)

The V12.FIXAntenna.FixEngine class, as well as several other FIX Antenna Python API classes, implements the Singleton Design Pattern on the C++ side. Therefore you should, first of all, get a pointer to the instance of the class, using the V12.FIXAntenna.FixEngine.__init__() method to access non-static methods of the class.

For example:

engine = v12.FixEngine()
session = engine.create_session(...)

Session description

The FIX session is represented by the V12.FIXAntenna.Session class. This class is responsible for:

In earlier versions of FIX Antenna (2.10.14 and earlier) Session object could be uniquely identified by SenderCompId/TargetCompId pair. 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. See Session identifier for more details.

Each session encapsulates message storage that is used to store the sent and received messages. There are two types of storages:

  • Persistent message storage uses files on disk to store messages. This storage is reliable and must be used when session state is important to persist e.g. to recover after failure. This type is to be used in highly available environment.

  • Transient message storage uses RAM to store messages. This storage is faster than persistent one, but does not provide recovery after failure. This type is to be used when recovery is not required e.g. for market data sessions or when recovery is handled by other component.

Unregistered acceptors

When engine receives FIX logon message it extracts SenderCompID and TargetCompID fields from the message and tries to find previously created acceptor with corresponding session ID (i.e. session SenderCompID equal to TargetCompID extracted from message and session TargetCompID equal to the SenderCompID extracted from messages). Refer to the FIX Session Acceptor for more information about how to create session acceptor. If engine cannot find corresponding acceptor the incoming logon is declined and connection is not established.

Engine though can also work in “trusted mode” i.e. if corresponding session acceptor cannot be found then session is created automatically. To enable this mode set CreateUnregisteredAcceptorSession property to “true” (refer to the section Common parameters for more details about property).

Application description

The Application class is responsible for:

Create a new class derived from the Application class and override the V12.FIXAntenna.Application.process() method in this class to process incoming messages. Then pass the instance of your class to the session to start receiving incoming messages.

Engine delivers incoming messages to the Application by calling V12.FIXAntenna.Application.process() method and analyzing its return value to make sure that incoming message was processed and Application is ready to process next incoming message.

If the V12.FIXAntenna.Application.process() method does not return “true” (i.e. returns “false” or throws an exception), the engine passes the same incoming message to the V12.FIXAntenna.Application.process() again and again until either V12.FIXAntenna.Application.process() returns “true” or number of attempts is exceeded (DelayedProcessing.MaxDeliveryTries, refer to Common parameters for more information). The interval between attempts is specified by property DelayedProcessing.DeliveryTriesInterval (refer to Common parameters for more information). If the number of unsuccessful attempts exceeds the MaxDeliveryTries, a Logout message with the reason “Application is not available” is sent to the counterparty and session is closed.

Other useful methods to override are: on_logon_event, on_logout_event, on_msg_reject_event, on_resend, etc. These are the call-back methods called to notify about the corresponding session-level events.

The V12.FIXAntenna.Application.process() method is called only when application-level message is received. All session-level messages (Heartbeats, Test Requests, Resend Requests, etc.) are handled by FIX Antenna. However you can modify default behavior overriding call-back methods in Application and providing your own logic.

Below is an example of custom implementation of Application interface:

class MyApp(v12.Application):

    def process(self_, message: v12.FixMessage, sid: v12.SessionId):
        print('<{},{}>: process()'.format(sid.sender, sid.target))
        print('\tInMessage: {}'.format(message))
        return True

    def on_logon_event(self_, event: v12.LogonEvent, sid: v12.SessionId):
        print('<{},{}>: on_logon_event()'.format(sid.sender, sid.target))
        print('\tInLogon: {}'.format(event.incoming_logon_message))
        print('\tOutLogon: {}'.format(event.outgoing_logon_message))
        print('\tOutLogout: {}'.format(event.outgoing_logout_message))
        event.logon_action = v12.LogonAction.AcceptWithConfirmLogon # default action; acceptors only

    def on_logout_event(self_, event: v12.LogoutEvent, sid: v12.SessionId):
        print('<{},{}>: on_logout_event()'.format(sid.sender, sid.target))
        print('\tInLogout: {}'.format(event.incoming_logout_message))
        event.reconnect_flag = True # reconnect on logout

    def on_session_level_reject_event(self_, event: v12.SessionLevelRejectEvent, sid: v12.SessionId):
        print('<{},{}>: on_session_level_reject_event()'.format(sid.sender, sid.target))
        print('\tInReject: {}'.format(event.incoming_reject_message))

    def on_msg_reject_event(self_, event: v12.MsgRejectEvent, sid: v12.SessionId):
        print('<{},{}>: on_msg_reject_event()'.format(sid.sender, sid.target))
        print('\tOutRejected: {}'.format(event.outgoing_rejected_message))

    def on_new_state_event(self_, event: v12.NewStateEvent, sid: v12.SessionId):
        print('<{},{}>: on_new_state_event()'.format(sid.sender, sid.target))
        print('\t{}->{}'.format(event.old_state, event.new_state))

    def on_resend(self_, message: v12.FixMessage, sid: v12.SessionId):
        print('<{},{}>: on_resend()'.format(sid.sender, sid.target))
        print('\tOutResendMessage: {}'.format(message))
        return True # allow this message to be resent

Note

It is not recommended to put lock inside the V12.FIXAntenna.Application.process(), synchronize different call-back methods unless you are absolutely confident in what you are doing. Also it is not recommended to perform time-consuming operations inside V12.FIXAntenna.Application.process() as it blocks receiving following messages.

Warning

Do not delete the registered Application until you unregister it.

Message description

The FIX message (specified by the FIX protocol) is represented by the V12.FIXAntenna.FixMessage class.

The V12.FIXAntenna.FixMessage class provides the following functionality:

Repeating Groups description

Please read the FIX Protocol explanation of the Repeating group first (refer to the section About FIX messages).

The FIX message may contain repeating groups. Each group contains:

  • Repeating Groups descriptionLeading tag, which contains the number of repeating group entries.

  • Repeating group entries.

  • At least one required tag for each entry, which is always the 1st tag in the entry. This tag plays role of entries delimiter and usually is referred as Start tag.

Repeating groups are usually referred by the leading tag.

To add new group to the message you simply should add leading field to the message. In the result the new group will be added with the number of entries according to the value of leading field.

To access fields inside a repeating group you should

  • Get group instance from the message by the leading tag

  • Get the value from the group specifying tag and entry index (entries are enumerated starting from 0).

To resize group simply modify the value of leading tag. Pay attention that this operation re-creates the group so you should populate values again.

To remove group simply remove leading tag from the message.

See Repeating group for usage samples.

../_images/FIXMessage.gif