FIXForge C++ FIX Engine - Programmer's Guide

2.36.0.0

Content

Introduction

Onix Solutions FIXForge C++ FIX Engine is a C++ library that will FIX-enable applications written in C++. The FIX Engine provides the following services:

System Requirements

Development environment:

Deployment environment:

Getting Started

All FIX Engine classes are located in the FIXForge::FIX namespace, header files are assembled in the FIXForge_FIXEngine.h header file. The typical way of using the Engine is as follows:
  1. Initialize the Engine .
  2. Create the Session object.
  3. Establish the FIX session as Initiator or Acceptor.
  4. Send and receive application-level FIX messages.
  5. Disconnect the session.
  6. Shutdown the Engine.

Error-reporting

Exception handling is used as a fundamental error-reporting mechanism. In the event of any errors arising the FIXForge::FIX::EngineException is thrown.

Engine

To initialize the FIX Engine class library one of the FIXForge::FIX::Engine::init methods is used.
Warning:
This method must be called before all other FIX Engine library methods.
The FIXForge::FIX::Engine::init(const std::string& configFile) method is used to specify the configuration file.

To shutdown the Engine the FIXForge::FIX::Engine::shutdown method is used.

Warning:
No other FIX Engine library methods must be called after this method.
Example:
#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;

try{
    Engine::init();

    // Session-related logic...

    Engine::shutdown();
}catch(const EngineException& ex){
    clog << "Exception: " << ex.what() << endl;
}

FIX Version

As the FIX protocol evolves its new versions will be released to you to extend the current functionality. Supported FIX versions are: FIX 4.0, FIX 4.1, FIX 4.2, FIX 4.3 and FIX 4.4. The FIXForge::FIX::Version enum is used to identify them.

Example:

Version currentFixVersion = FIX_44;

Each FIX version has its own namespace that contains objects that are unique for the version, e.g.:

using namespace FIXForge::FIX::FIX40;

Message

The general format of a FIX message is a stream of <tag=value> fields with a field delimiter (SOH) between fields in the stream (so-called "tag=value FIX format").

Below is an example of a FIX message:

FIXMessage.gif

It is represented with the FIXForge::FIX::Message class.

To create a message the FIXForge::FIX::Message(const std::string& type, FIXForge::FIX::Version version) constructor is used.

To parse a message in the raw (tag=value) FIX format the FIXForge::FIX::Message(const std::string& rawMessage) constructor is used.

To validate a message the FIXForge::FIX::Message::validate method is used. This method checks for the presence of required fields.

There are several overloaded methods FIXForge::FIX::Message::toString() to simplify debugging and monitoring. To update the BodyLength (9) and CheckSum (10) fields the FIXForge::FIX::Message::updateCheckSum() method is used.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;

{
    Message order("D", FIX_42); // New Order - Single (MsgType = D)
    order.updateCheckSum();
    clog << "Order" << order << endl;
}

{
    string rawMsg = "8=FIX.4.0\0x019=86\0x0135=D\0x0149=0\0x0156=0\0x0134=1\0x0152=99990909-17:17:17\0x0111=90001008\0x0121=1\0x0155=IBM\0x0154=1\0x0138=10\0x0140=1\0x0159=0\0x0110=191\0x01";
    Message order(rawMsg);
    order.validate();

    clog << order.toString() << endl;
    clog << order.toString(' ') << endl;
    clog << order.toString(Message::TAG_NAME | Message::TAG_NUMBER) << endl;
}

Fields

To set a field value the FIXForge::FIX::Message::set method is used.

To get a field value the FIXForge::FIX::Message::get method is used.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;
using namespace FIXForge::FIX::FIX40;

Message order("D", FIX_40); // New Order - Single

order.set(11, "Unique identifier of execution message");
string ClOrdID = order.get(11);

To remove a field the FIXForge::FIX::Message::remove method is used.

The FIXForge::FIX::FIX42::Tags class contains the constants for the tag values. This class is defined for each FIX version namespace. The use of these constants makes the source code more readable.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;
using namespace FIXForge::FIX::FIX40;

Message order("D", FIX_40); // New Order - Single
order.set(Tags::ClOrdID, "90001008");
order.set(Tags::Side, "1");
order.set(Tags::TimeInForce, "0");

See also:
Repeating Group.

Session

A FIX session is defined as a bi-directional stream of ordered messages between two parties within a continuous sequence number series. It is represented by the FIXForge::FIX::Session class.

To create a session the FIXForge::FIX::Session's constructors are used.

To terminate the session the FIXForge::FIX::Session::shutdown method is used.

A session has one of two possible roles: Acceptor or Initiator.

Acceptor is the receiving party of the FIX session. It listens for the incoming connection on the pre-defined port. The acceptor has responsibility to perform first level authentication and formally declare the connection request "accepted" through transmission of an acknowledgment Logon message.

Initiator establishes the telecommunications link and initiates the session via transmission of the initial Logon message.

To obtain the current role the FIXForge::FIX::Session::getRole method is used.

To establish the session as Acceptor the FIXForge::FIX::Session::logonAsAcceptor method is used.

To establish the session as Initiator the FIXForge::FIX::Session::logonAsInitiator method is used.

To disconnect the session the FIXForge::FIX::Session::logout method is used.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX; 
using namespace FIXForge::FIX::FIX40;

const string SENDER_COMP_ID = "SenderCompID";
const string TARGET_COMP_ID = "TargetCompID";
const Version VERSION = FIX_40;
const string HOST = "Localhost";
int ACCEPTOR_PORT = Engine::instance()->getListenPort();

ISessionListener listener;

Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);
Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);

acceptor.logonAsAcceptor(); 
initiator.logonAsInitiator(HOST, ACCEPTOR_PORT); // Sends the Logon message and waits for the acknowledgment Logon

// Message exchange and processing ...

acceptor.logout(); // Sends the Logout message and waits for the confirming Logout
initiator.logout();

acceptor.shutdown(); // Free resources
initiator.shutdown(); // Free resources

See also:
Session States, Custom Logon Message, Sequence Numbers.

Message Exchange

To send a message to counterparty the FIXForge::FIX::Session::send method is used. As soon as a session is created it is possible to start sending messages via the session. If the session is not established, the messages will be sent when the connection is established with the counterparty.

To receive incoming application-level messages it is necessary to override the FIXForge::FIX::ISessionListener::onInboundApplicationMsg method.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;
using namespace FIXForge::FIX::FIX42;

class SessionListener : public ISessionListener{
    public:
    
    virtual void onInboundApplicationMsg(const Message& msg, Session* sn){
        clog << "Incoming application-level message: " << msg << endl;
        // processing of the application-level incoming message...
    }
};

const string SENDER_COMP_ID = "AcceptorAndInitiator_SND";
const string TARGET_COMP_ID = "AcceptorAndInitiator_TRG";

const Version VERSION = FIX_42;

const string ACCEPTOR_HOST = "localhost";
int ACCEPTOR_PORT = Engine::instance()->getListenPort();

SessionListener listener;

Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);
acceptor.logonAsAcceptor();

Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);
initiator.logonAsInitiator(ACCEPTOR_HOST, ACCEPTOR_PORT);

Message order("D", VERSION); 

order.set(Tags::ClOrdID, "Unique identifier for Order as assigned by the buy-side");
order.set(Tags::HandlInst, "1");
order.set(Tags::Symbol, "Ticker symbol");
order.set(Tags::Side, "1");
order.set(Tags::TransactTime, "20051012-22:10:11");
order.set(Tags::OrdType, "1");

order.validate();

acceptor.send(&order);

// continue the message exchange...

acceptor.logout();
initiator.logout();

acceptor.shutdown(); 
initiator.shutdown();

Sequence Numbers

All FIX messages are identified by a unique sequence number (the FIXForge::FIX::Message::getSeqNum() method).

Sequence numbers are initialized at the start of each FIX Session starting at 1 (one) and increment throughout the session. Each session establishes an independent incoming and outgoing sequence series. A single FIX session can exist across multiple sequential (not concurrent) physical connections. Parties can connect and disconnect multiple times while maintaining a single FIX session.

In other words, FIX Session is comprised of one or more FIX Connections.

Resetting the inbound and outbound sequence numbers back to 1, for whatever reason, constitutes the beginning of a new FIX session. Monitoring sequence numbers enables parties to gracefully synchronize applications when reconnecting during a FIX session.

To get or set the expected sequence number of the next incoming message the FIXForge::FIX::Session::getInSeqNum(), FIXForge::FIX::Session::setInSeqNum() methods are used.

To get or set the sequence number of the next outgoing message the FIXForge::FIX::Session::getOutSeqNum(), FIXForge::FIX::Session::setOutSeqNum() methods are used.

To disconnect the FIX Connection while maintaining a single FIX Session the FIXForge::FIX::Session::logout() method is used.

It is possible to continue the session later using the FIXForge::FIX::Session::logonAsAcceptor() or FIXForge::FIX::Session::logonAsInitiator() methods again.

To terminate a FIX Session the FIXForge::FIX::Session::shutdown() method is used.

The Engine automatically synchronizes sequence numbers when reconnecting during a FIX session on the base of the information previously stored in log files.

To synchronize sequence numbers manually FIXForge::FIX::Session::setInSeqNum() and FIXForge::FIX::Session::setOutSeqNum() methods are used (before FIXForge::FIX::Session::logonAsAcceptor() or FIXForge::FIX::Session::logonAsInitiator() method calls).

SequenceNumbers.gif

Some implementations of FIX protocol (FIX Dialects) expect that the FIX Session coincides with FIX Connection, in other words that the sequence numbers are reset back to 1 after the Logout messages exchange. To interact with such FIX dialects, the keepSequenceNumbersAfterLogout parameter of FIXForge::FIX::Session's constructor should be set to false.

In this case after FIXForge::FIX::Session::shutdown() method sequence numbers are set back to 1. Next time when the FIXForge::FIX::Session object is created incoming and outgoing sequence numbers will start from 1 (in other words, a new FIX Session will be created).

Administration

License File

The license file (FIXForge.Cpp.FIX.Engine.lic) must be placed in the same directory as the FIX Engine DLL (FIXForge.Cpp.FIX.Engine_*.dll).

Persistent message storage and the log files

The MsgStorage folder must be created for storing log data. Incoming and outgoingmessages, session's state data and the FIX Engine log file (FixEngineLog.txt) are stored in this folder.

For each FIX session two files are created:

SESSION_NAME is formed on the base of SenderCompID, TargetCompID and a timestamp.

When the FIXForge::FIX::Session object is created anew after the Engine's restart, FIX Session's state (the sequence numbers of last received and sent messages, previously sent messages, etc) is restored from these files.

To start a FIX session as a new one (so called "clean start"), it is necessary to remove the log files from the previous runs.

Connecting parties must bi-laterally agree as to when sessions are to be started/stopped and log files are backed up based upon individual system and time zone requirements.

When the FIX session is finished, the log files are not needed anymore. They can be backed up and later a new FIX session with the same SenderCompID and TargetCompID will start sequence numbers from 1. The usual practice is to backup the log files at the end of each business day (so called "End Of Day procedure") to start the sequence numbers from 1 at the beginning of the next day.

See also:
Log.Directory, Log.FlushFileAfterEachMessage, Log.InboundMessages, Sequence Numbers.

Settings

The default values of FIX Engine settings can be changed using the configuration file that is given as a parameter of FIXForge::FIX::Engine::init(const std::string& configFile) method.

Example:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <section name="FixEngine" type="System.Configuration.NameValueSectionHandler"/>
    </configSections>

    <FixEngine>
        <add key="Dialect" value="LavaDialect.xml"/> 
        <add key="ListenPort" value="4500"/>
        <add key="Log.InboundMessages" value="true"/>
        <add key="Validate.NumberOfRepeatingGroupInstances" value="false"/> 
        <add key="Validate.RequiredFields" value="true"/>
        <add key="Resending.QueueSize" value="2500"/>
        <add key="Validate.UnknownFields" value="true"/>
        <add key="Validate.UnknownMessages" value="true"/>
    </FixEngine> 
</configuration>

FIX Engine configuration settings
Setting Description Default value

ConnectionRetries.Number Number of attempts to restore the telecommunication link. 3

ConnectionRetries.Interval The time interval between the attempts to restore the telecommunication link (in seconds). 30

Dialect Specify the description of the FIX_Dialect. Empty
ListenPort FIX Engine listens on this port for incoming connections.
   If '0' then only session-initiators can be created.
   If '-1' then the telecommunication level is disabled and only message parsing/assembling can be used.
0
Log.Directory Inbound and outboundmessages, session's state data and the FIX Engine log file (FixEngine.log) are stored in this directory. MsgStorage
Log.FlushFileAfterEachMessage Option to flush output files after each logged message. True
Log.InboundMessages Option to log inbound messages. True

Log.SessionSummary Option to create a summary log file with inbound and outbound messages (in *.summary file). True

Resending.QueueSize Number of sent messages that are available for resending on counterparty's Resend Request <2> message. 1000

SSL.CertificateFile The path to the SSL certificate file in (Privacy Enhanced Mail) Base64 encoded (.pem) format. Empty

SSL.ListenPort FIX Engine listens on this port for incoming SSL connections. If it is set to '0' then only SSL-based session-initiators can be created. If '-1' then the SSL encryption is disabled. 0

SSL.PrivateKeyFile The path to the SSL private key file in (Privacy Enhanced Mail) Base64 encoded (.pem) format. Empty

SSL.PrivateKeyPassword The password to load private keys that are protected by a password. Empty

SSL.VerifyPeer Option to request client certificates and perform the certificate verification. False

Validate.NumberOfRepeatingGroupInstances Option to validate that the declared number of Repeating Group instances is equal to the actual one. True
Validate.RequiredFields Option to validate the presence of required fields in inbound and outbound messages. False
Validate.UnknownFields Option to validate the presence of unknown fields (fields that do not belong to the message in accordance with the FIX protocol or its FIX Dialect. False

Validate.UnknownMessages Option to validate the presence of unknown FIX messages (messages that do not belong to the message in accordance with the FIX protocol or its FIX Dialect. False

See also:
Engine

Advanced

Repeating Group

It is permissible for fields to be repeated in the same message within a repeating group. For example,
"215=2<SOH></a>216=2<SOH>217=Dest_1<SOH>216=4<SOH>217=Dest_2<SOH>"
represents a repeating group with two repeating instances "delimited" by tag 216 (first field in the repeating group.). The NoRoutingIDs<215> field specifies the number of repeating group instances (2 in this case). This is so called NumberOfInstances field. The NumberOfInstances field must immediately precede the repeating group contents (repeating group instances).

RepeatingGroup.gif

The FIX repeating group is represented with the FIXForge::FIX::Group class.

To get the Group object that represents the existing repeating group of the message the FIXForge::FIX::Message::getGroup(int numberOfInstancesTag) method is used.

To create a new repeating group or modify the number of instances in the existing one the FIXForge::FIX::Message::setGroup(int numberOfInstancesTag, int numberOfInstances) method is used.

To remove a repeating group method FIXForge::FIX::Message::remove(int numberOfInstancesTag) is used.

The FIXForge::FIX::Group class works with fields and embedded repeating groups in the same manner as the FIXForge::FIX::Message class, but each method has an additional parameter that defines the index of the repeating group instance (starting from 0).

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;
using namespace FIXForge::FIX::FIX42;

Message request("V", FIX_42);

request.set(Tags::MDReqID, "ABSD");
request.set(Tags::SubscriptionRequestType, 1);
request.set(Tags::MarketDepth, 1);
request.set(Tags::MDUpdateType, 1);
request.set(Tags::AggregatedBook, "N");

// create a repeating group NoMDEntryTypes with two instances
Group* groupMDEntryTypes = request.setGroup(Tags::NoMDEntryTypes, 2);
groupMDEntryTypes->set(Tags::MDEntryType, 0, "EntryType_1"); // first instance
groupMDEntryTypes->set(Tags::MDEntryType, 1, "EntryType_2"); // second instance

// create a repeating group NoRelatedSym with two instances
Group* groupRelatedSym = request.setGroup(Tags::NoRelatedSym, 2);
groupRelatedSym->set(Tags::Symbol, 0, "EURUSD_0"); // first instance
groupRelatedSym->set(Tags::Symbol, 1, "EURUSD_1"); // second instance

request.validate();

clog << request << endl;

Session States

To obtain the current session state the FIXForge::FIX::Session::getState() method is used.

The states of the FIX session are listed below.
FIX Session states
State Description
Role == Acceptor Role == Initiator
DISCONNECTED The session is disconnected.
LOGON_IN_PROGRESS The session is waiting for the initial Logon message. The initial Logon message was sent and the session is waiting for the acknowledgment Logon message.
ACTIVE The session is fully established (after the successful Logon exchange).
RECONNECTING N/A (only session-initiator can be in this state). Session-initiator is trying to restore the telecommunication link.
LOGOUT_IN_PROGRESS The initial Logout message was sent and the session is waiting for the acknowledgment Logout message.

To be notified about the changes in the session stateoverwrite the FIXForge::FIX::ISessionListener::onStateChange method.

Example:

class Listener : public ISessionListener{
public :
    virtual void Listener::onStateChange(Session::State newState, Session::State prevState, Session* sn){       
        clog << "\nSession's state is changed, prevState=" << Session::state2string(prevState) 
             << ", newState=" << Session::state2string(newState) << endl;
    }
};

Session Events

To be notified about session events overwrite the FIXForge::FIX::ISessionListener class methods.

The methods of the FIXForge::FIX::ISessionListener class are listed below.

Session events
Method (Event handler) Description
onStateChange Session state is changed.
onError Error condition is detected.
onInboundApplicationMsg Application-level message is received from the counterparty.
onInboundSessionMsg Session-level message is received from the counterparty.
onOutboundApplicationMsg Application-level message will be sent to the counterparty.
onOutboundSessionMsg Session-level message will be sent to the counterparty.

onResendRequest Sent application-level message is about to be resent to the counterparty.
onWarning Warning condition is detected.

Warning:
It is important not perform time-consuming tasks inside event handlers.

Custom Logon Message

Sometime there is need to set additional fields (e.g. Username (553), Password (554)) in the initiation Logon message. In this case the FIXForge::FIX::Session::logonAsInitiator(const std::string &host, int port, int heartBtInt, Message *customLogonMsg) method must be used.

Example:

#include <FIXForge_FIXEngine.h>

using namespace FIXForge::FIX;
using namespace FIXForge::FIX::FIX43;

const string SENDER_COMP_ID = "CustomLogonMessage_SND";
const string TARGET_COMP_ID = "CustomLogonMessage_TRG";

const Version VERSION = FIX_43;

const int HBI = 30;
const string USERNAME = "USER_NAME";
const string PASSWORD = "PASSWORD";

int port = Engine::instance()->getListenPort();

ISessionListener listener;

Session acceptor(SENDER_COMP_ID, TARGET_COMP_ID, VERSION, &listener);
acceptor.logonAsAcceptor();
Session initiator(TARGET_COMP_ID, SENDER_COMP_ID, VERSION, &listener);

Message customLogonMsg("A", FIX_43);

customLogonMsg.set(Tags::Username, USERNAME);
customLogonMsg.set(Tags::Password, PASSWORD);

initiator.logonAsInitiator("localhost", port, HBI, &customLogonMsg);

// message exchange and processing ...

acceptor.logout();
initiator.logout();

acceptor.shutdown();
initiator.shutdown();

FIX Dialects

It is not uncommon for firms to implement slightly different interpretations of the FIX protocol (dialects), so sometime there is need to validate that such messages confirm to a particular FIX dialect.

The FixEngine.Dialect configuration setting specifies the description of such dialects in XML format. This description must confirm to the Dialect.xsd XML Schema file.

To add a new user-defined field to a FIX Message add the corresponding Field entity to the FIX Dialect description. For example:

<FIX version="4.0">
    <Message type="D">
        <Field tag="526" name="SecondaryClOrdID"/> <!-- Does not belong to Standard FIX 4.0 --> 
    </Message> 
</FIX>

To add a new user-defined repeating group to a FIX Message add the corresponding Group entity to the FIX Dialect description. For example:

<FIX version="4.0">
    <Message type="D">
        <Group numberOfInstancesTag="78" name="NoAllocs"> <!-- Number of repeating groups for pre-trade allocation, does not belong to Standard FIX 4.0 -->
            <Field tag="79" name="AllocAccount"/> <!--  Does not belong to Standard FIX 4.0 --> 
            <Field tag="661" name="AllocAcctIDSource"/> <!--  Does not belong to Standard FIX 4.0 --> 
            <Field tag="736" name="AllocSettlCurrency"/> <!--  Does not belong to Standard FIX 4.0 --> 
            <!-- Other group fields -->
        </Group>
    </Message> 
</FIX>

To make a field, which is required according to the FIX Protocol specification, optional, and visa-versa, add the corresponding Field entity to the FIX Dialect description and set the isRequired attribute accordingly. For example:

<FIX version="4.0">
    <Message type="D">
        <Field tag="21" isRequired="false" name="HandlInst"/> <!-- Required in Standard FIX 4.0, but optional in this FIX dialect --> 
        <Field tag="109" isRequired="true" name="ClientID"/> <!-- Optional in Standard FIX 4.0, but required in this FIX dialect --> 
    </Message> 
</FIX>

To define a User Defined Message add the corresponding Message entity to the FIX Dialect description. For example:

<FIX version="4.0">
    <Message type="UserDefinedMessage_1">
        <Field tag="100"/> 
        <Field tag="101"/> 
    </Message> 
</FIX>

Such a user-defined message can be used exactly the same way as the standard FIX Message:

Message udm_1("UserDefinedMessage_1", FIX_43);

udm_1.set(100, "Field 100");
udm_1.set(101, "Field 101");

udm_1.validate();

clog << "UDM: " << udm_1 << endl;

Example of a FIX Dialect description file:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="Lava">

<FIX version="4.2"> 
    <Message type="N">      
        <Group numberOfInstancesTag="73" name="RefAllocID">
            <!-- An additional field in the existing repeating group -->
            <Field tag="37" name="OrderID"/>            
        </Group>
    </Message>
</FIX>
    
<FIX version="4.3">
    <Message type="y">
        <Group numberOfInstancesTag="146" name="NoRelatedSym">
            <!-- An additional field in the existing repeating group -->
            <Field tag="64" isRequired="true" name="FutSettDate"/>
        </Group>
    </Message>
        
    <Message type="W">
        <Group numberOfInstancesTag="268" name="NoMDEntries">
            <!-- An additional field in the existing repeating group -->
            <Field tag="278" name="MDEntryID"/>
        </Group>
        <Field tag="64" name="FutSettDate"/>
    </Message>
  
    <Message type="X">
        <!-- An additional field -->
        <Field tag="55" name="Symbol"/>

        <!-- An additional field -->
        <Field tag="64" name="FutSettDate"/>
    </Message>
</FIX>
</Dialect>

Resend Request processing

When the Resend Request (4) message is received from the counterparty and the application has overridden the FIXForge::FIX::ISessionListener::onResendRequest() method, this method is called. Otherwise the sent application-level message is re-sent immediately.

If the sent application-level message should not be resent to the counterparty (e.g. an aged order) then the FIXForge::FIX::ISessionListener::onResendRequest() method should return false. In this case the Sequence Reset-GapFill (4) message will be sent instead.

SSL encryption

To use the Ssl (Secure Sockets Layer) connectivity the following steps should be taken:

  1. If the counterparty requires client-side SSL certificate set the SSL.CertificateFile and SSL.PrivateKeyFile FIX Engine configuration settings. They can refer to the same file if it contains both the SSL certificate and the private key.
  2. Set the encryption to FIXForge::FIX::Session::SSL using the FIXForge::FIX::Session::setEncryptionMethod() method right after the creation of the FIXForge::FIX::Session object.
  3. Establish the FIX Connection as usual.

For example:

ISessionListener listener;      

Session initiator("SenderCompIDValue", "TargetCompIDValue", FIX_42, &listener);
initiator.setEncryptionMethod(Session::SSL);
        
initiator.logonAsInitiator("localhost", 443, true);

// Message exchange ... 
                
initiator.logout("SSL connection is finished.");
initiator.shutdown();   

Format of SSL certificates

Only the (Privacy Enhanced Mail) Base 64 Encoded (.pem) SSL certificates are supported.

To convert into this format from other format types, the openssl command-line tool could be used (http://www.openssl.org).

For example, to convert from "Personal Information Exchange - PKCS#12" (.pfx) to "Base64 Encoded" (.pem), the following command is run on the PFX file:

openssl pkcs12 -in <file_name>.pfx -out <file_name>.pem -nodes 

Per-session SSL settings

Per-session SSL settings ara available via FIXForge::FIX::Session::setSslCertificateFile() and FIXForge::FIX::Session::setSslPrivateKeyFile() methods.

For example:

const string targetCompID = "CNX"; 
const string host = "TargetHost"; 

{ // Stream FIX Session 

    const string streamSenderCompID = "str"; 
    ISessionListener listener;  
    Session streamSession(streamSenderCompID, targetCompID, FIX_42, &listener); 
    streamSession.setEncryptionMethod(Session::SSL); 

    const string streamSslCertificateAndPrivateKeyFile = "str.pem"; 
    // If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File. 
    streamSession.setSslCertificateFile(streamSslCertificateAndPrivateKeyFile);
    streamSession.setSslPrivateKeyFile(streamSslCertificateAndPrivateKeyFile);

    const int streamPort = 442;
    streamSession.logonAsInitiator(host, streamPort, 30, true);

    clog << "Stream session is established" << endl;

    streamSession.logout();
}

{ // Trading FIX Session 

    const string tradingSenderCompID = "tr"; 
    ISessionListener listener;  
    Session tradingSession(tradingSenderCompID, targetCompID, FIX_42, &listener);
    tradingSession.setEncryptionMethod(Session::SSL); 

    const string tradingSslCertificateAndPrivateKeyFile = "tr.pem";
    // If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File.
    tradingSession.setSslCertificateFile(tradingSslCertificateAndPrivateKeyFile);
    tradingSession.setSslPrivateKeyFile(tradingSslCertificateAndPrivateKeyFile);

    const int tradingPort = 443;
    tradingSession.logonAsInitiator(host, tradingPort, 30, true);

    clog << "Trading session is established" << endl;

    tradingSession.logout();
}

FAST encoding and decoding

FAST (FIX Adapted for Streaming) is a binary encoding method for message oriented data streams.

FAST-related classes can be found in the FIXForge::FIX::FAST_1_1 namespace.

To encode a FIX message into a FAST stream the FIXForge::FIX::FAST_1_1::Encoder class is used.

For example:

string xmlFastTemplate = readTextFile("UdpFastTemplate.xml");
const bool encodeEachMessageIndependently = true;
Encoder encoder(xmlFastTemplate, sourceFixMessage.getVersion(), encodeEachMessageIndependently);

const int fastTemplateID = 36;      
const size_t bufferSize = 1024;
char fastStreamChunk[bufferSize];
size_t chunkSize = encoder.encode(sourceFixMessage, fastTemplateID, fastStreamChunk, bufferSize);

To decode a part of a FAST stream back into a FIX message the FIXForge::FIX::FAST_1_1::Decoder class is used.

For example:

const bool decodeEachMessageIndependently = true;
Decoder decoder(xmlFastTemplate, sourceFixMessage.getVersion(), decodeEachMessageIndependently);

const Message& decodedMessage = decoder.decode(fastStreamChunk, chunkSize);

FAST Template

Both FIXForge::FIX::FAST_1_1::Encoder and FIXForge::FIX::FAST_1_1::Decoder constructors require the string that contains XML-based FAST templates.

A FAST Template specifies the encoding and decoding rules in accordance with the FAST specification.

For example:

<?xml version="1.0" encoding="utf-8"?>
<templates>
    <template name="Market Data - Incremental Refresh (X)" id="88">
        <uInt32 name="BodyLength" id="9"/>
        <string name="MessageType" id="35">
            <constant value="X" />
        </string>
        <string name="SenderCompID" id="49">
            <copy/>
        </string>
        <string name="TargetCompID" id="56">
            <copy/>
        </string>
        <uInt64 name="MsgSeqNum" id="34">
            <increment value="1"/>
        </uInt64>
        <string name="SendingTime" id="52">
            <tail/>
        </string>
        <string name="PosDupFlag" id="43" presence="optional">
            <default/>
        </string>
        <sequence name="MDEntries">
            <length name="NoMDEntries" id="268"/>
            <string name="MDUpdateAction" id="279"/>
            <string name="Symbol" id="55"/>
        </sequence>
        <string name="CheckSum" id="10"/>
    </template>
<templates>

Field Types

The following field types are supported:

Field Example Notes
Signed 32-bit Integer <int32 name="MDEntrySize" id="271" presence="optional"> Min value: -2147483648
Max value: 2147483647
Unsigned 32-bit Integer <uInt32 name="BodyLength" id="9"/> Min value: 0
Max value: 4294967295
Signed 64-bit Integer <int64 name="MinQty" id="110"/> Min value: -9223372036854775808
Max value: 9223372036854775807
Unsigned 64-bit Integer <uInt64 name="MsgSeqNum" id="34"/> Min value: 0
Max value: 18446744073709551615
String <string name="SenderCompID" id="49"/> An optional charset attribute can be used to indicate the character set used in the string ("ascii" or "unicode").
Decimal <decimal name="MDEntryPx" id="270">
<exponent/>
<mantissa/>
</decimal>
Indicates that the field is represented by two parts: an exponent and a mantissa.
Byte Vector <byteVector name="RawData" id ="96" presence="optional"/> Sequence of bytes.
Sequence <sequence name="NoSecurityAltID" id="454" presence="optional">
<string name="SecurityAltID" id="455"/>
</sequence>

Specifies that the contained group of instructions should be used repeatedly to encode each element (e.g. to encode/decode a FIX Repeating Group).

A sequence can have an associated length field containing an unsigned integer indicating the number of encoded elements.

The optional presence attribute indicates whether the field is mandatory or optional. If the attribute is not specified, the field is mandatory.

The required name attribute identifies the corresponding field in the current FIX message type by the field name.

The optional id attribute identifies the corresponding field in the current FIX message type by the tag number.

Field Operators

A field that is not a Sequence can have a field operator. The Field Operator specifies an optimization operation for the field.

The following field operators are supported:

Field Operator Example Notes

Constant

<string name="MessageType" id="35">
<constant value="X" />
</string>

Specifies that the value of a field will always be the same initial value.

Is applicable to all field types.

Default

<string name="PosDupFlag" id="43" presence="optional">
<default = "N" />
</string>

Specifies that the value of a field is either present in the FAST stream or it will be the initial value.

Is applicable to all field types.

Copy

<uInt32 name="MDUpdateAction" id="279">
<copy value="1" />
</uInt32>

If the value is present in the stream it becomes the new previous value, otherwise the value of the field is the previous value.

Is applicable to all field types.

Increment

<uInt32 name="RptSeq" id="83">
<increment />
</uInt32>

If the value is present in the stream it becomes the new previous value, otherwise the value of the field is the previous value incremented by one.

Is applicable to Integer field types only.

Delta

<int32 name="MDEntrySize" id="271">
<delta />
</int32>

Specifies that a delta value is present in the stream. The field is obtained by combining the delta value with the previous value.

Is applicable to Integer, Decimal, String and Byte Vector field types.

Tail

<string name="SendingTime" id="52">
<tail/>
</string>

Specifies that a tail value is present in the stream. The value of the field is obtained by combining the tail value with the previous value.

Is applicable to String and Byte Vector fields with constant or increasing value length.

Template Identifier (Template ID)

Each FAST Template is assigned a Template Identifier which uniquely describes the encoding/decoding rules. More than one FAST template can be used to encode the same FIX message type, so the Template ID is supplied as an argument of the FIXForge::FIX::FAST_1_1::Encoder::encode method.

Dictionaries of previous values

Some Field Operators rely on a previous value. Previous values are maintained in named dictionaries. To reset the state of dictionaries (set the state of the previous values to undefined) the FIXForge::FIX::FAST_1_1::Encoder::reset and FIXForge::FIX::FAST_1_1::Decoder::reset methods are used.

Frequently Asked Questions (FAQ)

  1. Q. I need to continue the FIX Session starting from the specific message sequence number, but I have deleted the log files from the previous runs. How can I do this?

    A. You can use FIXForge::FIX::Session::setInSeqNum and FIXForge::FIX::Session::setOutSeqNum methods to set the start sequence numbers before establishing the session.

    See also:
    Sequence Numbers.
  2. Q. How can I customize the FIX Engine to work with non-standard FIX counterparties that employ user-defined fields and messages (use modifications of the FIX Protocol)?

    A. You need to define and use the corresponding XML-based FIX Dialect description. See: FIX Dialects.

  3. Q. How can I include the

    ResetSeqNumFlag (141) field in the Logon message?
    A. To send a Logon message with this field during FIX Connection establishment, use the Custom Logon Message . It is also possible to send a Logon message with the ResetSeqNumFlag set when the FIX Session is established (e.g. to maintain 24 hour connectivity). For example:

    Message logon("A", FIX_42);
    logon.set(141, "Y");
    
    sn.send(&logon);
    

  4. Q. What is the default behavior of the FIX Engine in case a Test Request <1> message was sent to the counterparty and the counterparty does not respond?
    A. When the response on the Test Request <1> message is not received during HeartBeatInt, the FIX Connection is considered lost. FIX Session-Acceptor changes its state to LOGON_IN_PROGRESS.

    FIX Session-Initiator changes its state to RECONNECTING and tries to restore the FIX Connection pre-configured number of times in pre-configured interval (using the binary exponential back off algorithm). Please note that FIX Engine automatically handles sending of Test Request messages (when needed).

    See also:
    ConnectionRetries.Number and ConnectionRetries.Interval.
  5. Q. How can I set SenderSubID and OnBehalfOfSubID fields in the Logon message?
    A. Please use Custom Logon Message.

    For example:

    customLogonMsg.set(Tags::SenderSubID, "SenderSubID_Value");
    customLogonMsg.set(Tags::OnBehalfOfSubID, "OnBehalfOfSubID_Value");
    

  6. Q. Why do I receive the
    "Invalid FIX Engine settings: Cannot open the persistent storage folder ('MsgStorage')"
    error (exception) when I try to run my FIX application as a Windows service? When I run my application as a standalone one, all work perfectly OK.
    A. The reason of this error is the different default current folder for Windows Service and Windows application. By default, the current directory for your Windows service is the System32 folder. To solve this issue specify the full path to the persistent storage folder using the Log.Directory setting.
    See also:
    Settings
  7. Q. How can I set SenderSubID, TargetSubID, SenderLocationID, TargetLocationID in all outgoing messages (including session-level ones)?

    A. You can use FIXForge::FIX::Session::senderSubID(const std::string &value), FIXForge::FIX::Session::targetSubID(const std::string &value), FIXForge::FIX::Session::senderLocationID(const std::string &value), FIXForge::FIX::Session::targetLocationID(const std::string &value) methods of the FIXForge::FIX::Session object.

Glossary

Acceptor
Session-acceptor is the receiving party of the FIX session. It listens for the incoming connection on the pre-defined port. The acceptor has responsibility to perform first level authentication and formally declare the connection request "accepted" through transmission of an acknowledgment Logon message.

Conditionally required fields
Fields which are required based on the presence or value of other fields.

Delimiter character (SOH)
The non-printing, ASCII "SOH" (hex: 0x01, referred to in this document as SOH), is used for field termination.

MsgSeqNum field
Integer message sequence number, the tag number is 34.

FIX
The Financial Information Exchange (FIX) Protocol is a message standard developed to facilitate the electronic exchange of information related to securities transactions. It is intended for use between trading partners wishing to automate communications.

FIX Connection
It is comprised of three parts: logon, message exchange, and logout.

FIX Dialect
This is a custom, slightly different interpretation of FIX protocol.

FIX Session
It is comprised of one or more FIX Connections, meaning that a FIX Session spans multiple logins.

Initiator
Session-Initiator establishes the telecommunications link and initiates the session via transmission of the initial Logon message.

Required Fields
Each message within the FIX protocol is comprised of required, optional and conditionally required fields (fields which are required based on the presence or value of other fields). Systems should be designed to operate when only the required and conditionally required fields are present.

SenderCompID field
Assigned value used to identify firm sending message, the tag number is 49.

TargetCompID field
Assigned value used to identify receiving firm, the tag number is 56.

User-defined fields
These fields are intended to be implemented between consenting trading partners and should be used with caution to avoid conflicts, which will arise as multiple parties begin implementation of the protocol. The tag numbers 5000 to 9999 have been reserved for them. These tags can be registered/reserved via the FIX website.

User-defined messages
Messages those format is privately defined between the sender and receiver. A "U" as the first character in the MsgType field (i.e. U1, U2, etc) indicates such messages.

Resources

FIX Dictionary - http://www.onixs.biz/fixdictionary.
Onix Solutions - http://www.onixs.biz.

Generated on Thu Jul 31 12:55:03 2008 for FIXForge C++ FIX Engine by  doxygen 1.5.2