<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coral Blocks &#187; CoralFIX</title>
	<atom:link href="https://www.coralblocks.com/index.php/category/coralfix/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.coralblocks.com/index.php</link>
	<description>Building amazing software, one piece at a time.</description>
	<lastBuildDate>Sat, 25 Apr 2026 13:00:06 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.1</generator>
	<item>
		<title>Why CoralFIX is very fast and easy to use?</title>
		<link>https://www.coralblocks.com/index.php/is-coralfix-the-fastest-and-easiest-to-use-fix-engine/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=is-coralfix-the-fastest-and-easiest-to-use-fix-engine</link>
		<comments>https://www.coralblocks.com/index.php/is-coralfix-the-fastest-and-easiest-to-use-fix-engine/#comments</comments>
		<pubDate>Mon, 05 Oct 2015 03:02:19 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[CoralFIX-HA]]></category>
		<category><![CDATA[asynchronous]]></category>
		<category><![CDATA[coralfix]]></category>
		<category><![CDATA[coralreactor]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[tcp]]></category>
		<category><![CDATA[ultra-low-latency]]></category>

		<guid isPermaLink="false">http://www.coralblocks.com/index.php/?p=1661</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<style>
* {
font-size: 101%;
}</p>
<p>.li_facts { margin: 0 0 17px 0; }
</style>
<p>In this article we list the main reasons that make CoralFIX a very fast and easy to use FIX engine. <span id="more-1661"></span><br />
<br/></p>
<ul>
<li class="li_facts"><strong style="color: #309677">Network I/O:</strong> The most important part of a FIX engine in terms of performance is the network I/O library. That&#8217;s because FIX parsing can be done in nanoseconds while TCP latencies are in microseconds. So it is not enough to be super fast when parsing the FIX message while your bottleneck may be in the network I/O. In addition to parsing a FIX message very fast (in nanoseconds), <strong>CoralFIX uses <a href="http://www.coralblocks.com/coralreactor" target="_blank">CoralReactor</a> under the hood</strong>, which brings our years of experience with Java NIO and network I/O. We provide our own selector implementation which is much faster than the standard JDK implementation.</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Non-Blocking I/O:</strong> CoralFIX is built from the ground up to use non-blocking sockets through Java NIO selectors. That has several advantages over blocking sockets:
<ul>
<br/></p>
<li><strong style="color: #309677">Ultra-Low-Latency:</strong> Blocking sockets are very slow and can block for any arbitrary amount of time when you try to send and receive data. Non-blocking sockets on the other hand never block and sending/receiving data becomes as fast as simply copying data to/from the underlying native socket buffer.</li>
<p><br/></p>
<li><strong style="color: #309677">Scalability:</strong> The same CoralFIX thread can not only handle hundreds of clients but it can also handle clients, servers and any mix of the two. For blocking sockets on the other hand, the old <em>one-thread-per-client</em> approach must be used, which is very hard to scale when the number of threads surpasses the number of available CPU cores. Thread pools or any other trick will not match the flexibility and scalability of non-blocking sockets running inside the same super-fast thread.
</li>
<p><br/></p>
<li><strong style="color: #309677">Simplicity:</strong> The single-threaded approach of CoralFIX eliminates all the issues that are so common to multithreaded programming. You suddenly don&#8217;t have to worry about thread synchronization, lock contention, race-conditions, deadlocks, thread starvation, context switches and many other pitfalls that arise when different threads need to coordinate and share state. Because CoralFIX clients and servers run inside the same thread, all these problems disappear and you can re-allocate your brain power to other tasks.
</li>
</ul>
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Zero Garbage:</strong> All Coral Blocks components <strong>produce zero garbage for the GC</strong> in the critical path. With CoralFIX you are able to send/receive billions of messages without ever producing any garbage. No GC interruption, ever!
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Zero Depedencies:</strong> At Coral Blocks we use <strong>Java as a syntax language</strong>. Our libraries have zero external dependencies and we don&#8217;t even rely on the JDK standard libraries. With CoralFIX you have total control over the critical path.
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Zero Copy:</strong> When parsing a ByteBuffer into a FixMessage object, CoralFIX does not copy any bytes or create any objects. The resulting FixMessage object is backed up by the same ByteBuffer that was parsed. The parsing process simply delimits the tags and values of the FIX message. Moreover all values are <em>lazy parsed</em>, in other words, a price value won&#8217;t be parsed to a double until you explicitly call <em>getDouble(FixTags.Price)</em>. Or you can call <em>getByteBuffer(FixTags.Price)</em> to return your value delimited in the original ByteBuffer, without any parsing.
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Thread Affinity:</strong> Although not a requirement, it is recommended that you <i>pin</i> your critical threads to dedicated cpu cores. <strong>CoralFIX supports thread affinity out-of-the-box</strong> and can pin your critical threads to the cpu cores you specify. To pin your critical threads, all you have to do is pass the cpu core id in the command-line options below:
</li>
<pre>
-DnioReactorProcToBind=CORE_ID 
-DlogProcToBindAsyncThread=CORE_ID
-DfixStoreProcToBind=CORE_ID
</pre>
<style>
.my_br {
  content: "";
  margin: 2em;
  display: block;
  font-size: 100%;
}
</style>
<p><br class="my_br" /></p>
<li class="li_facts"><strong style="color: #309677">Kernel Bypass:</strong> CoralFIX is fully compatible with kernel bypass. We have the expertise with OpenOnLoad from SolarFlare and can help you with the setup/config to bypass the kernel and go straight to the network card buffers to save extra microseconds.
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Audit Logging:</strong> Audit logging is a necessity for production FIX clients and servers. <strong>CoralFIX supports audit logging out-of-the-box</strong> and can asynchronously audit log a message in nanoseconds. To audit log all messages from your fix connection, all you have to do is:
</li>
<pre class="brush: java; title: ; notranslate">
config.add(&quot;auditLog&quot;, true);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Message Persistence:</strong> Although not always enforced, the FIX protocol specifies message retransmission for gap fills. When that&#8217;s in place, all application FIX messages sent must be persisted. <strong>CoralFIX supports messages persistence and retransmission out-of-the-box</strong> and can asynchronously persist application messages to disk in nanoseconds. To support persistence and to make your FIX client or server automatically retransmit messages through gap fills, all you need to do is:
</li>
<pre class="brush: java; title: ; notranslate">
config.add(&quot;supportPersistence&quot;, true);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Sequences Persistence:</strong> CoralFIX persists both inbound and outbound sequences to disk in a asynchronous way, without introducing any latency to the FIX client. That&#8217;s important if your FIX client is restarted so it can remember that last sequences it used. To tell CoralFIX to persist the sequences to disk, all you have to do is:
</li>
<pre class="brush: java; title: ; notranslate">
config.add(&quot;persistSequences&quot;, true);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">FIX Versions:</strong> <strong>CoralFIX supports all FIX versions.</strong> To specify the version you want to use, all you have to do is:
</li>
<pre class="brush: java; title: ; notranslate">
config.add(&quot;fixVersion&quot;, FixVersions.VERSION_44);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">FIX Session Protocol:</strong> <strong>CoralFIX makes all the FIX session protocol details transparent to the developer.</strong> That means you don&#8217;t have to worry about sequences, resend requests, sequence resets, gap fills, logon, logout, heartbeats, test requests or any other low level FIX detail. With CoralFIX you only focus on your application logic. You can even start a FIX client with few lines of code:
</li>
<pre class="brush: java; title: ; notranslate">
NioReactor nio = NioReactor.create();
		
MapConfiguration config = new MapConfiguration();
config.add(&quot;fixVersion&quot;, FixVersions.VERSION_44);
config.add(&quot;senderComp&quot;, &quot;testClient&quot;);

Client client = new FixApplicationClient(nio, &quot;localhost&quot;, 45451, config);		
client.open();

nio.start();
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">FIX Session Timers:</strong> <strong>CoralFIX supports session timers out-of-the-box</strong> so you can synchronize your FIX session with the exchange hours of operation. You can set daily and weekly timers to start or stop your FIX connection and optionally reset the sequences (defaults to true). To set a timer all you have to do is:
</li>
<pre class="brush: java; title: ; notranslate">
// add a start session timer daily at 14:30:00 EST
config.add(&quot;startSessionTimer&quot;, &quot;D-EST-14:30:00&quot;);
 
// add a stop session timer weekly on Sunday at 16:00:00 EST
config.add(&quot;stopSessionTimer&quot;, &quot;W-SUNDAY-EST-16:00:00&quot;);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">High Level API:</strong> CoralFIX provides a high-level and easy-to-use API based on our <strong>vast experience writing several different FIX trading gateways and market data feeds</strong> for all kinds of markets. We are constantly improving the API based on our customers feedback and our own research to make it even easier to understand and use. Below an example of how you would send a message from a CoralFIX client:
</li>
<pre class="brush: java; title: ; notranslate">
// Get a FIX message ready to be sent out, with sequences, header and everything taken care for you
FixMessage outFixMsg = getOutFixMessage(MsgTypes.NewOrderSingle);

// Add any kind of value as a tag
outFixMsg.add(Price, 50.34);
outFixMsg.add(ClOrdID, &quot;A123&quot;);
outFixMsg.add(Side, '2');

// Add a repeating group
FixGroup partyIds = outFixMsg.createGroup(NoPartyIDs);
partyIds.nextElement().add(PartyID, &quot;BLAH&quot;).add(PartyIDSource, 'D').add(PartyRole, 54);
partyIds.nextElement().add(PartyID, &quot;TRD&quot;).add(PartyIDSource, 'D').add(PartyRole, 36);

// Send out the message to the client
send(outFixMsg);
</pre>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Benchmarks:</strong> Our clients can modify and run our benchmark source code <strong>on their own environment</strong> to access the performance numbers. We publish our numbers as a reference but we encourage our clients to benchmark CoralFIX themselves. They have been doing that and reporting back results that they are unable to get through other FIX engine alternatives, even in C++. In our lab, we are able to go <a href="http://www.coralblocks.com/index.php/2014/10/ultra-low-latency-with-coralfix-and-coralreactor/" target="_blank">as low as 4.8 micros</a> for the one-way latency to send a FIX message from a client to a server over loopback. We have also used <code>tcpdump</code> and <i>Wireshark</i> to measure the <a href="http://www.coralblocks.com/index.php/2015/08/tick-to-trade-latency-numbers-using-coralfix-and-coralreactor/" target="_blank">tick-to-trade latencies</a> and they are around 8 micros.
</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Release Early, Release Often:</strong> We work very close to our customers and we are constantly listening to their feedback for improvements and new features. We have a quick release cycle and we release often to incorporate our customers needs as soon as they ask for them.</li>
<p><br/></p>
<li class="li_facts"><strong style="color: #309677">Satisfied Customers:</strong> CoralFIX has been used in production by small and big companies for years with great results. Our customers are not only happy with better performance numbers, but they are also able to complete and deploy their projects more quickly, increasing their productivity and reducing time-to-market.
</ul>
<p><br/></p>
<h3 class="coral">Conclusion</h3>
<p>Although it is important for a FIX engine to be as fast as possible, and we got that covered through fast parsing and networking, at Coral Blocks we believe that ease of use is even more important. Not just CoralFIX but all of our components must be very easy to understand, integrate and use. <strong>Our licensing model also allows us to have a commitment to our clients in providing first-class support and to share our know-how</strong> throughout the license period. We are passionate about what we do and we enjoy working side-by-side with our clients to bring outstanding results.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/is-coralfix-the-fastest-and-easiest-to-use-fix-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FIX clients and servers with CoralFIX and CoralReactor</title>
		<link>https://www.coralblocks.com/index.php/fix-clients-and-servers-with-coralfix/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fix-clients-and-servers-with-coralfix</link>
		<comments>https://www.coralblocks.com/index.php/fix-clients-and-servers-with-coralfix/#comments</comments>
		<pubDate>Tue, 08 Jul 2014 12:59:22 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[fix protocol]]></category>
		<category><![CDATA[sequences]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://cb.soliveirajr.com/index.php/?p=531</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CoralFIX is fully integrated with <a href="/index.php/category/coralreactor/" target="_blank">CoralReactor</a> so you can code your own ultra-low-latency, ultra-low-variance (i.e. no GC overhead) FIX network clients and servers. In this article we introduce the <code>FixApplicationClient</code> and the <code>FixApplicationServer</code> that you can use to code a FIX connection that takes care of all the low-level FIX session details for you, like logon, heartbeats, sequence reset, etc. <span id="more-531"></span></p>
<h3 class="coral">FixApplicationClient and FixApplicationServer</h3>
<p>By inheriting from <code>FixApplicationClient</code> you can code a fully functional FIX connection that will handle all the low-level session details of the FIX protocol like sequences, logon, resend requests, etc. All you have to do is handle the incoming application messages in any way you want. See an example below:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.sample;

import static com.coralblocks.coralfix.FixTags.*;

import com.coralblocks.coralfix.FixConstants.FixVersions;
import com.coralblocks.coralfix.FixConstants.MsgTypes;
import com.coralblocks.coralfix.FixGroup;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixTag;
import com.coralblocks.coralfix.FixTags;
import com.coralblocks.coralfix.client.FixApplicationClient;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class SimpleFixApplicationClient extends FixApplicationClient {
	
	// Add any extra / non-standard fix tag from your spec, so you can work with the name instead of the id
	private static FixTag MySpecialTag = FixTags.addTag(&quot;MySpecialTag&quot;, 3434);
	
	public SimpleFixApplicationClient(NioReactor nio, String localhost, int port, Configuration config) {
	    super(nio, localhost, port, config);
    }
	
	@Override
	protected void handleOpened() {
		// client was opened and will now try to connect to its destination
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleClosed() {
		// client was closed, its connection was terminated and it will now sit idle
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionEstablished() {
		// socket connection was established but no login handshake was done yet
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionOpened() {
		// the FIX session handshake through LOGON messages was performed...
		// the client is now ready to start sending/receiving messages
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionReady() {
		// any sequence reset or re-send request have been processed at the session level...
		// the client is now ready to start sending/receiving any business application messages
		
		// do anything you want to do here...
		
		sendNewOrderSingle();
	}
	
	private void sendNewOrderSingle() {
		
		FixMessage outFixMsg = getOutFixMessage(MsgTypes.NewOrderSingle);
		
		// Add the tags you want to outFixMsg
		// NOTE: there is no need to add any session-level tags like MsgSeqNum, SenderCompID, etc.
		outFixMsg.add(Price, 50.34);
		outFixMsg.addTimestamp(TransactTime, System.currentTimeMillis());
		outFixMsg.add(ClOrdID, &quot;A123&quot;);
		outFixMsg.add(MySpecialTag, 'Y');
		
		// Add a repeating group
		FixGroup partyIds = outFixMsg.createGroup(NoPartyIDs);
		partyIds.nextElement().add(PartyID, &quot;BLAH&quot;).add(PartyIDSource, 'D').add(PartyRole, 54);
		partyIds.nextElement().add(PartyID, &quot;TRD&quot;).add(PartyIDSource, 'D').add(PartyRole, 36);
		partyIds.nextElement().add(PartyID, &quot;FOO&quot;).add(PartyIDSource, 'D').add(PartyRole, 7);
		
		// Send out the message to the client
		send(outFixMsg);
	}
	
	@Override
	protected void handleConnectionTerminated() {
		// the socket connection was broken/terminated
		
		// do anything you want to do here...
	}
	
	@Override
	protected void prepareLogon(FixMessage outFixMsg) {
		super.prepareLogon(outFixMsg);
		
		// add/remove any tag here... probably not necessary because the base
		// class is already adding all the required tags
	}
	
	@Override
	protected void handleFixApplicationMessage(FixMessage fixMsg, boolean possDupe) {
		
		// do what you have to do with this FIX application message
	}		
	
	public static void main(String[] args) {
		
		String senderComp = args.length &gt; 0 ? args[0] : &quot;testClient&quot;;
		
		NioReactor nio = NioReactor.create();
		
		MapConfiguration config = new MapConfiguration();
		
		// REQUIRED
		config.add(&quot;fixVersion&quot;, FixVersions.VERSION_44);
		
		// the senderComp of the fix client
		// REQUIRED
		config.add(&quot;senderComp&quot;, senderComp);
		
		// NOT required:
		// config.add(&quot;targetComp&quot;, &quot;testAcct&quot;); // the TargetCompID tag
		// config.add(&quot;senderSub&quot;, &quot;xxx&quot;); // the SenderSubID tag
		// config.add(&quot;targetSub&quot;, &quot;yyy&quot;); // the TargetSubID tag
		// config.add(&quot;senderLoc&quot;, &quot;aaa&quot;); // the SenderLocationID tag
		// config.add(&quot;heartbeat&quot;, &quot;20&quot;); // the HeartBtInt tag (defaults to 10 seconds)
		// config.add(&quot;encryption&quot;, &quot;1&quot;); // the EncryptMethod tag (defaults to 0)
		// config.add(&quot;username&quot;, &quot;myusername&quot;); // sends the Username tag with the Logon message
		// config.add(&quot;password&quot;, &quot;mypass&quot;); // the RawData tag (the RawDataLength tag will also be included)
		
		// print all messages received and sent to STDOUT for debugging purposes
		// (default is false)
		config.add(&quot;debugMessages&quot;, true);
		// config.add(&quot;debugHeartbeats&quot;, true); // show heartbeats as well (default is true)
		
		// send a ResetSeqNumFlag=Y on Logon to force a sequence reset on both sides (inbound and outbound)
		// (default is false)
		config.add(&quot;forceSeqReset&quot;, true);
		
		// turn on asynchronous audit logging
		// (default is false)
		config.add(&quot;auditLog&quot;, false);
		// config.add(&quot;auditLogDir&quot;, &quot;/mylogdir/&quot;); // set the folder where to save the audit log file (default is &quot;auditLog&quot;)
		
		// turn on asynchronous fix logging (human readable fix messages)
		// (default is false)
		config.add(&quot;fixLog&quot;, false);
		// config.add(&quot;fixLogDir&quot;, &quot;/mylogdir&quot;); // set the folder where to save the fix log file (default is &quot;fixLog&quot;)
		// config.add(&quot;fixLogHeartbeats&quot;, true); // log heartbeats to the fix log (default is false)
		
		// persist sequences asynchronously to a file, so you don't lose them across restarts
		// (default is false)
		config.add(&quot;persistSequences&quot;, false);
		// config.add(&quot;persistDir&quot;, &quot;mySeqFolder&quot;); // the folder where to store the sequence files (default is current dir)
		// config.add(&quot;persistFilename, &quot;mySeqFilename&quot;); // the filename of the sequence file (default is the client name)
		
		// persists outbound fix messages asynchronously for message resends / gap fills
		// (default is false)
		config.add(&quot;supportPersistence&quot;, false);
		
		// open the admin server to accept telnet connections to monitor and control this fix client
		// (default is false)
		config.add(&quot;adminServer&quot;, false);
		
		// change the port for the admin server
		// (default is 45441)
		config.add(&quot;adminServerPort&quot;, 45441);
		
		// change to put the outbound FIX store in another thread
		// (default is true)
		config.add(&quot;fixStoreAsync&quot;, false);
		
		// set heartbeat interval in seconds
		// (default is 10)
		config.add(&quot;heartbeat&quot;, 5);
		
		/*
		// More optional config parameters
		// IMPORTANT: The default values should be what you want most of the time!
		
		config.add(&quot;includeLastMsgSeqNumProcessedTag&quot;, false); // include this header tag on every fix message? (default is true)
		
		config.add(&quot;maxLogonAttempts&quot;, 10); // if Logon fail for whatever reason, retry (default is 5)
		
		config.add(&quot;secondsToReopenAfterClose&quot;, 60 * 10); // if can't logon, then client will be closed and re-open after N seconds (default is 300)
		
		config.add(&quot;sendLogoutOnClose&quot;, false); // on a client close, a logout message will be sent (default is false)
		
		config.add(&quot;sendLogonOnConnected&quot;, true); // when socket is estabilished send logon automatically (default is true)
		
		config.add(&quot;persistSequencesImmediately&quot;, false); // force the mmap file to commit the the sequences to disk immediately (default is false)
		
		config.add(&quot;sequence&quot;, 1); // the initial inbound sequence (default is 1 or whatever is persisted if persistence is on)
		
		config.add(&quot;outboundSeq&quot;, 1); // the initial outbound sequence (default is 1 or wahtever is persisted if persitence is on)
		
		config.add(&quot;acceptInboundSeqFromServer&quot;, false); // accept whatever sequence you get from server as your inbound sequence (default is false)
		
		config.add(&quot;disconnectOnGap&quot;, false); // disconnect on gap instead of sending a sequence reset / message retransmission (default is false)
		
		config.add(&quot;reconnectOnStartTimerEvent&quot;, true); // when using a start timer, reconnect if connected (default is true)
		
		config.add(&quot;resetSequencesOnStartTimerEvent&quot;, true); // when using a start timer, reset the sequences (default is true)
		 */
		
		/*
		// More optional config parameters related to the max size of FIX messages:
		
		config.add(&quot;fixMaxTags&quot;, 64); // max number of tags, not including tags from repeating groups (defaults to 64)
		config.add(&quot;fixMaxGroups&quot;, 8); // max number of different repeating groups a message can have (defaults to 8)
		config.add(&quot;fixMaxValueLength&quot;, 256); // max length of a tag value in characters (defaults to 256)
		config.add(&quot;fixMaxGroupElements&quot;, 64); // max number of repeating group elements (defaults to 64)
		config.add(&quot;fixMaxValuesPerGroupElement&quot;, 64); // max number of repeating group tags/values per group element (defaults to 64)
		 */
		
		Client client = new SimpleFixApplicationClient(nio, &quot;localhost&quot;, 45451, config);
		client.open();
		
		nio.start();
	}
}
</pre>
<p>And same thing in the server side, by inheriting from <code>FixApplicationServer</code>:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.sample;

import static com.coralblocks.coralfix.FixTags.*;

import java.util.Iterator;

import com.coralblocks.coralfix.FixConstants.FixVersions;
import com.coralblocks.coralfix.FixConstants.MsgTypes;
import com.coralblocks.coralfix.FixGroup;
import com.coralblocks.coralfix.FixGroupElement;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixTag;
import com.coralblocks.coralfix.FixTags;
import com.coralblocks.coralfix.server.FixApplicationServer;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class SimpleFixApplicationServer extends FixApplicationServer {
	
	// Add any extra / non-standard fix tag from your spec, so you can work with the name instead of the id
	private static FixTag MySpecialTag = FixTags.addTag(&quot;MySpecialTag&quot;, 3434);

	public SimpleFixApplicationServer(NioReactor nio, int port, Configuration config) {
		super(nio, port, config);
		
	    // Specify the repeating group you expect to parse, for each message type:
	    addGroupTemplate(MsgTypes.NewOrderSingle, NoPartyIDs, PartyID, PartyIDSource, PartyRole);
	    
	   /* Explanation about addGroupTemplate above:
        *
        * MsgTypes.NewOrderSingle is the message type containing the repeating group
        *    
        * NoPartyIDs 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.
        *
        * PartyID 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)
        *
        * PartyIDSource, PartyRole, 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, ALL OF THEM.
        */
    }
	
	@Override
	protected void handleOpened() {
		// sever was opened and will now accept connections from clients...
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleClosed() {
		// server was closed, all clients were disconnected and it will not accept any connection...
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionEstablished(Client client) {
		// socket connection was established for a client but no login handshake was done yet
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionOpened(Client client) {
		// the FIX session handshake through LOGON messages was performed for this client...
		// the client is now ready to start sending/receiving messages
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionReady(Client client) {
		// any sequence reset or re-send request have been processed at the session level...
		// the client is now ready to start sending/receiving any business application messages
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleConnectionTerminated(Client client) {
		// the socket connection was broken/terminated for this client
		
		// do anything you want to do here...
	}
	
	@Override
	protected void handleFixApplicationMessage(Client client, FixMessage fixMsg, boolean possDupe) {
		
		// do whatever you want to do with the application message received from this client...
		
		if (fixMsg.checkType(MsgTypes.NewOrderSingle)) {
			
			double price = fixMsg.getDouble(Price);
			System.out.println(&quot;Read price: &quot; + price);
			
			CharSequence clOrdID = fixMsg.getCharSequence(ClOrdID);
			System.out.println(&quot;Read ClOrdID: &quot; + clOrdID);
			
			char mySpecialTag = fixMsg.getChar(MySpecialTag);
			System.out.println(&quot;Read MySpecialTag: &quot; + mySpecialTag);
			
			FixGroup fixGroup = fixMsg.getGroup(NoPartyIDs);
			System.out.println(fixGroup.getNumberOfElements());
		 
			// you can also print the whole fix group for debugging purposes:
			System.out.println(fixGroup);
		         
	        Iterator&lt;FixGroupElement&gt; iter = fixGroup.iterator();
		         
	        while(iter.hasNext()) {
	             
	            FixGroupElement elem = iter.next();
	            
	            CharSequence partyID = elem.getCharSequence(PartyID);
	            System.out.println(partyID);
	            
	            char partyIDSource = elem.getChar(PartyIDSource);
	            System.out.println(partyIDSource);
	            
	            int partyRole = elem.getInt(PartyRole);
	            System.out.println(partyRole);
	             
	            // you can also print the whole element for debugging purposes:
	            System.out.println(elem);
	        }
		}
	}
	
	public static void main(String[] args) {

		NioReactor nio = NioReactor.create();
		
		MapConfiguration config = new MapConfiguration();
		
		// REQUIRED
		config.add(&quot;fixVersion&quot;, FixVersions.VERSION_44);
		
		// print all messages received and sent to STDOUT for debugging purposes
		// (default is false)
		config.add(&quot;debugMessages&quot;, true);
		
		// accept as the client inbound sequence whatever sequence I receive in the first message coming from the client
		// (default is false)
		config.add(&quot;acceptInboundSeqFromClient&quot;, false);
		
		// turn on asynchronous audit logging
		// (default is false)
		config.add(&quot;auditLog&quot;, false);
		
		// turn on asynchronous fix logging (human readable fix messages)
		// (default is false)
		config.add(&quot;fixLog&quot;, false);
		
		// persist all sequences from all clients (senderCompIDs) to disk
		// (default is false)
		config.add(&quot;persistSequences&quot;, false);
		
		// support persistence of outbound fix messages for message resends / gap fills
		// (default is false)
		config.add(&quot;supportPersistence&quot;, false);
		
		// enable the telnet admin server
		// (default is false)
		config.add(&quot;adminServer&quot;, false);
		
		// change the port for the admin server
		// (default is 45442)
		config.add(&quot;adminServerPort&quot;, 45442);
		
		// change to put the outbound FIX store in another thread
		// (default is true)
		config.add(&quot;fixStoreAsync&quot;, false);
		
		FixApplicationServer server = new SimpleFixApplicationServer(nio, 45451, config);
		server.open();

		nio.start();
	}
}
</pre>
<h2 class="coral">Conclusion</h2>
<p>CoralFIX is fully integrated with <a href="/index.php/category/coralreactor/" target="_blank">CoralReactor</a> so you can easily code your own FIX clients and servers. Furthermore, it takes care of all the low-level session details of the FIX protocol for you, so all you have to do is handle messages in the application level.</p>
<p><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/fix-clients-and-servers-with-coralfix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Started with CoralFIX</title>
		<link>https://www.coralblocks.com/index.php/getting-started-with-coralfix/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=getting-started-with-coralfix</link>
		<comments>https://www.coralblocks.com/index.php/getting-started-with-coralfix/#comments</comments>
		<pubDate>Wed, 02 Jul 2014 17:40:07 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[fix engine]]></category>
		<category><![CDATA[fix parser]]></category>
		<category><![CDATA[gc]]></category>
		<category><![CDATA[repeating groups]]></category>

		<guid isPermaLink="false">http://cb.soliveirajr.com/index.php/?p=481</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>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 <code>SimpleFixApplicationServer</code> and <code>SimpleFixApplicationClient</code> as described <a href="/index.php/2014/07/fix-clients-and-servers-with-coralfix/" target="_blank">here</a>.<span id="more-481"></span></p>
<h2 class="coral">Working with FixMessages</h2>
<pre class="brush: java; title: ; notranslate">
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, &quot;TTTTTTT6&quot;). add(TargetCompID, &quot;TAL&quot;).add(5555, 3.14).add(34, &quot;1&quot;);
		// 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(&quot;EST&quot;));
		
		
		fixOutMsg.add(7777, 'Y').add(TargetSubID, &quot;ARCA&quot;).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(&quot;A&quot;) 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.29=9735=A49=TTTTTTT656=TAL5555=3.1400000034=152=20140707-19:37:11.4297777=Y57=ARCA108=6098=010=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(&quot;HeartBtInt&quot;)); 
		// 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(&quot;A&quot;) 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
	}
}
</pre>
<p>Notice above that you can add <em>fix tag values</em> to a <code>FixMessage</code> by passing the tag directly (<em>as a Java enum</em>) or the tag id (<em>as an int</em>). The <em>tag values</em> can be passed in a variety of formats from primitives to <code>CharSequence</code>s. You can also <em>chain</em> many <code>add</code> methods in the same line (<em>fluent API</em>).</p>
<p>In the other hand, when getting the <em>fix tag values</em> from the <code>FixMessage</code>, you can fetch them in a variety of formats, from primitive values (<em>no garbage is created when parsing primitives</em>) to <code>String</code> and <code>ByteBuffer</code> objects. To get the values you can pass the tag directly (<em>as a Java enum</em>), the tag name (<em>as a String</em>) or the tag id (<em>as an int</em>).</p>
<p>The whole <code>FixMessage</code> can also be printed for debugging purposes through its <code>toString</code> method.</p>
<h2 class="coral">Working with FIX tags and MsgTypes</h2>
<p>The class <code>FixTags</code> 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 <code>FixTags.*</code> 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:</p>
<pre class="brush: java; title: ; notranslate">
import static com.coralblocks.coralfix.FixTags.*;

// the flexibility and convenience of Java enumerations:
System.out.println(AllocAccount); // =&gt; AllocAccount(79)

// you can get a FixTag by its id:
System.out.println(fromId(79)); // =&gt; AllocAccount(79)

// you can get a FixTag by its name:
System.out.println(fromName(&quot;AllocAccount&quot;)); // =&gt; AllocAccount(79)

// you can define new FixTags easily:
System.out.println(fromName(&quot;SuperTag&quot;)); // =&gt; null
addTag(&quot;SuperTag&quot;, 6767);
System.out.println(fromName(&quot;SuperTag&quot;)); // =&gt; SuperTag(6767)

// now instead of using the string &quot;SuperTag&quot; everywhere,
// you can create a variable to use instead
private final static FixTag SuperTag = addTag(&quot;SuperTag&quot;, 6767);
// then use everywhere the variable instead of the string
fixMsg.add(SuperTag, &quot;aValue&quot;); // instead of fixMsg.add(&quot;SuperTag&quot;, &quot;aValue&quot;);
// same thing when getting:
fixMsg.getCharSequence(SuperTag); // instead of fixMsg.getCharSequence(&quot;SuperTag&quot;);

// you can check if a tag is defined by name and id:
System.out.println(isDefined(&quot;BeginString&quot;)); // =&gt; true
System.out.println(isDefined(79)); // =&gt; true
System.out.println(isDefined(&quot;blahblah&quot;)); // =&gt; false
System.out.println(isDefined(8888)); // =&gt; false

// and you can print all tags if you want to:
printAll();
</pre>
<p>By statically importing <code>FixConstants.*</code>, the same can be done for MsgTypes in case you need to define any new one that is not already defined:</p>
<pre class="brush: java; title: ; notranslate">
import static com.coralblocks.coralfix.FixConstants.*;

System.out.println(MsgTypes.NewOrderSingle); // =&gt; NewOrderSingle(&quot;D&quot;)

// but you can also add new ones:
MsgTypes.add(&quot;MyMessageType&quot;, &quot;t&quot;);
MsgTypes.add(&quot;SomeOtherType&quot;, &quot;tx&quot;);

System.out.println(MsgTypes.fromValue(&quot;t&quot;)); // =&gt; MyMessageType(&quot;t&quot;)
System.out.println(MsgTypes.fromValue(&quot;tx&quot;)); // =&gt; SomeOtherType(&quot;tx&quot;)

System.out.println(MsgTypes.fromName(&quot;MyMessageType&quot;)); // =&gt; MyMessageType(&quot;t&quot;)
System.out.println(MsgTypes.fromName(&quot;SomeOtherType&quot;)); // =&gt; SomeOtherType(&quot;tx&quot;)

System.out.println(MsgTypes.isValueDefined(&quot;t&quot;)); // =&gt; true
System.out.println(MsgTypes.isNameDefined(&quot;SomeOtherType&quot;)); // =&gt; true

</pre>
<h2 class="coral">Working with repeating groups</h2>
<p>CoralFIX makes it <strong>very easy</strong> and straightforward to work with FIX repeating groups, even in the situation where you have repeating groups inside repeating groups. See the examples below:</p>
<pre class="brush: java; title: ; notranslate">
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, &quot;TTTTTTT6&quot;). add(TargetCompID, &quot;TAL&quot;).add(5555, 3.14).add(34, 1);
		fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis());
		fixOutMsg.add(7777, 'Y').add(TargetSubID, &quot;ARCA&quot;).add(108, 60).add(98,  0);
		
		FixGroup fixGroup = fixOutMsg.createGroup(NoRelatedSym);
		
		// group element 1:
		fixGroup.nextElement().add(Symbol, &quot;AAPL&quot;).add(SettlDate, 1).add(SecurityDesc, &quot;blah1&quot;);
		
		// group element 2:
		FixGroupElement fixGroupElem = fixGroup.nextElement();
		fixGroupElem.add(Symbol, &quot;IBM&quot;).add(SettlDate, 2).add(SecurityDesc, &quot;blah2&quot;);

		// group element 3:
		fixGroupElem = fixGroup.nextElement();
		fixGroupElem.add(Symbol, &quot;LDK&quot;);
		fixGroupElem.add(SettlDate, 3).add(SecurityDesc, &quot;blah3&quot;);
		
		// group element 4:
		fixGroup.nextElement().add(Symbol, &quot;FB&quot;).add(SettlDate, 4).add(SecurityDesc, &quot;blah4&quot;);
		
		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()); // =&gt; 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&lt;FixGroupElement&gt; 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(&quot;SettlDate&quot;));
			System.out.println(elem.getCharSequence(107));
			
			// you can also print the whole element for debugging purposes:
			System.out.println(elem);
			System.out.println();
		}
	}
}
</pre>
<p>When it comes to building a <code>FixMessage</code> with a repeating group, you just create a <code>FixGroup</code> in the message and then call <code>nextElement()</code> on the <code>FixGroup</code> to create a new <code>FixGroupElement</code> with as many tags as you want. Each <code>FixGroupElement</code> will have the repeating tags of the group and you don&#8217;t need to specify the number of repeating groups (i.e. the value of tag <code>NoRelatedSym</code> above) because this is done automatically by counting the number of <code>FixGroupElement</code>s created.</p>
<p>When it comes to parsing, the most important part of the code above is where the <em>fix repeating group</em> is specified. The line means: message type <code>QuoteStatusRequest</code> has a repeating group defined by tag <code>NoRelatedSym</code> (<em>specifies the number of repeating group elements</em>) with the following possible tags: <code>Symbol</code> (<em>first and mandatory for all elements</em>), <code>SettlDate</code> and <code>SecurityDesc</code>.</p>
<h2 class="coral">Groups inside groups</h2>
<p>A FIX message can contain <em>repeating groups inside repeating groups</em>. CoralFIX makes it <strong>very easy</strong> to deal with that situation as well. See the examples below:</p>
<pre class="brush: java; title: ; notranslate">
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, &quot;TTTTTTT6&quot;). add(TargetCompID, &quot;TAL&quot;).add(5555, 3.14).add(34, 1);
		fixOutMsg.addTimestamp(SendingTime, System.currentTimeMillis());
		fixOutMsg.add(7777, 'Y').add(TargetSubID, &quot;ARCA&quot;).add(108, 60).add(98,  0);
		
		FixGroup fixGroup = fixOutMsg.createGroup(NoRelatedSym);
		
		FixGroupElement elem;
		
		FixGroup subgroup;
		
		// group element 1:
		elem = fixGroup.nextElement();
		elem.add(Symbol, &quot;AAPL&quot;).add(SettlDate, 1).add(SecurityDesc, &quot;blah1&quot;);
		// subgroup with 2 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, &quot;foo111&quot;).add(TestTag2, &quot;foo112&quot;);
		subgroup.nextElement().add(TestTag1, &quot;foo121&quot;).add(TestTag2, &quot;foo122&quot;);
		
		// group element 2:
		elem = fixGroup.nextElement();
		elem.add(Symbol, &quot;IBM&quot;).add(SettlDate, 2).add(SecurityDesc, &quot;blah2&quot;);
		// subgroup with 3 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, &quot;foo211&quot;).add(TestTag2, &quot;foo212&quot;);
		subgroup.nextElement().add(TestTag1, &quot;foo221&quot;).add(TestTag2, &quot;foo222&quot;);
		subgroup.nextElement().add(TestTag1, &quot;foo231&quot;).add(TestTag2, &quot;foo232&quot;);

		// group element 3:
		elem = fixGroup.nextElement();
		elem.add(Symbol, &quot;LDK&quot;).add(SettlDate, 3).add(SecurityDesc, &quot;blah3&quot;);
		// subgroup with 1 element:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, &quot;foo311&quot;).add(TestTag2, &quot;foo312&quot;);
		
		// group element 4:
		elem = fixGroup.nextElement();
		elem.add(Symbol, &quot;FB&quot;).add(SettlDate, 4).add(SecurityDesc, &quot;blah4&quot;);
		// subgroup with 2 elements:
		subgroup = elem.createGroup(NoTestSubgroup);
		subgroup.nextElement().add(TestTag1, &quot;foo411&quot;).add(TestTag2, &quot;foo412&quot;);
		subgroup.nextElement().add(TestTag1, &quot;foo421&quot;).add(TestTag2, &quot;foo422&quot;);

		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&lt;FixGroupElement&gt; 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(&quot;SettlDate&quot;));
			System.out.println(elem.getCharSequence(107));
			
			// you can also fetch a group as usual from the group
			subgroup = elem.getGroup(NoTestSubgroup);

			Iterator&lt;FixGroupElement&gt; 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();
		}
	}
}
</pre>
<p>When it comes to building a <code>FixMessage</code>, you can add a subgroup by calling <code>createGroup</code> on a <code>FixGroupElement</code>. Then you just call <code>nextElement()</code> and add the values as usual. When it comes to parsing, the most important part of the code above is where the fix repeating <em>subgroup</em> is specified. This line means: the group <code>NoRelatedSym</code> can contain a subgroup defined by tag <code>NoTestSubgroup</code> (<em>specifies the number of repeating subgroup elements</em>) with the following possible tags: <code>TestTag1</code> (<em>first and mandatory for all elements</em>)  and <code>TestTag2</code>. Also note that we must also include the new tag <code>NoTestSubgroup</code> in the group template list for the group <code>NoRelatedSym</code>.</p>
<h2 class="coral">Conclusion</h2>
<p>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.</p>
<p><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/getting-started-with-coralfix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CoralFIX Parser Performance Numbers</title>
		<link>https://www.coralblocks.com/index.php/coralfix-performance-numbers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=coralfix-performance-numbers</link>
		<comments>https://www.coralblocks.com/index.php/coralfix-performance-numbers/#comments</comments>
		<pubDate>Wed, 09 Jul 2014 19:47:53 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[fix parser]]></category>
		<category><![CDATA[fix protocol]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[throughput]]></category>
		<category><![CDATA[ultra-low-latency]]></category>

		<guid isPermaLink="false">http://cb.soliveirajr.com/index.php/?p=537</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In this article we present the performance numbers of CoralFIX when it comes to parsing messages. We measure the time it takes to generate a <code>ByteBuffer</code> from a <code>FixMessage</code> and the time it takes to generate a <code>FixMessage</code> from a <code>ByteBuffer</code>. For that we use three FIX messages: a simple one without repeating groups, one with a repeating group and lastly one with repeating groups inside repeating groups. <span id="more-537"></span></p>
<p>The machine used for the benchmarks below was an Intel i7 quad-core (4 x 3.50GHz) Ubuntu box overclocked to 4.50Ghz.</p>
<h2 class="coral">Simple FIX Message</h2>
<p>For our test we randomize 2.5 million FIX messages like the one below:</p>
<pre>
BeginString(8)=FIX.4.2 BodyLength(9)=101 MsgType(35)=SecurityStatusRequest("e") SenderCompID(49)=TTTTTTT6 TargetCompID(56)=872 
Unknown(5555)=6236.83333333 MsgSeqNum(34)=99 SendingTime(52)=20140709-14:43:12.934 Unknown(7777)=Y TargetSubID(57)=ARCA 
HeartBtInt(108)=60 EncryptMethod(98)=0 CheckSum(10)=114
</pre>
<p>From <code>FixMessage</code> to <code>ByteBuffer</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>474.51 nanos</b></font>
Min Time: 443.0 nanos
Max Time: 38.514 micros
Garbage: no garbage created for the GC
75% = [avg: 470.0 nanos, max: 475.0 nanos]
90% = [avg: 471.0 nanos, max: 481.0 nanos]
99% = [avg: 473.0 nanos, max: 522.0 nanos]
99.9% = [avg: 473.0 nanos, max: 632.0 nanos]
99.99% = [avg: 474.0 nanos, max: 1.671 micros]
9.999% = [avg: 474.0 nanos, max: 3.557 micros]
</pre>
<p>From <code>ByteBuffer</code> to <code>FixMessage</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>481.55 nanos</b></font>
Min Time: 438.0 nanos
Max Time: 8.929 micros
Garbage: no garbage created for the GC
75% = [avg: 475.0 nanos, max: 499.0 nanos]
90% = [avg: 478.0 nanos, max: 501.0 nanos]
99% = [avg: 480.0 nanos, max: 521.0 nanos]
99.9% = [avg: 480.0 nanos, max: 644.0 nanos]
99.99% = [avg: 481.0 nanos, max: 1.71 micros]
99.999% = [avg: 481.0 nanos, max: 3.345 micros]
</pre>
<h2 class="coral">FIX message with repeating groups</h2>
<p>For our test we randomize 2.5 million FIX messages like the one below:</p>
<pre>
BeginString(8)=FIX.4.2 BodyLength(9)=157 MsgType(35)=QuoteStatusRequest("a") SenderCompID(49)=TTTTTTT6 TargetCompID(56)=44611
Unknown(5555)=11855.33 MsgSeqNum(34)=58 SendingTime(52)=20140709-15:01:26.209 
<strong>[NoRelatedSym(146)=2 | Symbol(55)=AAPL FutSettDate(64)=65912 SecurityDesc(107)=blah1 | Symbol(55)=IBM FutSettDate(64)=56132 SecurityDesc(107)=blah2]</strong> 
Unknown(7777)=Y TargetSubID(57)=ARCA HeartBtInt(108)=60 EncryptMethod(98)=0 CheckSum(10)=114
</pre>
<p>From <code>FixMessage</code> to <code>ByteBuffer</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>879.73 nanos</b></font>
Min Time: 818.0 nanos
Max Time: 15.48 micros
Garbage: no garbage created for the GC
75% = [avg: 869.0 nanos, max: 888.0 nanos]
90% = [avg: 873.0 nanos, max: 903.0 nanos]
99% = [avg: 877.0 nanos, max: 956.0 nanos]
99.9% = [avg: 878.0 nanos, max: 1.26 micros]
99.99% = [avg: 879.0 nanos, max: 2.733 micros]
99.999% = [avg: 879.0 nanos, max: 4.483 micros]
</pre>
<p>From <code>ByteBuffer</code> to <code>FixMessage</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>1.132 micros</b></font>
Min Time: 1.044 micros
Max Time: 13.381 micros
Garbage: no garbage created for the GC
75% = [avg: 1.118 micros, max: 1.146 micros]
90% = [avg: 1.124 micros, max: 1.165 micros]
99% = [avg: 1.129 micros, max: 1.224 micros]
99.9% = [avg: 1.13 micros, max: 1.646 micros]
99.99% = [avg: 1.131 micros, max: 3.947 micros]
99.999% = [avg: 1.132 micros, max: 5.948 micros]
</pre>
<p><strong>Note:</strong> This shows a known weakness of the FIX protocol: parsing repeating groups is expensive.</p>
<h2 class="coral">FIX message with repeating groups inside repeating groups</h2>
<p>For our test we randomize 2.5 million FIX messages like the one below:</p>
<pre>
BeginString(8)=FIX.4.2 BodyLength(9)=272 MsgType(35)=QuoteStatusRequest("a") SenderCompID(49)=TTTTTTT6 TargetCompID(56)=63016 
Unknown(5555)=4592.00 MsgSeqNum(34)=64 SendingTime(52)=20140709-19:38:42.653 
[NoRelatedSym(146)=2 | 
Symbol(55)=AAPL FutSettDate(64)=61245 SecurityDesc(107)=blah1 
<strong>[NoTestSubgroup(10000)=2 | TestTag1(10001)=61245 TestTag2(10002)=21785 | TestTag1(10001)=foo421 TestTag2(10002)=foo422]</strong> | 
Symbol(55)=IBM FutSettDate(64)=21785 SecurityDesc(107)=blah2 
<strong>[NoTestSubgroup(10000)=2 | TestTag1(10001)=15732 TestTag2(10002)=39740 | TestTag1(10001)=foo421 TestTag2(10002)=foo422]</strong>] 
Unknown(7777)=Y TargetSubID(57)=ARCA HeartBtInt(108)=60 EncryptMethod(98)=0 CheckSum(10)=114
</pre>
<p>From <code>FixMessage</code> to <code>ByteBuffer</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>1.792 micros</b></font>
Min Time: 1.656 micros
Max Time: 14.2 micros
Garbage: no garbage created for the GC
75% = [avg: 1.771 micros, max: 1.815 micros]
90% = [avg: 1.78 micros, max: 1.844 micros]
99% = [avg: 1.788 micros, max: 1.92 micros]
99.9% = [avg: 1.79 micros, max: 2.106 micros]
99.99% = [avg: 1.791 micros, max: 5.73 micros]
99.999% = [avg: 1.791 micros, max: 6.249 micros]
</pre>
<p>From <code>ByteBuffer</code> to <code>FixMessage</code>:</p>
<pre>
Messages: 2,500,000
Avg Time: <font color="blue"><b>1.932 micros</b></font>
Min Time: 1.832 micros
Max Time: 16.903 micros
Garbage: no garbage created for the GC
75% = [avg: 1.913 micros, max: 1.95 micros]
90% = [avg: 1.921 micros, max: 1.976 micros]
99% = [avg: 1.928 micros, max: 2.084 micros]
99.9% = [avg: 1.93 micros, max: 2.319 micros]
99.99% = [avg: 1.931 micros, max: 5.932 micros]
99.999% = [avg: 1.932 micros, max: 6.324 micros]
</pre>
<p><strong>Note:</strong> This shows a known weakness of the FIX protocol: parsing repeating groups is expensive.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/coralfix-performance-numbers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ultra low-latency with CoralFIX and CoralReactor</title>
		<link>https://www.coralblocks.com/index.php/ultra-low-latency-with-coralfix-and-coralreactor/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ultra-low-latency-with-coralfix-and-coralreactor</link>
		<comments>https://www.coralblocks.com/index.php/ultra-low-latency-with-coralfix-and-coralreactor/#comments</comments>
		<pubDate>Wed, 22 Oct 2014 10:26:00 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[fast]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[low-latency]]></category>
		<category><![CDATA[throughput]]></category>

		<guid isPermaLink="false">http://www.coralblocks.com/index.php/?p=709</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><strong>Please note</strong> that this benchmark sends real <i>ExecutionReport</i> FIX messages. It simulates the <strong>very real trading scenario</strong> where your order is filled and your strategy needs to react as soon as possible. Furthermore, our clients run our benchmarks <strong>in their own environment</strong>. We provide all the source code of our benchmarks so clients can modify and adapt them in order to reach their <strong>own conclusions</strong>. They also run their <strong>own and very specific benchmarks and tests</strong> with similar results. This benchmark not only measures the FIX parser performance, but also and most importantly the <strong>network I/O performance</strong>. If you want to check our tick-to-trade latencies you can <a href="http://www.coralblocks.com/index.php/2015/08/tick-to-trade-latency-numbers-using-coralfix-and-coralreactor/" target="_blank">click here</a>.</p>
<p>To test the performance of CoralFIX + CoralReactor we have developed a simple test with a fix server and a fix client. The client connects to the server, the standard FIX handshake through LOGON messages happens and the server proceeds to send 2 million FIX messages to the client. So we are measuring <strong>one-way latency</strong> from FIX server to FIX client over loopback. For a throughput benchmark instead you can check <a href="/index.php/2014/10/blazing-fast-throughput-with-coralfix-coralreactor/" target="_blank">this article</a>. Note that the server only sends the next message to the client when it gets a message back from it so we can correctly measure the time it takes for each message <em>in isolation</em> to travel from the server to the client. We then compute the average latency, which includes the full CoralFIX parsing time (i.e. encoding and decoding of the FIX message) plus the full CoralReactor TCP network I/O time. Below we present the latency results and the source code. <span id="more-709"></span></p>
<p><b>NOTE:</b> If you want to check the benchmark of just the CoralFIX parser without any network I/O code (i.e. without CoralReactor) you can check <a href="/index.php/2014/07/coralfix-performance-numbers/" target="_blank">this article</a>.</p>
<h3 class="coral">The Results</h3>
<pre>
Messages: 1,800,000 (one-way)
Avg Time: <font color="blue"><b>4.774 micros</b></font>
Min Time: 4.535 micros
Max Time: 69.516 micros
Garbage created: <font color="red"><b>ZERO</b></font>
75% = [avg: 4.712 micros, max: 4.774 micros]
90% = [avg: 4.726 micros, max: 4.825 micros]
99% = [avg: 4.761 micros, max: 5.46 micros]
99.9% = [avg: 4.769 micros, max: 7.07 micros]
99.99% = [avg: 4.772 micros, max: 9.481 micros]
99.999% = [avg: 4.773 micros, max: 24.017 micros]
</pre>
<p>The machine used for the benchmarks was an Intel i7 (4 x 3.5GHz) Ubuntu box overclocked to 4.5GHz.</p>
<h3 class="coral">The Source Code</h3>
<p>The server:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.bench.latency;

import com.coralblocks.coralfix.FixConstants;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixTags;
import com.coralblocks.coralfix.server.FixApplicationServer;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.server.Server;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class FixLatencyOneWayServer extends FixApplicationServer {
	
	// java -Xms6g -Xmx8g -server -verbose:gc -Xbootclasspath/p:../CoralReactor-boot-jdk7/target/coralreactor-boot-jdk7.jar -cp target/coralfix-all.jar:lib/jna-3.5.1.jar -DnioReactorProcToBind=2 com.coralblocks.coralfix.bench.latency.FixLatencyOneWayServer
	
	private long id;
	
	public FixLatencyOneWayServer(NioReactor nio, int port, Configuration config) {
	    super(nio, port, config);
    }

	@Override
    protected void handleConnectionOpened(Client client) {
		this.id = 1;
		send(client);
	}
	
	@Override
    protected void handleFixApplicationMessage(Client client, FixMessage fixMsg, boolean possDupe) {
	    send(client);
    }

	private final void send(Client client) {
		
		FixMessage fixOutMsg = getOutFixMessage(client, FixConstants.MsgTypes.ExecutionReport);
		fixOutMsg.addTimestamp(FixTags.TransactTime, nio.currentTimeMillis());
		fixOutMsg.add(FixTags.Account, &quot;01234567&quot;);
		fixOutMsg.add(FixTags.OrderQty, 50);
		fixOutMsg.add(FixTags.Price, 400.5);
		fixOutMsg.add(FixTags.ClOrdID, id++);
		fixOutMsg.add(FixTags.HandlInst, '1');
		fixOutMsg.add(FixTags.OrdType, '2');
		fixOutMsg.add(FixTags.Side, '1');
		fixOutMsg.add(FixTags.Symbol, &quot;OC&quot;);
		fixOutMsg.add(FixTags.Text, &quot;NIGEL&quot;);
		fixOutMsg.add(FixTags.TimeInForce, '0');
		fixOutMsg.add(FixTags.SecurityDesc, &quot;AOZ3 C02000&quot;);
		fixOutMsg.add(FixTags.SecurityType, 'O');
		// Note: contrary to popular belief, System.nanoTime() is consistency across CPU cores
		// and can be used to measure one-way latency without any problems. We have also used
		// native rdtsc timers with very similar latency results.
		fixOutMsg.add(7676, System.nanoTime());
	
		send(client, fixOutMsg);
	}
	
	public static void main(String[] args) {
		NioReactor nio = NioReactor.create();
		MapConfiguration config = new MapConfiguration();
		config.add(&quot;fixVersion&quot;, 44);
		Server server = new FixLatencyOneWayServer(nio, 55555, config);
		server.open();
		nio.start();
	}
}

</pre>
<p><br/><br />
The client:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.bench.latency;

import com.coralblocks.coralbits.bench.Benchmarker;
import com.coralblocks.coralbits.util.SystemUtils;
import com.coralblocks.coralfix.FixConstants;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.client.FixApplicationClient;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class FixLatencyOneWayClient extends FixApplicationClient {

	// java -Xms6g -Xmx8g -server -verbose:gc -Xbootclasspath/p:../CoralReactor-boot-jdk7/target/coralreactor-boot-jdk7.jar -cp target/coralfix-all.jar:lib/jna-3.5.1.jar -DdetailedBenchmarker=true -DnioReactorProcToBind=3 com.coralblocks.coralfix.bench.latency.FixLatencyOneWayClient
	
	private int count = 0;
	private final int messages;
	private final Benchmarker bench;
	
	public FixLatencyOneWayClient(NioReactor nio, String localhost, int port, Configuration config) {
		super(nio, localhost, port, config);
		int warmup = SystemUtils.getInt(&quot;warmup&quot;, 200000);
		this.messages = SystemUtils.getInt(&quot;messages&quot;, 2000000);
		this.bench = Benchmarker.create(warmup);
    }
	
	@Override
	protected void handleFixApplicationMessage(FixMessage fixMsg, boolean possDupe) {
		
		long ts = fixMsg.getLong(7676);
		// Note: contrary to popular belief, System.nanoTime() is consistency across CPU cores
		// and can be used to measure one-way latency without any problems. We have also used
		// native rdtsc timers with very similar latency results.
		bench.measure(System.nanoTime() - ts);
		
		if (++count == messages) {
			// done...
			bench.printResults();
			close();
		} else {
			// send a dummy message back, just to trigger a new one...
			FixMessage fixOutMessage = getOutFixMessage(FixConstants.MsgTypes.ExecutionReport);
			fixOutMessage.add(333, 3);
			send(fixOutMessage);
		}
	}
	
	public static void main(String[] args) {
		NioReactor nio = NioReactor.create();
		MapConfiguration config = new MapConfiguration();
		config.add(&quot;fixVersion&quot;, &quot;44&quot;);
		config.add(&quot;senderComp&quot;, &quot;testClient&quot;);
		Client client = new FixLatencyOneWayClient(nio, &quot;localhost&quot;, 55555, config);
		client.open();
		nio.start();
	}
}

</pre>
<h3 class="coral">Conclusion</h3>
<p>CoralFIX + CoralReactor can easily deliver one-way FIX message latencies below 5 microseconds.</p>
<p><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/ultra-low-latency-with-coralfix-and-coralreactor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tick-to-Trade Latency Numbers using CoralFIX and CoralReactor</title>
		<link>https://www.coralblocks.com/index.php/tick-to-trade-latency-numbers-using-coralfix-and-coralreactor/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tick-to-trade-latency-numbers-using-coralfix-and-coralreactor</link>
		<comments>https://www.coralblocks.com/index.php/tick-to-trade-latency-numbers-using-coralfix-and-coralreactor/#comments</comments>
		<pubDate>Mon, 31 Aug 2015 03:59:39 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[CoralReactor]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[strategy]]></category>
		<category><![CDATA[tick]]></category>
		<category><![CDATA[tick-to-trade]]></category>
		<category><![CDATA[trade]]></category>
		<category><![CDATA[trading]]></category>

		<guid isPermaLink="false">http://www.coralblocks.com/index.php/?p=1587</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In this article we use wireshark and tcpdump to analyze the latency numbers of a test trading strategy that receives a market data tick through UDP using CoralReactor and places a trade order through FIX using CoralFIX. <span id="more-1587"></span></p>
<h3 class="coral">Test Details</h3>
<p>A pseudo market data generator sends UDP packets containing market data updates (i.e. ticks). Our test trading strategy receives these packets, parses them and places a trade order using the FIX protocol on a pseudo exchange that immediately executes the order. To warm up the test strategy, we initially send 1 million market data updates. Then we proceed to send one packet every 5 seconds. To measure the latency, we use tcpdump to record the UDP packet coming in and the FIX order going out. With the packet capture file from tcpdump we then use wireshark to calculate the difference in the timestamps of the packet arriving and the FIX order leaving.</p>
<h3 class="coral">Results</h3>
<p>As you can see from the wireshark screenshot below, the <font color="#008F63"><b>tick-to-trade latencies are around 8-9 microseconds</b></font>.</p>
<p><a href="/wp-content/uploads/2015/08/tick-to-trade2.png"><img src="/wp-content/uploads/2015/08/tick-to-trade2.png" alt="tick-to-trade" width="1268" height="1014" class="alignnone size-full wp-image-1589" /></a></p>
<h3 class="coral">Source Code</h3>
<p>Note that the source code down below produces zero garbage for the GC.</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.bench.trade;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;

import com.coralblocks.coralbits.util.PriceUtils;
import com.coralblocks.coralfix.FixConstants;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixTags;
import com.coralblocks.coralfix.client.FixApplicationClient;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.client.ClientAdapter;
import com.coralblocks.coralreactor.client.receiver.ReceiverUdpClient;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class TickToTrade extends ClientAdapter {
	
	private final NioReactor nio;
	private final FixApplicationClient fixGateway;
	private final byte[] symbol = new byte[8];
	private long orderIDs = 1;
	
	public TickToTrade(NioReactor nio, final Client marketDataFeed, FixApplicationClient fixGateway) {
		this.nio = nio;
		this.fixGateway = fixGateway;
		
		fixGateway.addListener(new ClientAdapter() {

			@Override
			public void onConnectionOpened(Client client) {
				// gateway is connected and ready to trade...
				marketDataFeed.open(); // open the feed...
				marketDataFeed.addListener(TickToTrade.this); // so that onMessage below is called
			}
		});
	}
	
	public void start() {
		fixGateway.open();
	}

	@Override
    public void onMessage(Client client, InetSocketAddress fromAddress, ByteBuffer msg) {
		
		// parse the market data quote
		long quoteId = msg.getLong();
		boolean isBid = msg.get() == 'B';
		msg.get(symbol);
		long size = msg.getInt();
		long price = msg.getLong();
		
		// hit the market data quote
		FixMessage outFixMsg = fixGateway.getOutFixMessage(FixConstants.MsgTypes.NewOrderSingle);
		outFixMsg.add(FixTags.ClOrdID, orderIDs++);
		outFixMsg.add(FixTags.OrigClOrdID, quoteId);
		outFixMsg.addTrimmed(FixTags.Symbol, symbol);
		outFixMsg.add(FixTags.Side, isBid ? &quot;2&quot; : &quot;1&quot;); // sell to the bid or buy from the offer
		outFixMsg.addTimestamp(FixTags.TransactTime, nio.currentTimeMillis());
		outFixMsg.add(FixTags.OrderQty, size);
		outFixMsg.add(FixTags.OrdType, &quot;2&quot;); // limit order
		outFixMsg.add(FixTags.Price, PriceUtils.toDouble(price));
		outFixMsg.add(FixTags.TimeInForce, &quot;3&quot;); // IoC
		fixGateway.send(outFixMsg);
    }

	public static void main(String[] args) {
		
		NioReactor nio = NioReactor.create();
		
		Client marketDataFeed = new ReceiverUdpClient(nio, 44444);
		
		MapConfiguration config = new MapConfiguration();
		config.add(&quot;fixVersion&quot;, 44);
		config.add(&quot;senderComp&quot;, &quot;testClient&quot;);
		config.add(&quot;forceSeqReset&quot;, true);
		
		FixApplicationClient fixGateway = new FixApplicationClient(nio, args.length &gt; 0 ? args[0] : &quot;localhost&quot;, 55555, config);
		
		TickToTrade tickToTrade = new TickToTrade(nio, marketDataFeed, fixGateway);
		tickToTrade.start();
		
		nio.start();
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/tick-to-trade-latency-numbers-using-coralfix-and-coralreactor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blazing Fast Throughput with CoralFIX + CoralReactor</title>
		<link>https://www.coralblocks.com/index.php/blazing-fast-throughput-with-coralfix-coralreactor/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=blazing-fast-throughput-with-coralfix-coralreactor</link>
		<comments>https://www.coralblocks.com/index.php/blazing-fast-throughput-with-coralfix-coralreactor/#comments</comments>
		<pubDate>Wed, 22 Oct 2014 10:06:25 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[fast]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[throughput]]></category>

		<guid isPermaLink="false">http://www.coralblocks.com/index.php/?p=702</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>To test the performance of CoralFIX + CoralReactor we have developed a simple test with a fix server and a fix client. The client connects to the server, the standard FIX handshake through LOGON messages takes place and the client proceeds to send (i.e. push) 5 million FIX messages to the server <i>as fast as it can</i>. Then the server receives and processes all the messages calculating the throughput. So we are are measuring the <strong>one-way throughput</strong> over loopback. For a latency benchmark instead you can check <a href="/index.php/2014/10/ultra-low-latency-with-coralfix-and-coralreactor/" target="_blank">this article</a>. Below we present the throughput results and the source code. <span id="more-702"></span></p>
<p><b>NOTE:</b> If you want to check the benchmark of just the CoralFIX parser without any network I/O code (i.e. without CoralReactor) you can check <a href="/index.php/2014/07/coralfix-performance-numbers/" target="_blank">this article</a>.</p>
<h3 class="coral">The Results</h3>
<pre>
Messages: 5,000,000 (one-way)
Throughput: <font color="blue"><b>279,314 msgs/sec</b></font>
</pre>
<p>The machine used for the benchmarks was an Intel i7 (4 x 3.5GHz) Ubuntu box overclocked to 4.5GHz.</p>
<h3 class="coral">The Source Code</h3>
<p>The server:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.bench.throughput;

import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.server.FixApplicationServer;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.server.Server;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class FixThroughputServer extends FixApplicationServer {
	
	// java -Xms6g -Xmx8g -server -verbose:gc -Xbootclasspath/p:../CoralReactor-boot-jdk7/target/coralreactor-boot-jdk7.jar -cp target/coralfix-all.jar:lib/jna-3.5.1.jar -DpersistSequences=false -DnioReactorProcToBind=2 com.coralblocks.coralfix.bench.throughput.FixThroughputServer
		
	private long start;
	private long msgCount;

	public FixThroughputServer(NioReactor nio, int port, Configuration config) {
	    super(nio, port, config);
    }

	@Override
    protected void handleFixApplicationMessage(Client client, FixMessage fixMsg, boolean possDupe) {
		msgCount++;
    }
	
	@Override
	protected void handleConnectionEstablished(Client client) {
		msgCount = 0;
	}
	
	@Override
	protected void handleConnectionOpened(Client client) {
		start = System.nanoTime();
	}
	
	@Override
	protected void handleConnectionTerminated(Client client) {
		if (msgCount &gt; 0) {
    		long totalTime = System.nanoTime() - start;
    		long latency = totalTime / msgCount;
    		long ops = msgCount * 1000000000L / totalTime;
    		System.out.println(&quot;Done receiving messages! messagesReceived=&quot; + msgCount 
		+ &quot; avgLatencyPerMsg=&quot; + latency + &quot; nanos throughput=&quot; + ops + &quot; msgs/sec&quot;);
		}
	}
	
	public static void main(String[] args) {
		NioReactor nio = NioReactor.create();
		MapConfiguration config = new MapConfiguration();
		config.add(&quot;fixVersion&quot;, 44);
		Server server = new FixThroughputServer(nio, 45451, config);
		server.open();
		nio.start();
	}
}


</pre>
<p><br/><br />
The client:</p>
<pre class="brush: java; title: ; notranslate">
package com.coralblocks.coralfix.bench.throughput;

import java.nio.channels.SelectionKey;
import java.nio.channels.WritableByteChannel;

import com.coralblocks.coralbits.util.SystemUtils;
import com.coralblocks.coralfix.FixConstants;
import com.coralblocks.coralfix.FixMessage;
import com.coralblocks.coralfix.FixTags;
import com.coralblocks.coralfix.client.FixApplicationClient;
import com.coralblocks.coralreactor.client.Client;
import com.coralblocks.coralreactor.nio.NioReactor;
import com.coralblocks.coralreactor.util.Configuration;
import com.coralblocks.coralreactor.util.MapConfiguration;

public class FixThroughputClient extends FixApplicationClient {
	
	// java -Xms6g -Xmx8g -server -verbose:gc -Xbootclasspath/p:../CoralReactor-boot-jdk7/target/coralreactor-boot-jdk7.jar -cp target/coralfix-all.jar:lib/jna-3.5.1.jar -DpersistSequences=false -DnioReactorProcToBind=3 com.coralblocks.coralfix.bench.throughput.FixThroughputClient
	
	private final int messagesToSend;
	private final int batchSize;
	
	private int msgCount;
	private long start;

	public FixThroughputClient(NioReactor nio, String host, int port, Configuration config) {
	    super(nio, host, port, config);
	    this.messagesToSend = config.getInt(&quot;messagesToSend&quot;);
	    this.batchSize = config.getInt(&quot;batchSize&quot;);
    }
	
	@Override
	protected void handleConnectionEstablished() {
		msgCount = 0;
	}

	@Override
	protected void handleConnectionOpened() {
		start = System.nanoTime();
		addInterestOp(SelectionKey.OP_WRITE);
	}
	
	@Override
	public void onWrite(WritableByteChannel channel) {
		
		for(int i = 0; i &lt; batchSize; i++) {
		
    		if (msgCount &lt; messagesToSend) {
    			
    			FixMessage fixOutMsg = getOutFixMessage(FixConstants.MsgTypes.ExecutionReport);
    			fixOutMsg.addTimestamp(FixTags.TransactTime, nio.currentTimeMillis());
    			fixOutMsg.add(FixTags.Account, &quot;01234567&quot;);
    			fixOutMsg.add(FixTags.OrderQty, 50);
    			fixOutMsg.add(FixTags.Price, 400.5);
    			fixOutMsg.add(FixTags.ClOrdID, &quot;4&quot;);
    			fixOutMsg.add(FixTags.HandlInst, '1');
    			fixOutMsg.add(FixTags.OrdType, '2');
    			fixOutMsg.add(FixTags.Side, '1');
    			fixOutMsg.add(FixTags.Symbol, &quot;OC&quot;);
    			fixOutMsg.add(FixTags.Text, &quot;NIGEL&quot;);
    			fixOutMsg.add(FixTags.TimeInForce, '0');
    			fixOutMsg.add(FixTags.SecurityDesc, &quot;AOZ3 C02000&quot;);
    			fixOutMsg.add(FixTags.SecurityType, 'O');
    		
    			if (!send(fixOutMsg)) {
    				// underlying kernel write socket buffer is full
    				// sending too fast and/or the other side is lagging
    				return; // abort and wait for OP_WRITE
    			}
    			msgCount++;
    		} else {
    			if (hasPendingDataToFlush()) {
    				flush();
    			} else {
    				printResults();
    				disconnect();
    				return;
    			}
    		}
		}
	}
	
	private void printResults() {
		long totalTime = System.nanoTime() - start;
		long latency = totalTime / msgCount;
		long ops = msgCount * 1000000000L / totalTime;
		System.out.println(&quot;Done sending messages! messagesSent=&quot; + msgCount 
		+ &quot; avgLatencyPerMsg=&quot; + latency + &quot; nanos throughput=&quot; + ops + &quot; msgs/sec&quot;);
	}
	
	public static void main(String[] args) {
		
		NioReactor nio = NioReactor.create();
		
		int messagesToSend = SystemUtils.getInt(&quot;messagesToSend&quot;, 5000000);
		int batchSize = SystemUtils.getInt(&quot;batchSize&quot;, 128);
		
		MapConfiguration config = new MapConfiguration();
		config.add(&quot;fixVersion&quot;, 44);
		config.add(&quot;senderComp&quot;, &quot;testSenderCompID&quot;);
		config.add(&quot;messagesToSend&quot;, messagesToSend);
		config.add(&quot;batchSize&quot;, batchSize);
		
		Client client = new FixThroughputClient(nio, &quot;localhost&quot;, 45451, config);
		client.open();
		nio.start();
	}
}


</pre>
<h3 class="coral">Conclusion</h3>
<p>CoralFIX + CoralReactor can easily process more than 250,000 FIX messages per second.</p>
<p><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/blazing-fast-throughput-with-coralfix-coralreactor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working with FIX Session Timers</title>
		<link>https://www.coralblocks.com/index.php/working-with-fix-session-timers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=working-with-fix-session-timers</link>
		<comments>https://www.coralblocks.com/index.php/working-with-fix-session-timers/#comments</comments>
		<pubDate>Wed, 10 Dec 2014 17:49:17 +0000</pubDate>
		<dc:creator><![CDATA[cb]]></dc:creator>
				<category><![CDATA[CoralFIX]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[fix session]]></category>
		<category><![CDATA[fix session timer]]></category>
		<category><![CDATA[reset sequences]]></category>
		<category><![CDATA[resetter]]></category>
		<category><![CDATA[scheduler]]></category>

		<guid isPermaLink="false">http://www.coralblocks.com/index.php/?p=725</guid>
		<description><![CDATA[ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In this article we show examples of how you can configure one or more <i>FIX timers</i> to perform any kind of action on your FIX session, such as resetting the sequences and connect/disconnect. <span id="more-725"></span></p>
<h3 class="coral">Daily and Weekly Timers</h3>
<p>CoralFIX comes with two ready-to-use timers that you can use in your FIX clients. See the examples below:</p>
<pre class="brush: java; title: ; notranslate">
// a timer that will trigger everyday 15:30:00 America/New_York
FixSessionTimer timer = new DailyFixSessionTimer(TimeZone.getTimeZone(&quot;America/New_York&quot;), 15, 30, 0);
System.out.println(timer); // =&gt; DailyFixSessionTimer-America/New_York-15:30:0

// a timer what will trigger every Sunday at 14:30:00 America/New_York
FixSessionTimer timer = new WeeklyFixSessionTimer(TimeZone.getTimeZone(&quot;America/New_York&quot;), Calendar.SUNDAY, 14, 30, 0);
System.out.println(timer); // =&gt; WeeklyFixSessionTimer-America/New_York-SUNDAY-14:30:0
</pre>
<p><br/></p>
<h3 class="coral">Adding Timers to a FIX Client</h3>
<p>There are two actions for a timer:</p>
<ul>
<li><code>Stop</code>: Disconnects and closes the client</li>
<li><code>Start</code>: Resets both inbound and outbound sequences and reconnects the client</li>
</ul>
<p><b>NOTE:</b> You can also use the config options &#8220;resetSequencesOnStartTimerEvent&#8221; and &#8220;reconnectOnStartTimerEvent&#8221; to fine tune the start action. Both of these options default to true.</p>
<p>To add one or more timers you pass them as config options. For the config option key you can use:</p>
<pre>
"startSessionTimer" => no label for this start timer
"startSessionTimer-myStartTimer" => "myStartTimer" is the label for this start timer
"stopSessionTimer" => no label for this stop timer
"stopSessionTimer-myStopTimer" => "myStopTimer" is the label for this stop timer
</pre>
<p>The formats for the weekly and daily timers are:</p>
<pre>
DailyTimer => D-TZ-HH:MM:SS => "D-America/New_York-13:00:00"
WeeklyTimer => W-DAY-TZ-HH:MM:SS => "W-SATURDAY-America/New_York-15:00:00"
</pre>
<p>See below some code examples:</p>
<pre class="brush: java; title: ; notranslate">
// add a start session timer daily at 14:30:00 America/New_York
config.add(&quot;startSessionTimer&quot;, &quot;D-America/New_York-14:30:00&quot;);

// add a stop session timer weekly on Sunday at 16:00:00 America/New_York
config.add(&quot;stopSessionTimer&quot;, &quot;W-SUNDAY-America/New_York-16:00:00&quot;);

// add a second start session timer with label &quot;midweekStart&quot; weekly on Wednesday at 14:00:00 America/New_York
config.add(&quot;startSessionTimer-midweekStart&quot;, &quot;W-WEDNESDAY-America/New_York-14:00:00&quot;);

// add a second stop session timer with lable &quot;midweekStop&quot; weekly on Wednesday at 13:00:00 America/New_York
config.add(&quot;stopSessionTimer-midweekStop&quot;, &quot;W-WEDNESDAY-America/New_York-13:00:00&quot;);
</pre>
<p><br/></p>
<h3 class="coral">Additional Features</h3>
<p>Timers are smart! That means they will inform the FIX client if it is in a <i>down period</i> and prevent a connection to the server until the next start timer triggers. The <code>FixApplicationClient</code> will also detect a missed start timer (i.e. start timer that was supposed to trigger but the client wasn&#8217;t running) and reset the sequences appropriately on the next time the client is started.<br />
<br/></p>
<h3 class="coral">Handling Multiple Timers</h3>
<p>There can be a situation where each timer needs to perform a different action inside the <code>handleTriggered</code> method. For that you can use the <code>FixSessionTimer</code> argument passed in the method to find out which timer has triggered. In order to do that you can compare the timers by reference or by label as the example below demonstrates:</p>
<pre class="brush: java; title: ; notranslate">
public class MyClient extends FixApplicationClient {

   // (...)

   @Override
   protected void handleTriggered(FixSessionTimer timer, boolean isCloseTrigger, boolean isMissedStartTrigger) {

      if (timer == timer1) {
         
            // your specific action here

      } else if (timer == timer2) {
         super.handleTriggered(timer); // reset both sequences
      }

      // OR

      if (timer.getLabel().equals(&quot;myTimerLabel1&quot;)) {

            // your specific cation here

      } else if (timer.getLabel().equals(&quot;myTimerLabel2&quot;)) {
         super.handleTriggered(timer); // reset both sequences
      }
   }
}
</pre>
<p><br/></p>
<h3 class="coral">Implementing Timers</h3>
<p>The <code>DailyFixSessionTimer</code> and the <code>WeeklyFixSessionTimer</code> should be enough for most situations. However, if you want to implement your own timer with a more complicated schedule, you can code your own implementation of the <code>FixSessionTimer</code> interface. </p>
<p><br/></p>
<h3 class="coral">Conclusion</h3>
<p>CoralFIX allows you to schedule timers to perform any kind of action you need on your FIX session, such as resetting sequences and connect/disconnect.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.coralblocks.com/index.php/working-with-fix-session-timers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
