The FIX Converter defines two classes for describing a tag=value message. The FixTag class has an integer ID and a byte array as its value. Getters and setters are provided to access these. The FixTagMessage class is basically a Vector of FixTags.
FIXML documents are manipulated in org.w3c.dom.Document form.
Your FIX Engine may already be providing you with a tag=value representation of your message, in which case, use the methods on FixTag and FixTagMessage to make your FixTagMessage. If not, read on...
To use the FIX converter to parse an array of bytes into its representation of a FIX message in tag=value format, use :-
import org.fixprotocol.contrib.converter.*; Document d = parsed FixRepository.xml FixConv fc = new FixConv(d); byte[] b = the FIX message FixTagMessage ftm = fc.bytesToFixTagMessage( b, extMaj, // eg: "4", "5", or null extMin, // eg: "4", "0", or null extSP, // eg: "SP1", "SP2", or null extEP, // eg: "EP196", or null extCv // eg: "jpmc-to-lse-custom-version", or null );
If the tags (BeginString (8), then possibly the ApplVerID (1128) tag, possibly the AppExtID (1156) tag, and then possibly the CstmApplVerID (1129) tag) identify a version of FIX that is not present in the repository, then the FIX message may not be decoded properly.
If the message doesn't fully define its version, and non-null external values are passed in, then these are used.
Often people edit FIX messages in text editors and don't get it right, especially when preparing test data. They might miss the BeginString, forget the BodyLength, or calculate the CheckSum incorrectly. A method is provided to repair FixTabMessages with these problems :-
ftm.repair();
Note that text editors often append \n or \r\n to the end of each line. You'll need to have stripped this prior to calling bytesToFixTagMessage.
To convert a FixTagMessage back to bytes, you can either :-
byte[] b = fc.fixTagMessageToBytes(ftm);
or :-
byte[] b = ftm.toBytes();
The FixTagMessage also has a handy .toString() method which produces a printable string representation, which is intended primarily for debug purposes. In this printable form, the \xHH notation is used for unprintable ASCII characters, so the SOH characters for example appear as \x01.
To convert a FixTagMessage to FIXML :-
Document d = fc.tagToXml( ftm, // the FixTagMessage extMaj, // eg: "4", "5", or null extMin, // eg: "4", "0", or null extSP, // eg: "SP1", "SP2", or null extEP, // eg: "EP196", or null extCv // eg: "jpmc-to-lse-custom-version", or null );
The FixTagMessage must obey a minimum of FIX rules, including :-
For FIX.5.0 onwards, if the ApplVerID tag is not found, the extMaj and extMin values are used (possibly with the extSP appended, if defined). If the ApplExtID tag is not found, the extEP is used if present. If the CstmApplVerID tag is not found, the extCv is used if present. If these external values are needed, and are not supplied, then an exception is thrown.
The generated XML will have the elements in the correct namespace, eg:
If the input tag=value message has the ApplExtID (1156) tag or if extEP was supplied, then the resulting FIXML message has the xv attribute.
Certain tags in the FixTagMessage must be in the places described by the rules above. The converter will accept other tags in messages and components in orders different to that in the Unified FIX Repository. Rules relating to repeating groups NoXxx tags, and the first tag in each group must still be adhered to (else the message can't be processed).
To convert a FixTagMessage to a printable string, you can :-
String s = fc.fixTagMessageToPretty( ftm, extMaj, // eg: "4", "5", or null extMin, // eg: "4", "0", or null extSP, // eg: "SP1", "SP2", or null extEP, // eg: "EP196", or null extCv // eg: "jpmc-to-lse-custom-version", or null );
This produces a string with one line per field, with each tag annotated with its name. Sometimes it can be easier to read a FIX tag=value message this way.
This method has to operate on an instance of a FixConv as it needs access to the Unified FIX Repository that has been loaded.
The the message doesn't fully define its version, and non-null external values are passed in, then these are used.
To convert from FIXML to tag=value :-
List<FixTagMessage> ftms = fc.xmlToTag( d, // the FIXML document extMaj, // eg: "4", "5", or null extMin, // eg: "4", "0", or null extSP, // eg: "SP1", "SP2", or null extEP, // eg: "EP196", or null extCv // eg: "jpmc-to-lse-custom-version", or null );
The FIXML document is expected to have its elements in the correct namespace. The code still works if no namespace is employed, but you may have to help it determine the version (see the versioning algorithm below for details).
The conversion algorithm inspects the namespace to work out what it can about the major, minor and service pack number of the message. It then looks for the v attribute on the root FIXML element, and also the cv attribute for the custom version. If this is insufficient, it tries to complete the picture by using the external version information passed into the xmlToTag method.
The version algorithm is as follows :-
if namespace missing or doesn't define major and minor if FIXML v attribute present use it else if extMaj and extMin supplied use them else error append extSP if supplied
else if namespace defines major only // this is the new FIX.5.0SP3 onwards style if FIXML v attribute present use it if namespace disagrees with major number in FIXML v attribute error else if extMaj and extMin is supplied use them else error append extSP if supplied
else namespace defines major and minor (and possibly service pack too) use them if FIXML v attribute present if namespace disagrees with info in FIXML v attribute error
Apologies for the above, but I didn't define the standard. This is an attempt to try to do the right thing by default.
The extension pack algorithm is as follows :-
if FIXML xv attribute present use it else if extEP supplied use it else no extension pack
The custom version algorithm is as follows :-
if FIXML cv attribute present use it else if extCv supplied use it else normal, non-customised version
If the input FIXML message has the xv attribute, or if extEP is supplied, then the resulting tag=value message will have the AppExtID (1156) tag.
You may have noticed the result is a list of tag=value messages. This is because FIXML documents may contain a Batch of messages, eg:
<FIXML xmlns="http://www.fixprotocol.org/FIXML-4-4" v="4.4"> <Batch> <!-- This header applies to all the messages --> <Hdr Snt="2001-09-11T09:30:47-05:00" PosDup="N" PosRsnd="N" SeqNum="521" SID="AFUNDMGR" TID="ABROKER"/> <Order ID="123456" Side="2" TxnTm="2001-09-11T09:30:47-05:00" Typ="2" Px="93.25" Acct="26522154"> <Instrmt Sym="IBM" ID="459200101" Src="1"/> <OrdQty Qty="1000"/> </Order> <!-- This second message is a copy of the first, with different ID --> <Order ID="123457" Side="2" TxnTm="2001-09-11T09:30:47-05:00" Typ="2" Px="93.25" Acct="26522154"> <!-- I've also included a message specific header --> <Hdr PosDup="Y"/> <Instrmt Sym="IBM" ID="459200101" Src="1"/> <OrdQty Qty="1000"/> </Order> </Batch> </FIXML>
The converter will ensure each output message has tags from the Batch Hdr, with any values added or overwritten in the individual message Hdrs.
The FIX converter cannot convert a list of tag=value messages into a single FIXML document.
The generated FixTagMessages have their tags in the same order as they are defined in the Unified FIX Repository.