B2BITS FIX Antenna C++  2.31.0
FIX Message

Table of Contents

Please refer to the section Message description for more information about FIX Message.

Creating FIX message

FIX Message object can be created in two different ways:

  1. Create FIX message skeleton using FIX message factory and populate fields
  2. Create FIX message from the raw FIX message (byte array)

To create a skeleton for a FIX application-level message, use the Engine::FIXMsgFactory::newSkel(...) method. Then set all required field for the newly created FIX message object.

For example:

#include <assert.h>
#include <B2BITS_V12.h>
using namespace std;
// New Order - Single (MsgType D)
pFIXMessage->set(FIXField::ClOrdID, "90001008");
pFIXMessage->set(FIXField::Side, "1");
pFIXMessage->set(FIXField::TimeInForce, "0");

Use the FIXMsgProcessor::parse(...) method to parse a string containing a raw FIX message into the FIXMessage class.

For example:

std::string aRawMessage("8=FIX.4.49=5235=249=SC56=FE34=252=20090126-10:59:427=116=110=174");

Get field

Use the bool Engine::FIXMessage::get(int tag, Engine::FIXFieldValue *value) method to get the FIX field value.

This method retrieves the field value by tag number and stores it into an instance of the Engine::FIXFieldValue class. The field can be:

  1. Not defined for this message type by specification.
  2. Defined as optional for this message type by specification and absent in this message instance.
  3. Defined for this message type by specification and present in this message instance.

In the 1st case the method throws Utils::Exception exception. In the 2nd case the method returns "false". In the 3rd case the method returns "true" and the value is returned in the inout parameter.

try {
// ...
if( pMsg->get( FIXField::ClOrdID, &val ) )
cout << std::string(val.data_, val.length_) << endl;
catch( const Utils::Exception& ex ) {
cout << "ERROR: " << ex.what() << endl;

Set field

Use the bool Engine::FIXMessage::set(int tag, const Engine::FIXFieldValue &value) method to set a field value.

This method returns "true" if the given tag is found and the old value is replaced with the new one. Otherwise the method returns "false" (the given tag is inserted).

The method throws Utils::Exception exception if it cannot be executed (e.g. the given tag is not defined for this message type).

try {
// ...
pMsg->set(FIXField::ClOrdID, "90001008");
catch( const Utils::Exception& ex ) {
cout << "ERROR: " << ex.what() << endl;

Remove field

Use the bool Engine::FIXMessage::remove(int tag) method to remove a field by tag.

This method returns "true" if the given tag is found and the field is removed. Otherwise the method returns "false".

try {
// ...
catch( const Utils::Exception& ex ) {
cout << "ERROR: " << ex.what() << endl;

Repeating group

Please refer to the section Repeating Groups description for more information about repeating groups.

The Engine::FIXGroup class is designed to work with Repeating Groups. The access to the repeating groups is provided by the Engine::FIXMessage class. The common workflow when working with repeating groups is

In case of nested repeating groups the parent repeating group should be used to get pointer to the inner repeating group the same way it is done in FIX message. In theory the level of nesting is not limited by the FIX protocol standard.

To add repeating group to the message simply set value for the repeating group leading tag to the number of entries planned for the repeating group.

To resize repeating group simply modify the value of leading tag. When setting the new value for the leading tag, the group is re-created and old field values inside the group are erased.

The Engine::FIXGroup class contains methods to work with message fields, similar to those existing in the Engine::FIXMessage class, however in contrast to them, there is an additional argument defining index (a sequence number starting with 0) of the group entry, for example:

Use the Engine::FIXMessage::remove(int tag) method, where tag is a Repeating Group Leading Tag, to remove the Repeating Group. Setting the corresponding tag to zero is not allowed (Parser Exception is thrown).

If non-existing or invalid values are specified for the arguments in the methods above then exception is thrown.

Example below demonstrates how to work with repeating group.

// create a new message
// get the pointer to the group object
Engine::FIXGroup *pGroup = pMsg->getGroup(Engine::FIXField::NoQuoteSets); // tag 296
// pGroup is NULL because this message does not contain a FIX group so far
clog << "pGroup=" << pGroup << endl;
// create a new group with 2 entries
pMsg->set(Engine::FIXField::NoQuoteSets, 2);
// get pointer to the newly created group
pGroup = pMsg->getGroup(Engine::FIXField::NoQuoteSets);
// set value for the field in 1st and 2nd entries
pGroup->set( Engine::FIXField::QuoteSetID, "a", 0 );
pGroup->set( Engine::FIXField::TotNoQuoteEntries, "100", 0 );
pGroup->set( Engine::FIXField::QuoteSetID, "b", 1 );
pGroup->set( Engine::FIXField::TotNoQuoteEntries, "200", 1 );
// pGroup is not NULL because now this message contains a FIX group
clog << "pGroup=" << pGroup << endl;
// create nested repeating group for the entry at index 0 with size 1
pGroup->set( Engine::FIXField::NoQuoteEntries, "1", 0 );
// get pointer to the nested repeating group
pNestedGroup = pGroup->getGroup(Engine::FIXField::NoQuoteEntries);
// set value for nested group field
pNestedGroup->set( Engine::FIXField::QuoteEntryID, "aa", 0 );
// release the pointers
// remove group from the message

User defined fields

User Defined Fields (the tag numbers 5000 to 9999) are operated the same way as standard fields.

For example:

int theCustomTag = 5000; // reserved for user defined fields
// generates a new skeleton for a FIX message
pFIXMessage->set(theCustomTag , "0.15"); // sets the tag's value

Copy message

To copy FIX message, use the Engine::FIXMsgProcessor::clone(const Engine::FIXMessage &inMsg) method. For example:

Release message

To de-allocate resources used by FIX message, use the Engine::FIXMessage::release(Engine::FIXMessage *apMsg) method.

For example:

FIXMessage *pFIXMessage = FIXMsgProcessor::singleton()->parse(rawMsg);
cout << "pFIXMessage: " << *pFIXMessage->toString() << endl;
// Cloning FIXMessage
FIXMessage *pClonedFIXMessage = FIXMsgProcessor::singleton()->clone(*pFIXMessage);
cout << "pClonedFIXMessage: " << *pClonedFIXMessage->toString() << endl;
// The user is responsible for the de-allocation

Utils::AutoPtr helper can be used to automate cleanup procedure.

// Now apMessageCopy is the owner of FIX message; it will call release in its destructor
Utils::AutoPtr<FIXMessage> apMessageCopy( Engine::FIXMsgProcessor::singleton()->clone(*pMessage), &FIXMessage::release );
int size = 0;
const char *buf = apMessageCopy->toRaw(&size);
cout << "Copied message will be destroyed automatically. " << std::string(buf, size) << endl;

Message validation

FIX Antenna supports message validation. Validation can be switched on/off. Following are available validation options:

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

Here is sample how to validate message:

// Create message
std::auto_ptr<Engine::FIXMessage> newOrderSingle( Engine::FIXMsgFactory::singleton()->newSkel(Engine::FIX44, "D") );
catch( Utils::Exception const& e )
std::cerr << "Validation error: " << e.what() << std::endl;
// Fill session protocol required fields
newOrderSingle->set( FIXFields::SenderCompID, "Sender" );
newOrderSingle->set( FIXFields::TargetCompID, "Target" );
newOrderSingle->set( FIXFields::MsgSeqNum, 1 );
// Fill New Order Single message required fields
newOrderSingle->set( FIXFields::ClOrdID, "clordid" );
newOrderSingle->set( FIXFields::Price, 1 );
newOrderSingle->set( FIXFields::Side, '1' );
newOrderSingle->set( FIXFields::Symbol, "symbol" );
newOrderSingle->set( FIXFields::OrdType, '1' );
newOrderSingle->set( FIXFields::OrderQty, 10 );
//Validate message
std::cout << "Message is valid." << std::endl;
See also
How to enable Message validation for Engine::Session.