Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Overview

This article would be interesting for those of you who has faced with FIX Antenna for the first time and want to touch and feel it.It will help you is intended to provide instructions on how to build your first application based on FIX Antenna so that you will be aware of possibilities FIX Antenna providesand aware you of its possibilities.

Application

Typically FIX application provides  FIX FIX connectivity to multiple clients  through through transport protocols and also offers possibilities to install, configure, administrate, and monitor trading information flows.

For our the case assume that , we need to build an app which that will be able to establish and terminate sessions and support the simplest Order simplest Order Flow presented below:

Image Modified

The main steps which need to be implemented in order to cover declared functionality are:

  • Initialize FIX engine
  • Create session (an initiator or acceptor )session
  • Send messages
  • Process incoming messages
  • Close session
  • Destroy the engine (to release resources)

This section describes how to create the application will step-by-step explain how to create the application with code examples.  Follow Follow the instructions below to write, compile, and run your first application with FIX Antenna C++.

Engine initialization

Use the instruction instructions below to initialize the FIX engine.:

Code Block
languagebashcpp
// Initialize engine.
FixEngine::init();

The " engine.properties " configuration file contains common FIX engine configuration parameters. If a full path is not specified FIX engine is looking looks in the current directory otherwise FIX engine uses a full path to locate the properties file.:

Code Block
languagebashcpp
// Initializes engine.
FixEngine::init("engine.properties");

If an error occurs during initialization (e.g. the properties file cannot can not be found, a required property is missing, etc.) the exception is thrown.:

Code Block
languagebashcpp
// Initialize engine.
try {
   FixEngine::init("engine.properties");
} 
catch( const Utils::Exception& ex ) {
   cout << "ERROR: " << ex.what() << endl;
}

For more information about FIX engine description refer to the section Engine description section.

Session creation

Creation of

Create acceptor session

-acceptor

You can create a an acceptor session acceptor in three steps:


Code Block
languagebashcpp
// Declare Application - FIX session observer
class MyApplication : public Engine::Application {
    // Override several virtual methods
    virtual bool process(const Engine::FIXMessage& msg, const Engine::Session& sn) { 
        return true; 
    }
    virtual bool onResend(const Engine::FIXMessage& msg, const Engine::Session& sn) {
        return true; 
    }
    
    virtual void onLogonEvent(const Engine::LogonEvent* event, const Engine::Session& sn) {}
    virtual void onLogoutEvent(const Engine::LogoutEvent* event, const Engine::Session& sn) {}
    virtual void onUnexpectedMessageEvent(const Engine::UnexpectedMessageEvent* apEvent, const Engine::Session& aSn) {}
    virtual void onSequenceGapEvent(const Engine::SequenceGapEvent* event, const Engine::Session& sn) {}
    virtual void onSessionLevelRejectEvent(const Engine::SessionLevelRejectEvent* event, const Engine::Session& sn) {}
    virtual void onMsgRejectEvent(const Engine::MsgRejectEvent* event, const Engine::Session& sn) {}
    virtual void onHeartbeatWithTestReqIDEvent(const Engine::HeartbeatWithTestReqIDEvent& event, const Engine::Session& sn) {}
    virtual void onResendRequestEvent(const Engine::ResendRequestEvent& event, const Engine::Session& sn) {}
    virtual void onNewStateEvent(const Engine::NewStateEvent& event, const Engine::Session& sn) {}
    virtual void onUnableToRouteMessage(const Engine::UnableToRouteMessageEvent& event, const Engine::Session& sn) {}
};
// Create instance of Application
MyApplication application;
// Create instance of FIX session 
Engine::Session* pSA =  Engine::FixEngine::singleton()->createSession(&application, "Sender", "Target", Engine::FIX44);
// Connect session as acceptor
pSA->connect();

For more information about FIX session in general and FIX session acceptors description please refer to the sections  Session description section.

Creation of

Create initiator session

-initiator

You can create a an initiator session initiator in three steps:


Code Block
languagebashcpp
// Declare Application - FIX session observer
class MyApplication : public Engine::Application {
    // Override several virtual methods
    virtual bool process(const Engine::FIXMessage& msg, const Engine::Session& sn) { 
        return true; 
    }
    virtual bool onResend(const Engine::FIXMessage& msg, const Engine::Session& sn) {
        return true; 
    }
    
    virtual void onLogonEvent(const Engine::LogonEvent* event, const Engine::Session& sn) {}
    virtual void onLogoutEvent(const Engine::LogoutEvent* event, const Engine::Session& sn) {}
    virtual void onUnexpectedMessageEvent(const Engine::UnexpectedMessageEvent* apEvent, const Engine::Session& aSn) {}
    virtual void onSequenceGapEvent(const Engine::SequenceGapEvent* event, const Engine::Session& sn) {}
    virtual void onSessionLevelRejectEvent(const Engine::SessionLevelRejectEvent* event, const Engine::Session& sn) {}
    virtual void onMsgRejectEvent(const Engine::MsgRejectEvent* event, const Engine::Session& sn) {}
    virtual void onHeartbeatWithTestReqIDEvent(const Engine::HeartbeatWithTestReqIDEvent& event, const Engine::Session& sn) {}
    virtual void onResendRequestEvent(const Engine::ResendRequestEvent& event, const Engine::Session& sn) {}
    virtual void onNewStateEvent(const Engine::NewStateEvent& event, const Engine::Session& sn) {}
    virtual void onUnableToRouteMessage(const Engine::UnableToRouteMessageEvent& event, const Engine::Session& sn) {}
};
// Create instance of Application 
MyApplication application;
// Create instance of FIX session
Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession(&application, "Sender", "Target", Engine::FIX44);
// Connect session as initiator
pSI->connect(30, "127.0.0.1", 9106);

For more information about FIX session in general and FIX session initator description refer to the sections Session description.sessions in general and FIX session initiator description please refer to the Session description section.

Create session with custom FIX version

If there is a need to create a session explicitly and specify the FIX protocol version via API, the createSession() overload which accepts the scpProtocolName string parameter should be used.

The scpProtocolName string parameter contains the protocol ID (ID attribute from the .xml dictionary file) to use.

The following piece of code can be used to load the additional dictionary with a custom FIX protocol version:

Code Block
languagecpp
Engine::FixEngine::singleton()->loadProtocolFile( "custom_fix44.xml" );
Engine::ProtocolID pid = Engine::FixEngine::singleton()->createFixParser( "FIX44_MY" );
Engine::Session* pSaFIX44 = Engine::FixEngine::singleton()->createSession( &application, "SenderCompID_FIX44", "TargetCompID_FIX44", pid, &params );

Customizing Logon message

FIX Antenna HFT doesn't provide the ability to modify the particular tag in the Logon message, but it is possible to pass the whole Logon to update the values of some tags in it such as Sender, Target, etc.

The following piece of code can be used to create a custom Logon message:

Code Block
std::auto_ptr<Engine::FIXMessage> customLogon;
 
if( !customLogonString .empty() ) {
    customLogon.reset( Engine::FIXMsgProcessor::singleton()->parse( customLogonString ) );
}
 
if( NULL == customLogon.get() ) {
    // Establishes the FIX session as Initiator.
    session_->connect( hbi,
                       host,
                       port,
                       Engine::NONE );
} else {
    // Establishes the FIX session as Initiator.
    session_->connect( hbi,
                       *customLogon,
                       host,
                       port,
                       Engine::NONE );
}

Creating new order

FIX Antenna provides two interfaces for FIX messages message manipulations:

  1. Flat model
  2. Object model

The flat model is based on a simple get/set FIXMessage interface and demonstrates high performance.:

Code Block
languagebashcpp
// create FIX 4.4 New Order Single skeleton
Engine::FIXMessage* pOrder = Engine::FIXMsgFactory::singleton()->newSkel(Engine::FIX44, "D");
// set ClOrdID
pOrder->set( FIXField::ClOrdID, "USR20000101" );
// get ClOrdID
Engine::FIXFieldValue clOrdID;
bool isPresent = pOrder->set( FIXField::ClOrdID, &clOrdID );
assert( isPresent );
// set trading session
// create repeating group with 1 entry
pOrder->set( FIXField::NoTradingSessions, 1 );
// get pointer to the repeating group
Engine::FIXGroup *pGroup = pOrder->getGroup(FIXFields::NoTradingSessions);
// set trading session ID for the 1st entry
pGroup->set( FIXField::TradingSessionID, "PRE-OPEN", 0 );
// set all required fields ...

The object model is a typified interface that is less efficient but more user-friendly than the flat one.:

Code Block
languagebashcpp
// create FIX 4.4 New Order Single
FIX44::NewOrderSingle order( Engine::FIXMsgFactory::singleton()->newSkel(Engine::FIX44, "D") );
// set ClOrdID
order.ClOrdID().set( "USR20000101" );
// get ClOrdID
bool isPresent = !order.ClOrdID().isEmpty();
string clOrdID = order.ClOrdID();

For more information about FIX

message

messages and repeating groups refer to the

sections 

Message descriptionRepeating Groups description sections.

Sending order

To send a message to the session you should call call the Engine::Session::put method method. In fact, this method does not send the message but puts it to in the queue, from which the message will be sent out by a separate thread. The method in its turn returns immediately. In other words, sending is an asynchronous process in FIX Antenna, which also means that after the method returns message is not necessarily sent yet.:

Code Block
languagebashcpp
// Send order (flat model) to session initiator
pSI->put( pOrder);
// Send order (object model) to session acceptor
pSA->put( order.get() );

For more information about sending messages refer to the sections Send message and Send message sections.

Processing incoming message

The Application class is responsible for:

  • Processing incoming messages from the remote FIX Engine:


    Code Block
    languagebashcpp
    virtual bool Engine::Application::process(const Engine::FIXMessage &, const Engine::Session &aSn)
  • Processing session events (required only if the default behavior is not suitable):


    Code Block
    languagebashcpp
    virtual void Engine::Application::onResendRequestEvent(const Engine::ResendRequestEvent &,const Engine::Session &)
    ...

Create a new class derived from the Application class and override the Engine::Application::process method in this class to process incoming messages. If an incoming message is successfully processed, the method should return "'true"', if the message cannot be processed at the moment, it should be copied for further processing by the application.

Other useful methods to override are Engine::Application::onLogonEventEngine::Application::onLogoutEvent,Engine::Application::onSequenceGapEventEngine::Application::onSessionLevelRejectEvent, etc. These are the call-back callback methods called to notify about the corresponding session-level events.

Note that all pure virtual methods of the Application must be overridden (implementation can be just an empty body). The The Engine::Application::process method method is called only when the application-level message is received. All session-level messages (such as Heartbeats, Test Requests, Resend Requests, etc. ) are handled by FIX Antenna. However, you can modify default behavior by overriding call-back methods in the Application and providing your own logic.

if you
Note
Info

If there is a need to keep the FIX message for future processing create a the copy of the message and save a copy must be created and saved instead of saving the original message (refer to the Engineusing the Engine::FIXMsgProcessor::clone method)clone method. Below is an example of a custom implementation of Engineof the Engine::Application interfaceApplication interface:

Code Block
languagebash
class Appl : public Engine::Application{
public:
    virtual bool process(const Engine::FIXMessage & aMsg, const Engine::Session& aSn) {
        std::clog << "aMsg: " << *aMsg.toString('|') << std::endl;
        return true;
    }   
    virtual void onLogonEvent(const Engine::LogonEvent* apEvent, const Engine::Session& aSn) {
        std::clog << "LogonEvent, the Logon message was received: " << apEvent->m_pLogonMsg->toString() << std::endl;
    }  
    virtual void onLogoutEvent(const Engine::LogoutEvent* apEvent, const Engine::Session& aSn) {
        std::clog << "LogoutEvent, the Logout message was received: " << apEvent->m_pLogoutMsg->toString() << std::endl;
    }    
    virtual void onSequenceGapEvent(const Engine::SequenceGapEvent* apEvent, const Engine::Session& aSn) {
        std::clog << "SequenceGapEvent" << std::endl;
    }    
    virtual void onSessionLevelRejectEvent(const Engine::SessionLevelRejectEvent* apEvent, const Engine::Session& aSn) {
        std::clog << "SessionLevelRejectEvent" << std::endl;
    }      
    virtual void onMsgRejectEvent(const Engine::MsgRejectEvent* event, const Engine::Session& sn){
        std::clog << "MsgRejectEvent" << std::endl;
    }       
    virtual void onResendRequestEvent(const Engine::ResendRequestEvent &,const Engine::Session &) {
        std::clog << "ResendRequestEvent" << std::endl;
    }    
    virtual void onNewStateEvent(const Engine::NewStateEvent &,const Engine::Session &) {
        std::clog << "NewStateEvent" << std::endl;
    }    
    virtual void onUnableToRouteMessage(const Engine::UnableToRouteMessageEvent &,const Engine::Session &) {
        std::clog << "UnableToRouteMessage" << std::endl;
    }    
    virtual bool onResend(const Engine::FIXMessage &,const Engine::Session &) {
        std::clog << "Resend" << std::endl;
        return true;
    }    
    virtual void onHeartbeatWithTestReqIDEvent(const Engine::HeartbeatWithTestReqIDEvent &,const Engine::Session &) {
        std::clog << "HeartbeatWithTestReqIDEvent" << std::endl;
    }
};
Warning

Do not delete the registered Application until you unregister it

. For more information about processing incoming messages and Application class refer to the section Application description

.

Closing session

Use the following methods to close the session:

Code Block
language
bash
cpp
Engine::Session::disconnect( bool forcefullyMarkAsTerminated = false )
Code Block
language
bash
cpp
Engine::Session::disconnect( const std::string &logoutText, bool forcefullyMarkAsTerminated = false )

For more information about disconnect refer to the
sections 

Full sample

The sample below illustrates all aforementioned instructions combined in one application.:

Code Block
languagebashcpp
#include <iostream>
#include <memory>
#include <B2BITS_V12.h>
using namespace std;
class MyApp : public Engine::Application {
public:
    MyApp() {}
    virtual bool process(const Engine::FIXMessage& fixMsg, const Engine::Session& aSn) { 
        cout << *fixMsg.toString('|') << endl; 
        return true;
    }
    virtual void onLogonEvent(const Engine::LogonEvent* apEvent, const Engine::Session& aSn) {
        cout << "onLogonEvent" << endl;
    }
    virtual void onLogoutEvent(const Engine::LogoutEvent* apEvent, const Engine::Session& aSn) {
        cout << "onLogoutEvent" << endl;
    }
    virtual void onMsgRejectEvent(const Engine::MsgRejectEvent* event, const Engine::Session& sn) {
        cout << "onMsgRejectEvent" << endl;
    }
    virtual void onSequenceGapEvent(const Engine::SequenceGapEvent* apEvent, const Engine::Session& aSn) {
        cout << "onSequenceGapEvent" << endl;
    }
    virtual void onSessionLevelRejectEvent(const Engine::SessionLevelRejectEvent* apEvent, const Engine::Session& aSn) {
        cout << "onSessionLevelRejectEvent" << endl;
    }
    virtual void onHeartbeatWithTestReqIDEvent(const Engine::HeartbeatWithTestReqIDEvent& event, const Engine::Session& sn) {
        cout << "onHeartbeatWithTestReqIDEvent" << endl;
    }
    virtual void onResendRequestEvent(const Engine::ResendRequestEvent& event, const Engine::Session& sn) {
        cout << "onResendRequestEvent" << endl;
    }
    virtual void onNewStateEvent(const Engine::NewStateEvent& event, const Engine::Session& sn) {
        cout << "onNewStateEvent" << endl;
    }
    virtual void onUnableToRouteMessage(const Engine::UnableToRouteMessageEvent& event, const Engine::Session& sn) {
        cout << "onUnableToRouteMessage" << endl;
    }
    virtual bool onResend(const Engine::FIXMessage& msg, const Engine::Session& sn) {           
        cout << "onResend" << endl;
        return true;
    }
};
int main( int argc, char* argv[] ) 
{
    try
    {
        // Initialize engine.
        Engine::FixEngine::init();
        // Create Application instance
        MyApp application;
        // Create FIX session instance
        Engine::Session* pSA =  Engine::FixEngine::singleton()->createSession(&application, "Sender", "Target", Engine::FIX44);
        // Connect session as acceptor
        pSA->connect();
        // Create FIX session instance
        Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession(&application, "Target", "Sender", Engine::FIX44);
        // Connect session as initiator
        pSI->connect(30, "127.0.0.1", Engine::FixEngine::singleton()->getListenPort());  
        // create FIX 4.4 New Order Single 
        auto_ptr<Engine::FIXMessage> pOrder(pSI->newSkel("D"));
        // set ClOrdID
        pOrder->set(FIXField::ClOrdID, "USR20000101" );
        pOrder->set(FIXField::HandlInst,    "2");
        pOrder->set(FIXField::Symbol,     "IBM");
        pOrder->set(FIXField::OrderQty,   "200");
        pOrder->set(FIXField::Side,         "1");
        pOrder->set(FIXField::OrdType,      "5");
        pOrder->set(FIXField::TimeInForce,  "0");
        //+++++++++++++++++++++
        // Send order to session initiator
        pSI->put(pOrder.get());
        // Close sessions
        pSI->disconnect();
        pSA->disconnect();
        // release resources
        pSA->registerApplication(NULL); 
        pSI->release();
        pSA->registerApplication(NULL); 
        pSA->release();
        Engine::FixEngine::destroy();
    }
    catch(std::exception const& ex) 
    {
        cout << " ERROR: " << ex.what() << endl;
        return -1;
    }
}