Getting Started with CoralFIX

This article shows the basics of CoralFIX API when it comes to adding/retrieving values from FixMessages, creating new FIX tags and working with repeating groups. You can also get started quickly by using our SimpleFixApplicationServer and SimpleFixApplicationClient as described here.

Working with FixMessages

package com.coralblocks.coralfix.sample;

import static com.coralblocks.coralfix.FixTags.*;

import java.nio.ByteBuffer;

import com.coralblocks.coralbits.util.ByteBufferUtils;
import com.coralblocks.coralfix.FixConstants.FixVersions;
import com.coralblocks.coralfix.FixConstants.MsgTypes;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixParser;

public class Sample {

	public static void main(String[] args) {

		FixMessage fixOutMsg = new FixMessage(FixVersions.VERSION_42);
		// or
		// FixMessage fixOutMsg = new FixMessage(); // defaults to VERSION_44 (you can change the default with -DfixDefaultVersion=50)
		
		fixOutMsg.add(MsgType, MsgTypes.Logon);
		// or
		// fixOutMsg.add(MsgType, 'A'); // same thing as above
		
		fixOutMsg.add(SenderCompID, "TTTTTTT6"). add(TargetCompID, "TAL").add(5555, 3.14).add(34, "1");
		// fluent API
		// you can add by tag name (enum) and tag id (integer)

		fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis()); // UTC time zone by default...
		// timestamps are automatically converted to the FIX format YYYYMMdd HH:mm:ss.SSS
		// or if you need a different time zone:
		// fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis(), TimeZone.getTimeZone("EST"));
		
		
		fixOutMsg.add(7777, 'Y').add(TargetSubID, "ARCA").add(108, 60).add(98,  0);

		// you can print the full message for debugging purposes:
		System.out.println(fixOutMsg);
		// prints BeginString(8)=FIX.4.2 BodyLength(9)=97 MsgType(35)=Logon("A") SenderCompID(49)=TTTTTTT6 TargetCompID(56)=TAL Unknown(5555)=3.14000000 MsgSeqNum(34)=1 SendingTime(52)=20140707-19:37:11.429 Unknown(7777)=Y TargetSubID(57)=ARCA HeartBtInt(108)=60 EncryptMethod(98)=0
		
		ByteBuffer bb = ByteBuffer.allocate(1024);
		
		fixOutMsg.writeTo(bb); // write complete fix message to the ByteBuffer...
		
		bb.flip();

		// you can also print the ByteBuffer for debugging purposes:
		ByteBufferUtils.println(bb); // ByteBufferUtils.println does not change the ByteBuffer position...
		// prints [8=FIX.4.29=9735=A49=TTTTTTT656=TAL5555=3.1400000034=152=20140707-19:37:11.4297777=Y57=ARCA108=6098=010=160]
		// note: SOH character which separates tags is a non-ascii character so you don't see it...

		FixParser parser = new FixParser();

		FixMessage fixMsg = parser.parse(bb);

		// passing the tag name as an enum
		System.out.println(fixMsg.getInt(BodyLength));
		// prints 80
		// BodyLength = tag 9

    	// you can also pass the tag name as a String
		System.out.println(fixMsg.getLong("HeartBtInt")); 
		// prints 60
    	// HeartBtInt = tag 108

		// you can also pass the tag id
		System.out.println(fixMsg.getDouble(5555)); 
		// prints 3.14

		// gets timestamp as epoch UTC long
		System.out.println(fixMsg.getTimestamp(SendingTime)); 
		// prints 1104411600000

		// gets the timestamp as a CharSequence
		System.out.println(fixMsg.getCharSequence(SendingTime));
		// prints 20140707-19:42:57.002

    	// gets a single char
		System.out.println(fixMsg.getChar(7777)); 
		// prints Y

	    // gets value as a CharSequence
		System.out.println(fixMsg.getCharSequence(BeginString)); 
		// prints FIX.4.2
	    // BeginString = tag 8
		
		// gets a ByteBuffer with the value
		System.out.println(fixMsg.getByteBuffer(BeginString));
		// prints java.nio.HeapByteBuffer[pos=2 lim=9 cap=109]

		// prints the whole message for debugging purposes
		System.out.println(fixMsg);
		// prints BeginString(8)=FIX.4.2 BodyLength(9)=109 BeginString(8)=FIX.4.2 BodyLength(9)=87 MsgType(35)=Logon("A") SenderCompID(49)=TTTTTTT6 TargetCompID(56)=TAL Unknown(5555)=3.14 MsgSeqNum(34)=1 SendingTime(52)=20041230-13:00:00 Unknown(7777)=Y TargetSubID(57)=ARCA HeartBtInt(108)=60 EncryptMethod(98)=0 CheckSum(10)=009
	}
}

Notice above that you can add fix tag values to a FixMessage by passing the tag directly (as a Java enum) or the tag id (as an int). The tag values can be passed in a variety of formats from primitives to CharSequences. You can also chain many add methods in the same line (fluent API).

In the other hand, when getting the fix tag values from the FixMessage, you can fetch them in a variety of formats, from primitive values (no garbage is created when parsing primitives) to String and ByteBuffer objects. To get the values you can pass the tag directly (as a Java enum), the tag name (as a String) or the tag id (as an int).

The whole FixMessage can also be printed for debugging purposes through its toString method.

Working with FIX tags and MsgTypes

The class FixTags defines most of the FIX tags by id as specified by the standard FIX dictionary. As we did in our first example above, you can statically import FixTags.* to use fix tags straight in your code by their names (i.e. java enums). Of course you can also add new tags. Below some examples:

import static com.coralblocks.coralfix.FixTags.*;

// the flexibility and convenience of Java enumerations:
System.out.println(AllocAccount); // => AllocAccount(79)

// you can get a FixTag by its id:
System.out.println(fromId(79)); // => AllocAccount(79)

// you can get a FixTag by its name:
System.out.println(fromName("AllocAccount")); // => AllocAccount(79)

// you can define new FixTags easily:
System.out.println(fromName("SuperTag")); // => null
addTag("SuperTag", 6767);
System.out.println(fromName("SuperTag")); // => SuperTag(6767)

// now instead of using the string "SuperTag" everywhere,
// you can create a variable to use instead
private final static FixTag SuperTag = addTag("SuperTag", 6767);
// then use everywhere the variable instead of the string
fixMsg.add(SuperTag, "aValue"); // instead of fixMsg.add("SuperTag", "aValue");
// same thing when getting:
fixMsg.getCharSequence(SuperTag); // instead of fixMsg.getCharSequence("SuperTag");

// you can check if a tag is defined by name and id:
System.out.println(isDefined("BeginString")); // => true
System.out.println(isDefined(79)); // => true
System.out.println(isDefined("blahblah")); // => false
System.out.println(isDefined(8888)); // => false

// and you can print all tags if you want to:
printAll();

By statically importing FixConstants.*, the same can be done for MsgTypes in case you need to define any new one that is not already defined:

import static com.coralblocks.coralfix.FixConstants.*;

System.out.println(MsgTypes.NewOrderSingle); // => NewOrderSingle("D")

// but you can also add new ones:
MsgTypes.add("MyMessageType", "t");
MsgTypes.add("SomeOtherType", "tx");

System.out.println(MsgTypes.fromValue("t")); // => MyMessageType("t")
System.out.println(MsgTypes.fromValue("tx")); // => SomeOtherType("tx")

System.out.println(MsgTypes.fromName("MyMessageType")); // => MyMessageType("t")
System.out.println(MsgTypes.fromName("SomeOtherType")); // => SomeOtherType("tx")

System.out.println(MsgTypes.isValueDefined("t")); // => true
System.out.println(MsgTypes.isNameDefined("SomeOtherType")); // => true

Working with repeating groups

CoralFIX makes it very easy and straightforward to work with FIX repeating groups, even in the situation where you have repeating groups inside repeating groups. See the examples below:

package com.coralblocks.coralfix;

import static com.coralblocks.coralfix.FixConstants.MsgTypes.*;
import static com.coralblocks.coralfix.FixTags.*;

import java.nio.ByteBuffer;
import java.util.Iterator;

public class Sample3 {

	public static void main(String[] args) {
		
		FixMessage fixOutMsg = new FixMessage();

		fixOutMsg.add(MsgType, QuoteStatusRequest);
		
		fixOutMsg.add(SenderCompID, "TTTTTTT6"). add(TargetCompID, "TAL").add(5555, 3.14).add(34, 1);
		fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis());
		fixOutMsg.add(7777, 'Y').add(TargetSubID, "ARCA").add(108, 60).add(98,  0);
		
		FixGroup fixGroup = fixOutMsg.createGroup(NoRelatedSym);
		
		// group element 1:
		fixGroup.nextElement().add(Symbol, "AAPL").add(SettlDate, 1).add(SecurityDesc, "blah1");
		
		// group element 2:
		FixGroupElement fixGroupElem = fixGroup.nextElement();
		fixGroupElem.add(Symbol, "IBM").add(SettlDate, 2).add(SecurityDesc, "blah2");

		// group element 3:
		fixGroupElem = fixGroup.nextElement();
		fixGroupElem.add(Symbol, "LDK");
		fixGroupElem.add(SettlDate, 3).add(SecurityDesc, "blah3");
		
		// group element 4:
		fixGroup.nextElement().add(Symbol, "FB").add(SettlDate, 4).add(SecurityDesc, "blah4");
		
		System.out.println(fixOutMsg); // for debugging purposes...
		
		ByteBuffer bb = ByteBuffer.allocate(1024);
		
		fixOutMsg.writeTo(bb); // write complete fix message to the ByteBuffer...
		
		bb.flip();

		FixParser parser = new FixParser();
		
		// define a repeating group for a message type:
		parser.addGroupTemplate(QuoteStatusRequest, NoRelatedSym, Symbol, SettlDate, SecurityDesc);
	       
         	/* Explanation about addGroupTemplate above:
         	*
         	* QuoteStatusRequest is the message type containing the repeating group
         	*    
         	* NoRelatedSym is the main repeating group tag, meaning the repeating groups will
         	* start after that tag. This tag contains the number (i.e. an integer) of repeating groups that follow.
         	*
         	* Symbol is the very first tag that every repeating group will have. That's important
         	* to correctly denote the starting of a new repeating group and is enforced by the
         	* FIX spec (i.e. you can't start a new repeating group with another tag)
         	*
         	* SettlDate, SecurityDesc, etc. are all the other tags (not included the very first
         	* one above) that this repeating group can contain. They can be specified in any order
         	* and can appear in the repeating group in any order. They are also all optional, in other words,
         	* they do not need to appear in the FIX message but they do have to be specified here.
         	*/
		
		FixMessage fixMsg = parser.parse(bb);
		
		fixGroup = fixMsg.getGroup(NoRelatedSym);
		
		System.out.println(fixGroup.getNumberOfElements()); // => 4

		// you can also print the whole fix group for debugging purposes:
		System.out.println(fixGroup);
		// Symbol(55)=AAPL SettlDate(64)=1 SecurityDesc(107)=blah1 | Symbol(55)=IBM SettlDate(64)=2 SecurityDesc(107)=blah2 | Symbol(55)=LDK SettlDate(64)=3 SecurityDesc(107)=blah3 | Symbol(55)=FB SettlDate(64)=4 SecurityDesc(107)=blah4
		
		System.out.println();
		
		Iterator<FixGroupElement> iter = fixGroup.iterator();
		
		while(iter.hasNext()) {
			
			FixGroupElement elem = iter.next();
			
			// fetch fix tag values as usual:
			System.out.println(elem.getCharSequence(Symbol));
			System.out.println(elem.getInt("SettlDate"));
			System.out.println(elem.getCharSequence(107));
			
			// you can also print the whole element for debugging purposes:
			System.out.println(elem);
			System.out.println();
		}
	}
}

When it comes to building a FixMessage with a repeating group, you just create a FixGroup in the message and then call nextElement() on the FixGroup to create a new FixGroupElement with as many tags as you want. Each FixGroupElement will have the repeating tags of the group and you don’t need to specify the number of repeating groups (i.e. the value of tag NoRelatedSym above) because this is done automatically by counting the number of FixGroupElements created.

When it comes to parsing, the most important part of the code above is where the fix repeating group is specified. The line means: message type QuoteStatusRequest has a repeating group defined by tag NoRelatedSym (specifies the number of repeating group elements) with the following possible tags: Symbol (first and mandatory for all elements), SettlDate and SecurityDesc.

Groups inside groups

A FIX message can contain repeating groups inside repeating groups. CoralFIX makes it very easy to deal with that situation as well. See the examples below:

package com.coralblocks.coralfix;

import static com.coralblocks.coralfix.FixConstants.MsgTypes.*;
import static com.coralblocks.coralfix.FixTags.*;

import java.nio.ByteBuffer;
import java.util.Iterator;

public class Sample4 {

	public static void main(String[] args) {
		
		FixMessage fixOutMsg = new FixMessage();

		fixOutMsg.add(MsgType, QuoteStatusRequest);
		
		fixOutMsg.add(SenderCompID, "TTTTTTT6"). add(TargetCompID, "TAL").add(5555, 3.14).add(34, 1);
		fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis());
		fixOutMsg.add(7777, 'Y').add(TargetSubID, "ARCA").add(108, 60).add(98,  0);
		
		FixGroup fixGroup = fixOutMsg.createGroup(NoRelatedSym);
		
		FixGroupElement elem;
		
		FixGroup subgroup;
		
		// group element 1:
		elem = fixGroup.nextElement();
		elem.add(Symbol, "AAPL").add(SettlDate, 1).add(SecurityDesc, "blah1");
		// subgroup with 2 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, "foo111").add(TestTag2, "foo112");
		subgroup.nextElement().add(TestTag1, "foo121").add(TestTag2, "foo122");
		
		// group element 2:
		elem = fixGroup.nextElement();
		elem.add(Symbol, "IBM").add(SettlDate, 2).add(SecurityDesc, "blah2");
		// subgroup with 3 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, "foo211").add(TestTag2, "foo212");
		subgroup.nextElement().add(TestTag1, "foo221").add(TestTag2, "foo222");
		subgroup.nextElement().add(TestTag1, "foo231").add(TestTag2, "foo232");

		// group element 3:
		elem = fixGroup.nextElement();
		elem.add(Symbol, "LDK").add(SettlDate, 3).add(SecurityDesc, "blah3");
		// subgroup with 1 element:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, "foo311").add(TestTag2, "foo312");
		
		// group element 4:
		elem = fixGroup.nextElement();
		elem.add(Symbol, "FB").add(SettlDate, 4).add(SecurityDesc, "blah4");
		// subgroup with 2 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, "foo411").add(TestTag2, "foo412");
		subgroup.nextElement().add(TestTag1, "foo421").add(TestTag2, "foo422");

		System.out.println(fixOutMsg); // for debugging purposes...
		
		ByteBuffer bb = ByteBuffer.allocate(1024);
		
		fixOutMsg.writeTo(bb); // write complete fix message to the ByteBuffer...
		
		bb.flip();
		
		FixParser parser = new FixParser();
		
		// define a repeating group for a message type:
		parser.addGroupTemplate(QuoteStatusRequest, NoRelatedSym, Symbol, SettlDate, SecurityDesc, NoTestSubgroup);
		parser.addSubgroupTemplate(NoRelatedSym, NoTestSubgroup, TestTag1, TestTag2, TestTag3, TestTag10, TestTag8);

		/*
		* Explanation about the addSubgroupTemplate above:
		* 
		* NoRelatedSym is the parent repeating group, in other words, the repeating group that will 
		* contain another repeating group.
		* It will most likely have been specified by a previous addGroupTemplate method.
		* 
		* NoTestSubgroup is the main repeating group tag, meaning the repeating groups will
		* start after that tag. This tag contains the number (i.e. an integer) of repeating groups that follow.
		* 
		* TestTag1 is the very first tag that every repeating group will have. That's important
		* to correctly denote the starting of a new repeating group and is enforced by the
		* FIX spec (i.e. you can't start a new repeating group with another tag)
		* 
		* TestTag2, TestTag3, TestTag10, TestTag8 are all the other tags (not included the very first
		* one above) that this repeating group can contain. They can be specified in any order
		* and can appear in the repeating group in any order. They are also all optional, in other words,
		* they do not need to appear in the FIX message but they do have to be specified here.
		*/
		
		FixMessage fixMsg = parser.parse(bb);
		fixGroup = fixMsg.getGroup(NoRelatedSym);
		
		Iterator<FixGroupElement> iter = fixGroup.iterator();
		
		while(iter.hasNext()) {
			
			elem = iter.next();
			
			// fetch fix tag values as usual:
			System.out.println(elem.getCharSequence(Symbol));
			System.out.println(elem.getInt("SettlDate"));
			System.out.println(elem.getCharSequence(107));
			
			// you can also fetch a group as usual from the group
			subgroup = elem.getGroup(NoTestSubgroup);

			Iterator<FixGroupElement> iter2 = subgroup.iterator();
			
			while(iter2.hasNext()) {
				
				FixGroupElement e = iter2.next();
				
				// and you can fetch the fix tag values as usual:
				System.out.println(e.getCharSequence(TestTag1));
				System.out.println(e.getCharSequence(TestTag2));
			}
			
			System.out.println();
		}
	}
}

When it comes to building a FixMessage, you can add a subgroup by calling createGroup on a FixGroupElement. Then you just call nextElement() and add the values as usual. When it comes to parsing, the most important part of the code above is where the fix repeating subgroup is specified. This line means: the group NoRelatedSym can contain a subgroup defined by tag NoTestSubgroup (specifies the number of repeating subgroup elements) with the following possible tags: TestTag1 (first and mandatory for all elements) and TestTag2. Also note that we must also include the new tag NoTestSubgroup in the group template list for the group NoRelatedSym.

Conclusion

CoralFIX makes it very easy to parse fix messages. The API comes with the most common fix tags and you can easily define new ones as needed. Working with fix tags is very easy because they are all Java enumerations that you can use directly inside your code. CoralFix also provides a simple and fast API to fetch fix tag values from fix messages, fix repeating groups and even from groups inside groups. The library is an ultra-low-latency Coral Blocks component that has minimal variance and produces zero garbage.