Ошибка QuickFix/n: Тег появляется более одного раза (поле=523)

#quickfix #fix-protocol #quickfixn

Вопрос:

Мое приложение QuickFix/n 5.0SP2 отклоняет сообщение R с тегом ошибки, которое появляется несколько раз (Поле=523). Я рассмотрел все подобные проблемы на этом сайте, и предложенные решения не работают для меня. Я использовал в настройках параметр DataDictionary=Y. Я пробовал использовать параметры проверки, установленные в Y и N. Сообщение содержит пользовательские поля, которые я добавил в словарь данных приложения. Я проверил порядок всех полей, и он выглядит хорошо. Я попытался использовать пакеты nuget QuickFix.Net.NETCore.FIX50SP2 и QuickFIXn.FIX5.0SP2 на случай, если возникнет разница в анализе сообщений.

Некоторые поля получены не в правильном порядке в соответствии со стандартным протоколом ИСПРАВЛЕНИЯ. Я обновил порядок полей словаря данных, чтобы он соответствовал порядку полей в сообщении. Может ли заказ по-прежнему вызывать отклонение сообщения?

Чтобы подтвердить, что выбран правильный словарь данных, я попытался добавить новое обязательное поле, и мое приложение, как и ожидалось, отклонило сообщение, в котором говорилось, что требуемый тег отсутствует.

Я застрял на этой ошибке уже неделю, любая помощь будет высоко оценена!

Отклонено сообщение: 20210924-05:09:21.123 : 8=FIXT.1.1 9=123 35=R 34=234 52=20210924-05:09:21.721 49=XYZ 56=ABC 131=LST1 46=1 55=110 Тыс. Макс. 828=57 60=20210924-05:09:21 75=20210924 464=Y 20086=1 20073=REQ 20074=N 20075=N 20076=N 20077=[N/A] 20078=[N/A] 20079=5 20081=300 453=2 448=xyz 447=C 452=3 802=3 523=Шрути B 803=2 523=Нью-Йорк 803=25 523=США 803=4000 448=Клиент 447=C 452=1 802=1 523=123 803=4002 5745=1 48=123ABC 22=1 460=10 167=MBS 762=MBSSPL 15=долл. США 64=20211015 541=20510920 223=2 38=1000000 54=1 699=1ABC2 761=1 423=12 228=1.0 58=Испытание DN 092401 10=209

Сессии

 # default settings for sessions-->
[DEFAULT]
ConnectionType=initiator
ReconnectInterval=60
ResetOnLogon=N
ResetOnLogout=Y
LogonTimeout=60
UseLocalTime=Y
FileLogPath=/fix_logs

# session definition
[SESSION]
# inherit FileLogPath, ConnectionType,
#    ReconnectInterval from default
BeginString=FIXT.1.1
SenderCompID=XYZ
TargetCompID=ABC
StartDay=monday
EndDay=saturday
StartTime=00:30:00
EndTime=18:16:00
HeartBtInt=60
CheckLatency=N
MaxLatency=240
UseDataDictionary=Y
DefaultApplVerID=FIX.5.0SP2
SocketConnectPort=xxxxx
SocketConnectHost=xxx.xx.xx.xxx
FileStorePath=/file_store
TransportDataDictionary=FIXT11.xml
AppDataDictionary=FIX50SP2.xml
ValidateFieldsOutOfOrder=Y
ValidateFieldsHaveValues=Y
ValidateUserDefinedFields=Y
 

Частичный словарь

 <fix type="FIX" major="5" minor="0" servicepack="2">
    <header/>
    <messages>
        <message name="QuoteRequest" msgtype="R" msgcat="app">
            <field name="QuoteReqID" required="Y"/>
            <component name="QuotReqGrp" required="Y"/>
            <component name="Parties" required="Y"/>
            <field name="MultipleTickets" required="N"/>
            <field name="SecurityID" required="N"/>
            <field name="SecurityIDSource" required="N"/>
            <field name="Product" required="N"/>
            <field name="SecurityType" required="N"/>
            <field name="SecuritySubType" required="N"/>
            <field name="Currency" required="N"/>
            <field name="SettlDate" required="N"/>
            <field name="MaturityDate" required="N"/>
            <field name="CouponRate" required="N"/>
            <component name="OrderQtyData" required="N"/>
            <field name="Side" required="N"/>
            <component name="SpreadOrBenchmarkCurveData" required="N"/>
            <field name="PriceType" required="N"/>
            <field name="Factor" required="N"/>
            <field name="Text" required="N"/>
            <field name="EncodedTextLen" required="N"/>
            <field name="EncodedText" required="N"/>
            <field name="BookingType" required="N"/>
            <field name="OrderRestrictions" required="N"/>
        </message>
    </messages>
    <trailer/>
    <components>
        <component name="QuotReqGrp">
                <field name="NoRelatedSym" required="Y"/>
                <field name="Symbol" required="Y"/>
                <field name="SymbolSfx" required="N"/>
                <field name="TrdType" required="N"/>
                <field name="TransactTime" required="Y"/>
                <field name="TradeDate" required="Y"/>
                <field name="TestMessageIndicator" required="N"/>
                <field name="NoOfDealers" required="N"/>
                <field name="NegotiationType" required="N"/>
                <field name="CanRespond" required="N"/>
                <field name="CanQuote" required="N"/>
                    <field name="CanRequote" required="N"/>
                    <field name="BookName" required="N"/>
                    <field name="TraderList" required="N"/>
                    <field name="TimeoutPeriod" required="N"/>
                    <field name="NewTimePeriod" required="N"/>
                    <field name="QuoteTimePeriod" required="N"/>
                    <field name="ConfirmTimePeriod" required="N"/>
                    <field name="RequoteTimePeriod" required="N"/>
                <!--<field name="Price" required="Y"/>-->
        </component>
        <component name="Parties">
            <group name="NoPartyIDs" required="Y">
                <!--<field name="NoPartyIDs" required="Y"/>-->
                <field name="PartyID" required="Y"/>
                <field name="PartyIDSource" required="N"/>
                <field name="PartyRole" required="N"/>
                <component name="PtysSubGrp" required="Y"/>
            </group>
        </component>
        <component name="PtysSubGrp">
            <group name="NoPartySubIDs" required="Y">
                <field name="PartySubID" required="Y"/>
                <field name="PartySubIDType" required="Y"/>
            </group>
        </component>
        <component name="OrderQtyData">
            <field name="OrderQty" required="N"/>
            <field name="CashOrderQty" required="N"/>
            <field name="OrderPercent" required="N"/>
            <field name="RoundingDirection" required="N"/>
            <field name="RoundingModulus" required="N"/>
        </component>
        <component name="SpreadOrBenchmarkCurveData">
            <field name="Spread" required="N"/>
            <field name="BenchmarkCurveCurrency" required="N"/>
            <field name="BenchmarkCurveName" required="N"/>
            <field name="BenchmarkCurvePoint" required="N"/>
            <field name="BenchmarkPrice" required="N"/>
            <field name="BenchmarkPriceType" required="N"/>
            <field name="BenchmarkSecurityID" required="N"/>
            <field name="BenchmarkSecurityIDSource" required="N"/>
        </component>
    </components>
    <fields>
    </fields>
</fix>
 

Комментарии:

1. Привет, Шрути, можете ли вы подтвердить, что выполнили следующие действия: quickfixn.org/tutorial/custom-fields-groups-and-messages.html ?

2. @TT. Да, я проверил эту ссылку, и она выглядела довольно простой . Я обновил исходный вопрос частью используемого мной словаря. Чтобы убедиться, что у меня все поля в порядке и чтобы сделать их чище, я удалил все дополнительные сообщения и компоненты. Я также добавил большинство тегов в основное сообщение запроса котировок. Я подтвердил, что каждое поле в сообщении определено в разделе поля.

3. @TT. — Если я добавлю фиктивное обязательное поле, скажем, поле 9999, в группу NoPartyIDs в качестве первого поля в группе, я не получу ошибку отсутствия требуемого тега. Вместо этого я все еще получаю ошибку повторяющегося тега. Однако, когда я меняю NoPartyIDs на поле, я получаю сообщение об ошибке для требуемого тега. Таким образом, похоже, что когда QuickFix сталкивается с группой, он обрабатывает самую внутреннюю группу внутри этой родительской группы, а затем работает вовне. В группе NoPartySubIDs всего 2 поля, и в сообщении есть 2 поля, 523 и 803, в том же порядке.

4. @TT. Согласно входящему сообщению, компонент Сторон должен был находиться в компоненте QuotReqGrp. Я исправил это, а также удалил тег компонента и просто пошел с тегами групп. Теперь я могу прочитать сообщение в своем коде, спасибо!

5. Всегда пожалуйста. Можете ли вы ответить на свой собственный вопрос, описав шаги, которые вы предприняли для решения своей проблемы? Это может помочь будущим посетителям с аналогичной проблемой.

Ответ №1:

Проблема заключалась в наличии пользовательских полей во входящем сообщении, которые отсутствовали в моем словаре данных. В какой-то момент, пытаясь добавить эти пользовательские поля и очистить словарь, я удалил компонент Parties из компонента QuotReqGrp и поместил его после QuotReqGrp. Я снова начал со свежей копии словаря данных и добавил пользовательские поля, чтобы устранить проблему.