Custom Fields and a Custom Data Dictionary in QuickFIX
Written and maintained by ZagTrader. Last reviewed . How this page is sourced and checked
Most counterparties add fields of their own, usually numbered 5000 and above, and some change which standard fields a message may carry. QuickFIX checks every incoming message against its data dictionary, so those fields are rejected until the dictionary knows them. The fix is a copy of the standard dictionary with the counterparty's changes, not switching validation off.
Add a field in three places
Start from the dictionary for your FIX version that ships with the engine (FIX44.xml, FIX50SP2.xml) and save it under a new name. A field needs:
- A definition in the
<fields>section with a number, a name and a type. - An entry in each message that may carry it, under
<messages>, markedrequired="Y"orrequired="N". - Enumerated values, if the counterparty lists them, as
<value>elements. Other values are then rejected with 373=5.
<messages>
<message name="NewOrderSingle" msgtype="D" msgcat="app">
<field name="ClOrdID" required="Y"/>
<!-- the standard fields of the message stay as they are -->
<field name="StrategyCode" required="N"/>
</message>
</messages>
<fields>
<field number="5001" name="StrategyCode" type="STRING">
<value enum="VWAP" description="VWAP"/>
<value enum="TWAP" description="TWAP"/>
</field>
</fields>- Names must be unique and must match between the message entry and the field definition. A field used in a message but missing from
<fields>stops the engine at start. - Pick the type the counterparty specifies: STRING, INT, PRICE, QTY, CHAR, BOOLEAN, UTCTIMESTAMP and so on. A wrong type produces incorrect data format rejects for valid values.
- Point the session at the new file:
DataDictionary=for FIX 4.x,AppDataDictionary=for FIX 5.0 and later.
Settings that relax the checks
When you cannot get a full specification, these settings stop specific rejects. Each one hides real errors too, so prefer a correct dictionary.
| Setting | Effect |
|---|---|
| ValidateUserDefinedFields=N | Fields numbered 5000 and above that the dictionary does not define, or does not allow in that message, are accepted. |
| AllowUnknownMsgFields=Y | Standard fields below 5000 that the dictionary does not allow in that message are accepted. |
| AllowUnknownEnumValues=Y | Values outside an enumeration are accepted (QuickFIX/J 3.x and QuickFIX/n). |
| ValidateFieldsOutOfOrder=N | Header fields found in the body are accepted. |
| UseDataDictionary=N | No validation at all, and repeating groups are not parsed. Avoid on order flow. |
Reading and setting custom fields in code
- Without generated classes, use the generic accessors with the tag number: in QuickFIX/J
message.setString(5001, "VWAP")andmessage.getString(5001). QuickFIX/n and QuickFIX C++ have the same idea with typed field objects. - Reading a field that is not there throws a field-not-found exception. Thrown from your message handler, it turns into a Conditionally Required Field Missing reject to the counterparty, so check for optional fields first.
- To get typed classes for custom fields and messages, regenerate the message classes from your dictionary. QuickFIX/J documents this as building custom artefacts; QuickFIX/n and QuickFIX C++ ship generators in their repositories.
Test the dictionary before go-live
Load the same XML into the parser's venue dictionary: open the parser, choose Venue dictionary in the toolbar and load the file. Paste certification messages or a log; custom tags get their names, new values are accepted, and anything the dictionary would reject is flagged. The file is read in your browser and kept only on your device.
Questions
- Why does QuickFIX reject my custom tag?
- Because the data dictionary does not define it, or does not allow it in that message type. Add the field definition and the message entry, or set ValidateUserDefinedFields=N for tags of 5000 and above.
- Where do custom tags start?
- The user-defined range starts at 5000. QuickFIX uses 5000 as the line between ValidateUserDefinedFields and AllowUnknownMsgFields.
- Can one QuickFIX application use different dictionaries per counterparty?
- Yes. DataDictionary or AppDataDictionary is a per-session setting, so each [SESSION] can point at its own file.
The FIX side of the problem
What the error means on any FIX engine, with example messages you can open in the parser:
Reference
Sources
- QuickFIX/J source: DataDictionary.java (field checks)
- QuickFIX/J user manual: Configuration
- QuickFIX/J source: ValidationSettings.java (validation defaults)
- QuickFIX/J README: runtime artefacts per FIX version
- QuickFIX/n documentation: Custom fields, groups and messages
- QuickFIX/n documentation: Configuration
- QuickFIX C++ documentation: User defined fields
- QuickFIX C++ documentation: Validation
Setting names, defaults and message texts were checked against the projects' source code and documentation on the review date shown at the top of the page. Behaviour can change between releases; check the version you run. This guide is independent and not affiliated with the QuickFIX projects.
See also
More QuickFIX guides
- QuickFIX/J vs QuickFIX/n vs QuickFIX C++: Which One to Use
- QuickFIX Session Settings Explained: Configuration Reference
- QuickFIX with FIX 5.0 SP2: FIXT.1.1, Transport and Application Dictionaries
- Repeating Groups in QuickFIX: Reading, Writing and Validation Errors
- QuickFIX Session Schedules: Daily vs Weekly Sessions, Time Zones and Sunday to Thursday Markets
- QuickFIX "Tag not defined for this message type": Causes and Fixes
- QuickFIX "Conditionally Required Field Missing": Why Your Handler Caused It
- QuickFIX "Incorrect data format for value": Field Types and Fixes
- QuickFIX "MsgSeqNum too low": Reset Sequence Numbers Safely and Fix the File Store
- QuickFIX Logon Problems: Session Not Found, CompID Mismatch and Rejected Logons
- QuickFIX SSL and TLS: Setup per Engine and Handshake Failures
- QuickFIX onMessage Not Called: Message Cracking Problems
- Reading and Analyzing QuickFIX Logs: messages.log and event.log