Now currently I am working on copy operator. What I understand from all the document and other material available on net is that Quickfast maintains a dictionary which is used by multiples entries within a UDP message to check the previous value.
eg: Lets say in the below given template we can have multiple MDEntries depending upon NoMDEntries tag value. Lets say we have 2 as the value . What I did was , I put the value of MDEntryType (with copy oprerator ) as 1 (some random value) in the first entry, but for the second entry I did not put any value. After I decode the message the value of MDEntryType should be 1 for both the entries.
Is my understanding correct ?
<template dictionary="1" id="1" name="MDIncRefreshSample_1"> <string id="35" name="MessageType"> <constant value="X"></constant> </string> <string id="49" name="SenderCompID"> <constant value="Client"></constant> </string> <string id="56" name="TargetCompID"> <constant value="Server"></constant> </string> <uint32 id="34" name="MsgSeqNum"></uint32> <uint64 id="52" name="SendingTime"></uint64> <sequence name="MDEntries"> <length id="268" name="NoMDEntries"></length> <uint32 id="279" name="MDUpdateAction"> <copy value="1"></copy> </uint32> <string id="269" name="MDEntryType"> <copy value="0"></copy> </string> <uint32 id="278" name="MDEntryID"></uint32> <uint32 id="48" name="SecurityID"> <delta></delta> </uint32> <decimal id="270" name="MDEntryPx"> <exponent> <default value="-2"></default> </exponent> <mantissa> <delta></delta> </mantissa> </decimal> <int32 id="271" name="MDEntrySize"> <delta></delta> </int32> <string id="37" name="OrderID"></string> <uint32 id="273" name="MDEntryTime"> <copy></copy> </uint32> </sequence> </template>
Now when I try to implement the above in my code, I am not able to copy the value in the second entry. Here is the snippet of the code I used (help taken from testRoundTrip.cpp)
Template Created :
<templates> <template dictionary="InstrumentReferenceData" name="InstrumentReferenceData" id="3"> <typeRef name="instrumentreferencedata"/> <uInt32 name="timestamp" id="52"> <delta/> </uInt32> <uInt32 name="srcId" id="50"> <copy/> </uInt32> <uInt32 name="seqNum" id="34"> <increment value="1"/> </uInt32> <uInt32 name="isix" id="48"> <delta/> </uInt32> <string name="isin" id="455"> <delta/> </string> <string name="exchId" id="207"> <copy/> </string> <string name="instGrp" id="1151"> <copy/> </string> <string name="instTypCod" id="461"> <copy/> </string> <string name="currCode" id="15"> <copy/> </string> <decimal name="ticSiz" id="969"> <delta/> </decimal> <uInt32 name="setId" id="TBD"> <copy/> </uInt32> <sequence name="MDFeedTypes"> <length name="noOfStreams" id="1141"/> <string name="streamType" id="1022"> <copy dictionary="template" /> </string> <string name="streamService"> <copy/> </string> <string name="inetAddr"> <delta/> </string> <uInt32 name="port" id="TBD"> <delta/> </uInt32> <uInt32 name="mktDepth" id="264" presence="optional"/> </uInt32> <uInt32 name="mdBookType" id="1021" presence="optional"/> </uInt32> </sequence> </template> </templates>
Message creation plus encoding and decoding: (I have poulated the value in streamtype field only once)
Messages::MessagePtr msg(new Messages::Message(templateRegistry->maxFieldCount()));
msg->addField(identity_timestamp, Messages::FieldUInt32::create(1));
msg->addField(identity_srcId, Messages::FieldUInt32::create(2));
msg->addField(identity_seqNum, Messages::FieldUInt32::create(3));
msg->addField(identity_isix, Messages::FieldUInt32::create(4));
msg->addField(identity_isin, Messages::FieldAscii::create("isin"));
msg->addField(identity_exchId, Messages::FieldAscii::create("exchId"));
msg->addField(identity_instGrp, Messages::FieldAscii::create("instGrp"));
msg->addField(identity_instTypCod, Messages::FieldAscii::create("instTypCod"));
msg->addField(identity_currCode, Messages::FieldAscii::create("currCode"));
msg->addField(identity_ticSiz, Messages::FieldDecimal::create(Decimal(123, -1)));
msg->addField(identity_setId, Messages::FieldUInt32::create(5));
lengthIdentity.setId("1141");
Messages::SequencePtr sequence_MDFeedTypes(new Messages::Sequence(lengthIdentity, 2));
Messages::FieldSetPtr entry(new Messages::FieldSet(6)); // todo Hardcoded 6?
entry->addField(identity_streamType, Messages::FieldAscii::create("streamType")); // Populated the value 1st time
entry->addField(identity_streamService, Messages::FieldAscii::create("streamService"));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.com"));
entry->addField(identity_port, Messages::FieldUInt32::create(2222));
entry->addField(identity_mktDepth, Messages::FieldUInt32::create(10));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
entry.reset(new Messages::FieldSet(6));
entry->addField(identity_streamType, Messages::FieldAscii::create("")); // Did not Populate the value 2nd time
entry->addField(identity_streamService, Messages::FieldAscii::create(""));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.org"));
entry->addField(identity_port, Messages::FieldUInt32::create(2224));
entry->addField(identity_mdBookType, Messages::FieldUInt32::create(3));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
msg->addField(identity_MDFeedTypes, Messages::FieldSequence::create(sequence_MDFeedTypes));
Codecs::Encoder encoder(templateRegistry);
Codecs::DataDestination destination;
template_id_t templId = 3; // from the XML above
encoder.encodeMessage(destination, templId, *msg);
std::string fastString;
destination.toString(fastString);
std::cout<<"fastString is "<<fastString<<std::endl;
destination.clear();
Codecs::Decoder decoder(templateRegistry);
Codecs::DataSourceString source(fastString);
Codecs::SingleMessageConsumer consumer;
Codecs::GenericMessageBuilder builder(consumer);
decoder.decodeMessage(source, builder);
Messages::Message & msgOut(consumer.message());
Messages::MessageFormatter formatter(std::cout);
formatter.formatMessage(msgOut); // I have made some printing changes to print the ouptut per tag
validateMessage1(msgOut);
encoder.reset();
encoder.encodeMessage(destination, templId, msgOut);
std::string reencoded;
destination.toString(reencoded);
destination.clear();
I am able to encode and successfully decode the message, but the value is not getting copied in the second entry (streamType tag). Here is my decoded ouput:
1st entry:
streamType[1022]=streamType
streamService[]=streamService
inetAddr[]=inetAddr.com
port[TBD]= 2045
2nd entry:
streamType[1022]= //value not copied
streamService[]=
inetAddr[]=inetAddr.org
port[TBD]= 2046
Could you please let us know, if we are making a mistake somewhere. I am very new to this :)
I have following queries too :
1/ Do we need to explicitly need to enable/disable dictionary in quickfast ? (In FIX we could do that with flag, DataDictionary = Y/N). Also in the template created above , I found this line:
<string name="streamType" id="1022"> <copy dictionary="template" /> </string>
Is it neccesary to give dictionary name while using operators and how are they related?
2/ Do we also need to explicitly mention that PMAP bits are required?
Codecs::PresenceMap pmap(1); // I came across this function, so I got this doubt whether we need to explicitly mention about pmap.