Closed ahdzesq closed 5 years ago
Thank you for the report @ahdzesq .
I have some questions.
You are sending this message with hffix and using one of the hffix::message_writer::push_back_string
methods, is that right? Can you provide the code excerpt?
Is there some function like printf
which is formatting the FIX message and substituting %E
for a floating point conversion at some point after the FIX message has been written or before the FIX message is read?
This is how it looks like the Function that I'm using
` miliseconds = (microsec_clock::universal_time() - epoch).total_milliseconds(); ptime tsExecutionReport(epoch_milliseconds_to_ptime(miliseconds));
hffix::message_writer ExecutionReport(bufferExecutionReport, bufferExecutionReport + sizeof(bufferExecutionReport));
ExecutionReport.push_back_header (FIX_VERSION);
ExecutionReport.push_back_string (hffix::tag::MsgType, "8");
ExecutionReport.push_back_string (hffix::tag::SenderCompID, SenderCompId);
ExecutionReport.push_back_string (hffix::tag::TargetCompID, TargetCompId);
ExecutionReport.push_back_int (hffix::tag::MsgSeqNum, Out_Seq_Num);
ExecutionReport.push_back_timestamp (hffix::tag::SendingTime, tsExecutionReport);
ExecutionReport.push_back_string (hffix::tag::OrderID, ExecRep.OrderID);
ExecutionReport.push_back_string (hffix::tag::ClOrdID, ExecRep.ClOrdID);
ExecutionReport.push_back_int (hffix::tag::ExecID, ExecRep.ExecID);
ExecutionReport.push_back_int (hffix::tag::ExecType, ExecRep.ExecType);
ExecutionReport.push_back_string (hffix::tag::OrdStatus, ExecRep.OrderStatus);
ExecutionReport.push_back_int (hffix::tag::Account, ExecRep.Account);
if (ExecRep.Symbol.compare("") != 0)
ExecutionReport.push_back_string (hffix::tag::Symbol, ExecRep.Symbol);
if (ExecRep.SecurityID.compare("") != 0)
ExecutionReport.push_back_string (hffix::tag::SecurityID, ExecRep.SecurityID);
ExecutionReport.push_back_int (hffix::tag::Side, ExecRep.Side);
ExecutionReport.push_back_int (hffix::tag::OrderQty, ExecRep.OrderQty);
ExecutionReport.push_back_int (hffix::tag::OrdType, ExecRep.OrdType);
ExecutionReport.push_back_decimal (hffix::tag::Price, ExecRep.Price.Mantissa, ExecRep.Price.Exponent);
ExecutionReport.push_back_int (hffix::tag::TimeInForce, ExecRep.TimeInForce);
ExecutionReport.push_back_int (hffix::tag::LeavesQty, ExecRep.LeavesQty);
ExecutionReport.push_back_int (hffix::tag::CumQty, ExecRep.CumQty);
if (ExecRep.SecuritySubType.compare("") != 0)
ExecutionReport.push_back_string (hffix::tag::SecuritySubType, ExecRep.SecuritySubType);
if (ExecRep.LastPx.Mantissa != 0)
ExecutionReport.push_back_decimal (hffix::tag::LastPx, ExecRep.LastPx.Mantissa, ExecRep.LastPx.Exponent);
if (ExecRep.LastQty != 0)
ExecutionReport.push_back_int (hffix::tag::LastQty, ExecRep.LastQty);
if (ExecRep.Text.compare("") != 0)
ExecutionReport.push_back_string (hffix::tag::Text, ExecRep.Text);
ExecutionReport.push_back_trailer(); `
Is there some function like printf which is formatting the FIX message and substituting %E for a floating point conversion at some point after the FIX message has been written or before the FIX message is read?
About this the answer is no, the Tag text it came with the char '%' from the exchange
Just to give you a little of context, I have two classes the first one is "SessionInitiator" this one starts the session with the exchange, sends all the orders, and receive the execution report messages, after reading the execution report it fills a struct named Execution report that it has a lot of fields then pass this execution report to another class "SessionAcceptor" that uses the function above described to send it to the correct "Client", this function is where the error happens
Regards.
Well, considering that
%
It seems likely there is some function which is transforming the message buffer after
ExecutionReport.push_back_trailer();
and before the SessionAcceptor
sends the message. Is there anything in your code like that? What function is called to send the message buffer to the network?
James,
There is nothing before the
ExecutionReport.push_back_trailer();
Take a look this is the part of code that receivers the Execution report from the Exchange and Send it to the SessionAccetor Class
ExecutionReport ExecutionReport;
if (reader.find_with_hint(hffix::tag::OrderID, i))
ExecutionReport.OrderID = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::SecondaryOrderID, i))
ExecutionReport.SecondaryOrderID = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::ClOrdID, i))
ExecutionReport.ClOrdID = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::ExecID, i))
ExecutionReport.ExecID = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::ExecType, i))
ExecutionReport.ExecType = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::OrdStatus, i))
ExecutionReport.OrderStatus = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::Account, i))
ExecutionReport.Account = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::Symbol, i))
ExecutionReport.Symbol = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::SecurityID, i))
ExecutionReport.SecurityID = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::SecurityIDSource, i))
ExecutionReport.SecurityIDSource = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::Side, i))
ExecutionReport.Side = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::OrderQty, i))
ExecutionReport.OrderQty = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::OrdType, i))
ExecutionReport.OrdType = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::Price, i))
i++->value().as_decimal(ExecutionReport.Price.Mantissa, ExecutionReport.Price.Exponent);
if (reader.find_with_hint(hffix::tag::TimeInForce, i))
ExecutionReport.TimeInForce = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::LeavesQty, i))
ExecutionReport.LeavesQty = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::CumQty, i))
ExecutionReport.CumQty = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::HandlInst, i))
ExecutionReport.HndlInst = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::ExDestination, i))
ExecutionReport.ExDestination = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::SecuritySubType, i))
ExecutionReport.SecuritySubType = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::SettlDate, i))
ExecutionReport.SettlDate = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::TradeDate, i))
ExecutionReport.TradeDate = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::TrdMatchID, i))
ExecutionReport.TrdMatchID = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::AggressorIndicator, i))
ExecutionReport.AggressorIndicator = i++->value().as_string();
if (reader.find_with_hint(hffix::tag::LastPx, i))
i++->value().as_decimal(ExecutionReport.LastPx.Mantissa, ExecutionReport.LastPx.Exponent);
if (reader.find_with_hint(hffix::tag::LastQty, i))
ExecutionReport.LastQty = i++->value().as_int<int>();
if (reader.find_with_hint(hffix::tag::Text, i))
ExecutionReport.Text = i++->value().as_string();
boost::erase_all(ExecutionReport.Text, "%");
string OrderToFind = ExecutionReport.ClOrdID.substr(ExecutionReport.ClOrdID.find("_") + 1);
ExecutionReport.ClOrdID = OrderToFind;
map<string,string> :: const_iterator OrdIt;
OrdIt = OrderMap.find(OrderToFind);
if (OrdIt != OrderMap.end())
{
Session* TempSession = TradingSessions.find(OrdIt->second)->second;
if (TempSession != NULL)
{
TempSession->SendExecutionReport (ExecutionReport);
if (ExecutionReport.OrderStatus == "2" || ExecutionReport.OrderStatus == "8")
{
OrderMap.erase(OrdIt->first);
}
}
}
`
Before of that there is just a Switch that it iterates to the Message type '8'
as you can see there is a struct that it names ExecutionReport where it have a Text field, the Execution report struct looks like this:
struct ExecutionReport
{
string OrderID;
string SecondaryOrderID;
string ClOrdID;
int ExecID;
int ExecTransType;
string ExecType;
string OrderStatus;
int Account;
string Symbol;
string SecurityID;
int SecurityIDSource;
int Side;
int OrderQty;
int OrdType;
Px Price;
int TimeInForce;
int LeavesQty;
int CumQty;
int HndlInst;
string ExDestination;
string SecuritySubType;
Px LastPx;
int LastQty;
int TradeDate;
int SettlDate;
string AggressorIndicator;
string TrdMatchID;
string Text;
}
`
As you can see the Text field is only a string, so the character '%' it comes from the exchange, the only way that I've found this works is removing the character '%' from the string "Text"
Many Thanks, Regards.
Hi @ahdzesq , What's your theory of why this problem is happening?
Could not reproduce, closing.
Hello,
I was sending a FIX message that pushes a string that it contains a character '%' but this causes an error while checksumming the FIX Message
10=135 [incorrect should be 182]
Also, the field BodyLength value is incorrect
The original field text contains this: "% EF Error: Issuer-Err (7): Operation after hours"
Looking for the packet after sending it (with Wireshark) the text field contains this: "-7.160094E + 12F Error: Issuer-Err ( 7): Operation after hours "
if I remove the character '%' after sending the FIX Message there is no problem and the checksum is correct
Just to let you know
Regards.