Basic concept
Fixopedia is a high-level mechanism for accessing FIX protocol definition in run-time. It is responsible for:
- Encapsulating all information about supported versions of the FIX protocol.
- Providing a set of interfaces that give flexible access to FIX messages meta-data.
FIX Dictionary
FixDictionary is a storage of meta-data which describes different versions and dialects of the FIX protocol. The format of FixDictionary structure description is XML. The FixDictionary allows loading protocol descriptions dynamically. It provides the following information about the FIX protocol elements:
- The type of FIX protocol element (FixDictionary(root), Protocol, Message, Group, Block, Field)
- Reference to the parent element
- Reference to the list of child elements
- Reference to the relative Block.
- The required attribute (in context of parent or relation).
- The set of possible values (if available)
- Value restrictions
The FixDictionary supports the following operations with the FIX protocol:
- criterial search - can be flat, shallow or deep.
- insert - extends dictionary structure with user-defined elements.
- modify - changes some attributes of existing elements.
- delete - removes user-defined elements.
Creating and starting
The FixDictionary object can be created in a common way. The FixDictionary allows modifying FIX protocols before it is started, all modification actions are prohibited after FixDictionary::start() is called.
For example:
#include "B2BITS_Fixopaedia.h"
#include "B2BITS_FDElement.h"
#include "B2BITS_Fixopaedia_Descriptions.h"
using namespace Fixopaedia;
std::auto_ptr<FixDictionary> dict(new FixDictionary());
dict->start();
dict.reset()
Inserting new FIX protocol element
The FixDictionary can be extended with new FIX protocol elements using the FixDictionary::insert() method.
For example:
#include "B2BITS_Fixopaedia.h"
#include "B2BITS_FDElement.h"
#include "B2BITS_Fixopaedia_Descriptions.h"
using namespace Fixopaedia;
std::auto_ptr<FixDictionary> dict(new FixDictionary());
FDElement* protocol = dict->get("\\\\FIX44");
FDTypeInfo* ti = dict->getTypeInfo(FixDictionaryFactory::nameByFDT(FDT_INT));
FieldDescription* fd = FieldDescription::create("myField", 1000, ti, false);
protocol->toProtocolDescriptionPtr()->registerAdditionalDescription(fd);
FDElement* msgP = dict->getRootElement()->get("FIX44\\P");
dict->insert(fd, msgP, NULL, NOT_REQUIRED, "", true);
dict->start();
Removing existing FIX protocol elements
The FixDictionary allows removing existing FIX protocol elements using the FixDictionary::remove() method.
For example:
#include "B2BITS_Fixopaedia.h"
#include "B2BITS_FDElement.h"
#include "B2BITS_Fixopaedia_Descriptions.h"
using namespace Fixopaedia;
std::auto_ptr<FixDictionary> dict(new FixDictionary());
FDElement* fP_1000 = dict->get("\\\\FIX44\\P\\T$1000");
assert(fP_1000 != NULL);
assert(1000 == fP_1000->toFieldDescription()->getTag());
FDElements fdeList;
fdeList.push(fP_1000);
dict->remove(fdeList);
dict->start();
Loading FIX protocol customization
The FixDictionary allows loading FIX protocol customization. The FIX protocol customization must be in XML format. The FixDictionary::loadXmlFile() method loads the FIX protocol customization from file. The FixDictionary::executeXml() method loads the FIX protocol customization from string.
For example:
#include "B2BITS_Fixopaedia.h"
#include "B2BITS_FDElement.h"
#include "B2BITS_Fixopaedia_Descriptions.h"
using namespace Fixopaedia;
std::auto_ptr<FixDictionary> dict(new FixDictionary());
dict->loadXmlFile("exampleFIXProtocol.xml");
std::string xml2("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<fixdics><update>"
"<fixdic fixversion=\"4.1\" title=\"FIX 4.1\" date=\"2006/5/11\">"
"<fielddic>"
"<fielddef tag=\"386\" name=\"field386float\" type=\"float\">"
"</fielddef>"
"</fielddic>"
"<msgdic>"
"<msgdef msgtype=\"G\" >"
"<field tag=\"386\"/>"
"</msgdef></msgdic></fixdic>"
"</update></fixdics>");
dict->executeXml(xml2);
dict->start();
Searching FIX protocol elements
The FixDictionary allows searching for FIX protocol elements using the FixDictionary::query() method. The search criteria are specified by the FIXPath language.
For example:
#include "B2BITS_Fixopaedia.h"
#include "B2BITS_FDElement.h"
#include "B2BITS_Fixopaedia_Descriptions.h"
using namespace Fixopaedia;
std::auto_ptr<FixDictionary> dict(new FixDictionary());
FDElements fdeList;
bool qres = dict->query("\\\\FIX44\\BB", SEARCH_DEEP, "Type=Field, ID=571", &fdeList);
assert(qres);
assert(1 == fdeList.size());
FIXPath
FixPath is a string that defines a partial field location in the given Fix Message of the given FIX protocol. The FixPath can be used to locate a specified element in the FixDictionary. The FIXPath grammar is the following:
<FixPath> ::= "\\", <Protocol>, "\", <MessageType>, "\", <PathNode> { , "\", <PathNode> } ;
<Protocol> ::= Fix protocol version;
<MessageType> ::= The type of Fix message;
<PathNode> := [<Name>], ["$", <tag>] ; (*)
<Name> ::= The name of dictionary entry ('T' for tags and 'G' for groups);
<tag> ::= The number of tag for Field or leading tag for Group;
<IndexInGroup> ::= The index of partial field in repeating group. (**)(***)
(*) At least one element '<Name>' or ' "$", <tag>' must be specified.
(**) IndexInGroup is zero-based.
(***) IndexInGroup is always ignored by FixDictionary but can be used by dictionary-based applications for selecting partial field in repeating group.
The FixPath can be absolute or relative. For absolute path the FixDictionary calculates field position starting from dictionary root. For relative path the FixDictionary calculates field position starting from current context (i.e. if we get a message from FixDictionary, we can query its fields by a relative path, without selecting the protocol and message type).
<RelativePath> ::= ".\", <PathNode> { , "\", <PathNode> } ;
The dictionary element for every iteration is searched in the following way:
- Search always starts from Name.
- If the dictionary element is not found, the FixDictionary will search the element by tag.
- If the name is not specified, the FixDictionary will search the element by tag.
For example:
\\FIX44\8\$31 - FixDictionary entry for Field with tag 31 in message of type "8" for FIX v4.4;
\\FIX44\8\ClOrdID - FixDictionary entry for Field with Name "ClOrdID" in message of type "8" for FIX v4.4;
\\FIX44\8\Instrument\$55 - FixDictionary entry for Field with tag 31 in block "Instrument" (The same result will be for path '\\FIX44\8\$55');
.\$25 - FixDictionary entry for Field or Group with tag 25 depending on context.