QuickFIX не проверяет повторяющуюся группу

Я реализую набор клиент-сервер на основе QuickFIX. Когда я пытаюсь отправить сообщение, содержащее повторяющуюся группу сторон, я получаю отказ со следующим описанием: "58=Тег не определен для этого типа сообщения|371=447|"

Я пытаюсь отправить сообщение типа OrderCancelReplaceRequest.

Пример кода:

FIX44::OrderCancelReplaceRequest order(FIX::MsgType("G"));

FIX44::OrderCancelReplaceRequest::NoPartyIDs party;
// 448-PartyID
party.set(FIX::PartyID("PartyId"));
// 447-PartyIDSource
party.set(FIX::PartyIDSource('B'));    
// 452-PartyRole
party.set(FIX::PartyRole(1));    
// 802-NoPartySubIDs
party.set(FIX::NoPartySubIDs(0));

order.addGroup(party);

...

Если сообщение не содержит группы сторон, оно успешно проверяется сервером.

Более того, он проходит валидацию успешно, даже если содержит группу FIX44::OrderCancelReplaceRequest::NoAllocs:

 FIX44::OrderCancelReplaceRequest::NoAllocs alloc;
 // 79-AllocAccount
 alloc.set(FIX::AllocAccount("Alloc Account"));
 // 80-AllocQty
 alloc.set(FIX::AllocQty(4.2));
 order.addGroup(alloc);

Итак, я вижу эту проблему только тогда, когда пытаюсь использовать группу Сторон.

Файл конфигурации для сервера:

[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=28663
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
DataDictionary=<some path here>/FIX44.xml
FileLogPath=QuickFixServerLog
ValidateUserDefinedFields=N

[SESSION]
BeginString=FIX.4.4
SenderCompID=EXECUTOR
TargetCompID=CLIENT1
FileStorePath=store

Конфигурационный файл клиента:

[DEFAULT]
ConnectionType=initiator
ReconnectInterval=1
FileStorePath=store
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
DataDictionary=<some path here>/FIX44.xml
HttpAcceptPort=9911
ValidateUserDefinedFields=N
ResetOnLogout=Y
ResetOnLogon=Y

[SESSION]
BeginString=FIX.4.4
SenderCompID=CLIENT1
TargetCompID=EXECUTOR
SocketConnectHost=127.0.0.1
SocketConnectPort=28663
HeartBtInt=15

Обновление

Пример запроса, полученного сервером (из логов сервера):

8=FIX.4.4|9=234|35=G|34=2|49=CLIENT1|52=20150417-10:49:07.715|56=EXECUTOR|1=Account|11=Id123|38=11.11|40=1|41=OrigId321|44=4.2|54=2|55=Symbol|60=20150417-10:49:07|78=2|79=AllocAccount1|79=AllocAccount2|80=10|80=20|447=B|448=PartyId|452=1|453=1|802=0|10=185|

Ответ на этот запрос:

8=FIX.4.4|9=124|35=3|34=2|49=EXECUTOR|52=20150417-10:49:07.719|56=CLIENT1|45=2|58=Tag not defined for this message type|371=447|372=G|373=2|10=060|

person Andrey Ferapontov    schedule 16.04.2015    source источник
comment
Мы не сможем вам помочь, если вы не опубликуете фактическое сообщение. (Пожалуйста, сделайте разделители полей видимыми.)   -  person Grant Birchmeier    schedule 16.04.2015
comment
Просто предположение. Ваш ValidateUserDefinedFields=N может мешать, если у вас есть пользовательские поля. Попробуйте сделать Y и посмотрите. Но, как сказал @Grant, просмотр сообщений очень поможет.   -  person DumbCoder    schedule 17.04.2015
comment
Спасибо за ваши комментарии! Я обновил описание примерами сообщений. Что касается ValidateUserDefinedFields, я пробовал (а также отключал все остальные возможные настройки проверки в файле конфигурации), но это не помогло.   -  person Andrey Ferapontov    schedule 17.04.2015
comment
Вы абсолютно уверены, что обмениваетесь данными с сервером FIX 4.4? <Parties> component block был добавлен только с версии 4.3, возможно, вы общаетесь с сервером версии 4.2?   -  person TT.    schedule 17.04.2015
comment
Сервер 4.4, я уверен.   -  person Andrey Ferapontov    schedule 17.04.2015
comment
Я проверил сообщение FIX здесь и не обнаружил в нем ничего плохого. Вы написали сервер FIX, используя quickfix? Если это так, возможно, вы могли бы отладить его на стороне сервера, посмотреть, что вызывает сообщение об отклонении?   -  person TT.    schedule 18.04.2015
comment
Если у вас есть контроль над реализацией сервера, не могли бы вы попробовать добавить ValidateFieldsOutOfOrder=N в конфигурацию?   -  person TT.    schedule 18.04.2015
comment
Небольшое примечание: если вы ответите на мои комментарии, пожалуйста, начните свой ответ с @TT, чтобы я получил уведомление (вы увидите, что вы можете написать в комментариях, если вы нажмете ссылку справки рядом с полем для комментариев)   -  person TT.    schedule 18.04.2015
comment
@TT Большое спасибо за ваши комментарии! Пробовал ValidateFieldsOutOfOrder=N, но, к сожалению, результат тот же. Сервер реализован с помощью quickfix. В настоящее время я пытаюсь его отладить и опишу все результаты отладки, как только закончу ее.   -  person Andrey Ferapontov    schedule 20.04.2015
comment
Еще одна попытка решения. В загруженном пакете быстрого исправления C++ найдите файл MessagesTestCase.cpp. В этом файле найдите строку NoPartyIDs. В примере есть добавление группы NoPartyIDs к сообщению FIX44::NewOrderCross. По-видимому, это использует FIX44::NewOrderCross::NoSides в качестве контейнера для группы NoPartyIDs. Может быть, вы могли бы попробовать и посмотреть, нужен ли такой же шаблон использования для добавления идентификаторов вечеринок в FIX44::OrderCancelReplaceRequest?   -  person TT.    schedule 20.04.2015
comment
@TT Спасибо, я посмотрел тестовый пример, но по-прежнему не вижу проблем в своем клиентском коде. Сообщение, которое создает клиент, выглядит в порядке - проблема на стороне сервера, поскольку QuickFIX не находит встроенное поле 447 в своем словаре данных.   -  person Andrey Ferapontov    schedule 20.04.2015
comment
Итак, если вы зарегистрируете сообщение, созданное на стороне клиента, 453 будет перед любым другим тегом в группе NoPartyIDs (448 447 452 802)?   -  person TT.    schedule 20.04.2015
comment
@TT Да, на стороне клиента порядок 453, 448, 447, 452. Но сервер получает то же сообщение со всеми полями, установленными в порядке увеличения...   -  person Andrey Ferapontov    schedule 20.04.2015
comment
@TT Спасибо большое! Ваша идея с порядком полей была верна - я делал преобразование сообщения в клиенте (это требовалось какой-то бизнес-логикой), и в результате объект Message был создан и отправлен на сервер. Этот объект сообщения не смог сохранить порядок полей. Я изменил это преобразование, чтобы порядок полей не нарушался, и все заработало. Спасибо еще раз!   -  person Andrey Ferapontov    schedule 20.04.2015


Ответы (2)


Как вы заметили после нашего разговора в разделе комментариев, порядок полей в <Parties> component block указана неправильная группа. Порядок полей в повторяющейся группе (или блоке компонентов, как в случае <Parties>) должен быть сохранен. Вы можете найти здесь сообщение в блоге на предмет, объясняющий важность порядка полей в повторяющихся группах.

В вашем случае модификация сообщения на стороне клиента испортила порядок полей группы <Parties>, что привело к сообщению Reject с сервера.

person TT.    schedule 20.04.2015
comment
Конечно, никаких проблем! Спасибо еще раз! - person Andrey Ferapontov; 21.04.2015

@TT Мои 10 центов. Fiximate — ваш друг.

В моем словаре данных FIX4.4 я вижу, что для типа сообщения OrderCancelReplaceRequest тег 447 PartyIDSource не определен. Я прилагаю свое сообщение словаря данных.

Если вам нужно определить PartyIDSource, добавьте его в свой словарь данных.

<message name="OrderCancelReplaceRequest" msgtype="G" msgcat="app">
    <field name="OrderID" required="N" />
    <component name="Parties" required="N" />
    <field name="TradeOriginationDate" required="N" />
    <field name="TradeDate" required="N" />
    <field name="OrigClOrdID" required="Y" />
    <field name="ClOrdID" required="Y" />
    <field name="SecondaryClOrdID" required="N" />
    <field name="ClOrdLinkID" required="N" />
    <field name="ListID" required="N" />
    <field name="OrigOrdModTime" required="N" />
    <field name="Account" required="N" />
    <field name="AcctIDSource" required="N" />
    <field name="AccountType" required="N" />
    <field name="DayBookingInst" required="N" />
    <field name="BookingUnit" required="N" />
    <field name="PreallocMethod" required="N" />
    <field name="AllocID" required="N" />
    <group name="NoAllocs" required="N">
      <field name="AllocAccount" required="N" />
      <field name="AllocAcctIDSource" required="N" />
      <field name="AllocSettlCurrency" required="N" />
      <field name="IndividualAllocID" required="N" />
      <component name="NestedParties" required="N" />
      <field name="AllocQty" required="N" />
    </group>
    <field name="SettlType" required="N" />
    <field name="SettlDate" required="N" />
    <field name="CashMargin" required="N" />
    <field name="ClearingFeeIndicator" required="N" />
    <field name="HandlInst" required="N" />
    <field name="ExecInst" required="N" />
    <field name="MinQty" required="N" />
    <field name="MaxFloor" required="N" />
    <field name="ExDestination" required="N" />
    <group name="NoTradingSessions" required="N">
      <field name="TradingSessionID" required="N" />
      <field name="TradingSessionSubID" required="N" />
    </group>
    <component name="Instrument" required="Y" />
    <component name="FinancingDetails" required="N" />
    <group name="NoUnderlyings" required="N">
      <component name="UnderlyingInstrument" required="N" />
    </group>
    <field name="Side" required="Y" />
    <field name="TransactTime" required="Y" />
    <field name="QtyType" required="N" />
    <component name="OrderQtyData" required="Y" />
    <field name="OrdType" required="Y" />
    <field name="PriceType" required="N" />
    <field name="Price" required="N" />
    <field name="StopPx" required="N" />
    <component name="SpreadOrBenchmarkCurveData" required="N" />
    <component name="YieldData" required="N" />
    <component name="PegInstructions" required="N" />
    <component name="DiscretionInstructions" required="N" />
    <field name="TargetStrategy" required="N" />
    <field name="TargetStrategyParameters" required="N" />
    <field name="ParticipationRate" required="N" />
    <field name="ComplianceID" required="N" />
    <field name="SolicitedFlag" required="N" />
    <field name="Currency" required="N" />
    <field name="TimeInForce" required="N" />
    <field name="EffectiveTime" required="N" />
    <field name="ExpireDate" required="N" />
    <field name="ExpireTime" required="N" />
    <field name="GTBookingInst" required="N" />
    <component name="CommissionData" required="N" />
    <field name="OrderCapacity" required="N" />
    <field name="OrderRestrictions" required="N" />
    <field name="CustOrderCapacity" required="N" />
    <field name="ForexReq" required="N" />
    <field name="SettlCurrency" required="N" />
    <field name="BookingType" required="N" />
    <field name="Text" required="N" />
    <field name="EncodedTextLen" required="N" />
    <field name="EncodedText" required="N" />
    <field name="SettlDate2" required="N" />
    <field name="OrderQty2" required="N" />
    <field name="Price2" required="N" />
    <field name="PositionEffect" required="N" />
    <field name="CoveredOrUncovered" required="N" />
    <field name="MaxShow" required="N" />
    <field name="LocateReqd" required="N" />
    <field name="CancellationRights" required="N" />
    <field name="MoneyLaunderingStatus" required="N" />
    <field name="RegistID" required="N" />
    <field name="Designation" required="N" />
  </message>
person rupweb    schedule 20.04.2015
comment
Привет, rupweb, в моем случае <component name="Parties" required="N" /> определяется в нижней части словаря. Я только что загрузил последнюю версию из версии quickfix C++, и в нижней части FIX44.xml находится определение <component name='Parties'>. Элемент группы NoPartyIds включает в себя поле PartyIDSource, для которого номер тега определен как 447 (<field number='447' name='PartyIDSource' type='CHAR'>). - person TT.; 20.04.2015
comment
Спасибо за ответ. Поле PartyIDSource с номером 447 встроено в компонент Party, так что причина не в этом... - person Andrey Ferapontov; 20.04.2015
comment
@TT Итак, ваши данные сообщения FIX 4.4 OrderCancelReplaceRequest отличаются от моих. Можете ли вы вставить свое сообщение OrderCancelReplaceRequest? Причина, по которой я спрашиваю снова, - это сообщение об ошибке: Тег, не определенный для этого типа сообщения, указывает на что-то вроде этого. Где должен быть определен тег, если не в словаре данных? - person rupweb; 21.04.2015
comment
Он не определен в самом сообщении, он определен в компоненте Parties. Найдите строку <component name='Parties'> в FIX44.xml, определяющую группу NoPartyIDs. Вы увидите ссылку на PartyIDSource. - person TT.; 21.04.2015
comment
Кстати, сообщение об ошибке OP было вызвано неправильным порядком полей в блоке компонента Стороны. - person TT.; 21.04.2015
comment
Хах, я был на полпути :) - person rupweb; 22.04.2015