Repeating groups in quickfix/c++
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 e开发者_JAVA百科xample for doing that?
Thank you very much in advance.
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);
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.
精彩评论