Repeating groups in quickfix/c++
Asked Answered
N

2

5

I am writing a program that uses the quickfix library. The documentation is very poor, so I am requesting the help of SO fellows.

I have seen in the Group class that there are iterators. So I suppose that there is some STL-ish way of parsing repeating groups. Am I wrong? Can anybody provide a simple example for doing that?

Thank you very much in advance.

Nitaniter answered 12/12, 2010 at 21:58 Comment(1)
HEADS UP: even though the FAQ states different quickfix( as of 1.13.3 ) will not do repeating groups without a data dictionary. If you're seeing FieldNotFound exceptions being thrown for groups you know exist, double check your config.Recede
D
3

There are iterators in FieldMap class which is a super class of Message and Group class.

I'm not sure what do you mean by parsing repeating groups.

Fix engine parses raw fix messages for you when they arrive and your callback gets parsed FIX message - which has internal maps of tags (key/value) for tags in message header, body and tail.

Looking at 1.13.2 version of code, when the engine gets new string message from network it will eventually create a Message passing it the string. Message constructor then calls setString() on itself which effectively parses the received string and creates a map of tags.

If you look at Message::setString you can see that first the new field is added and then in setGroup it checks if the field is part of the group. If it is then this method, setGroup, takes over parsing of the following tags while those tags are part of the group. Once it comes across of tag that is not part of the group it stops parsing the group, it returns and continues parsing fields from message.

Now this all happens internally before the callback to your app where you handle received message.

There is a way to iterate over fields in a message. You can iterate over fields of header, body or over groups (and over each group).

const FIX40::ExecutionReport& msg; // new incoming message

// iterate over header
FIX::FieldMap::iterator it;
FIX::FieldMap::iterator b = msg.getHeader().begin();
FIX::FieldMap::iterator e = msg.getHeader().end();

for(it = b; it != e; ++it)
{
    switch(it->first)
    {
        case FIX::FIELD::MsgSeqnum:
              /* it->second.getString() - do something with tag data*/ ;
              break;
        ...
    }
}

And similarly for body:

FIX::FieldMap::iterator it;
FIX::FieldMap::iterator b = msg.begin();
FIX::FieldMap::iterator e = msg.end();

And there is groups iterator (FieldMap::g_begin/g_end) as well so you could iterate over groups in msg or header and you can similarly iterate, or search, tags within each group.

Group as well as Message extends FieldMap so all the getField/setField functionality is shared across.

Internals ... skip if too much detail.

In the above example this code:

message.getGroup(1, group);
group.get(MDEntryType);

Effectively passes the call from message.getGroup(1, group) -> FieldMap::getGroup(1, group.field(), group) -> getGroupRef(num,field) -> m_groups.find(field) which gives you a vector of groups (vector<FieldMap*>) and returns the num element, aka the num group from the message (a FieldMap).

group.get(field) is created using macros for each tag which is effectively translated as (map).getField(field). During initialization the (map) for group is a reference to the object of which the tag is member of so it returns the tag from the specific group (see example src/C++/fix44/NewOrderSingle.h it has couple of internal classes which extend Group)

Hope that it makes some sense.

Danger answered 4/1, 2011 at 4:6 Comment(0)
F
5

Use Quickfix library alongwith the documentation of how FIX messages are constructed. Else it would be very difficult to decipher how the messages are organized.

This is an example from Quickfix website

Your message is the MarketDataSnapshotFullRefresh class object.

FIX::NoMDEntries noMDEntries; 
message.get(noMDEntries); -> 

You get the count of repeating groups, how many times you need to iterate over the object message to get all the entries. Remember FIX::NoMDEntries is a field.

FIX42::MarketDataSnapshotFullRefresh::NoMDEntries group; -> 

This is a little tricky. You go inside a message to get the groups. Here NoMDEntries is an enclosed class inside MarketDataSnapshotFullRefresh class. Remeber this is the class which will give you the data. Now either you run through a loop or write the same code multiple times to extract all the fields inside each group. getGroup gives you the group from which you extract fields. getField will give you the field data. Most of the nomenclature of Quickfix is FIX messages. So refer a FIX message website like Fiximate and your life will be much easier.

FIX::MDEntryType MDEntryType;
FIX::MDEntryPx MDEntryPx;
FIX::MDEntrySize MDEntrySize;
FIX::OrderID orderID;

message.getGroup(1, group);
group.get(MDEntryType);
group.get(MDEntryPx);
group.get(MDEntrySize);
group.get(orderID);

message.getGroup(2, group);
group.get(MDEntryType);
group.get(MDEntryPx);
group.get(MDEntrySize);
group.get(orderID);
Farce answered 13/12, 2010 at 14:58 Comment(2)
+1 for your lonk to Fiximate. However, you don't seem to answer my question about iterator (I've already read the Quickfix docs).Nitaniter
@Luca Martini - It will be easier for you to not use the internal iterators, primarily Field iterators. They will require the overhead of knowing which fields are at which position. Use the public functions to parse your messages using the functions provided to return you the groups. The get and set functions should be the functions which you should be using to parse the messages, unless and until you are doing changes to the library.Farce
D
3

There are iterators in FieldMap class which is a super class of Message and Group class.

I'm not sure what do you mean by parsing repeating groups.

Fix engine parses raw fix messages for you when they arrive and your callback gets parsed FIX message - which has internal maps of tags (key/value) for tags in message header, body and tail.

Looking at 1.13.2 version of code, when the engine gets new string message from network it will eventually create a Message passing it the string. Message constructor then calls setString() on itself which effectively parses the received string and creates a map of tags.

If you look at Message::setString you can see that first the new field is added and then in setGroup it checks if the field is part of the group. If it is then this method, setGroup, takes over parsing of the following tags while those tags are part of the group. Once it comes across of tag that is not part of the group it stops parsing the group, it returns and continues parsing fields from message.

Now this all happens internally before the callback to your app where you handle received message.

There is a way to iterate over fields in a message. You can iterate over fields of header, body or over groups (and over each group).

const FIX40::ExecutionReport& msg; // new incoming message

// iterate over header
FIX::FieldMap::iterator it;
FIX::FieldMap::iterator b = msg.getHeader().begin();
FIX::FieldMap::iterator e = msg.getHeader().end();

for(it = b; it != e; ++it)
{
    switch(it->first)
    {
        case FIX::FIELD::MsgSeqnum:
              /* it->second.getString() - do something with tag data*/ ;
              break;
        ...
    }
}

And similarly for body:

FIX::FieldMap::iterator it;
FIX::FieldMap::iterator b = msg.begin();
FIX::FieldMap::iterator e = msg.end();

And there is groups iterator (FieldMap::g_begin/g_end) as well so you could iterate over groups in msg or header and you can similarly iterate, or search, tags within each group.

Group as well as Message extends FieldMap so all the getField/setField functionality is shared across.

Internals ... skip if too much detail.

In the above example this code:

message.getGroup(1, group);
group.get(MDEntryType);

Effectively passes the call from message.getGroup(1, group) -> FieldMap::getGroup(1, group.field(), group) -> getGroupRef(num,field) -> m_groups.find(field) which gives you a vector of groups (vector<FieldMap*>) and returns the num element, aka the num group from the message (a FieldMap).

group.get(field) is created using macros for each tag which is effectively translated as (map).getField(field). During initialization the (map) for group is a reference to the object of which the tag is member of so it returns the tag from the specific group (see example src/C++/fix44/NewOrderSingle.h it has couple of internal classes which extend Group)

Hope that it makes some sense.

Danger answered 4/1, 2011 at 4:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.