FIX client Server Implementation QuickFix

If you are working in trading based company then it’s very important to have knowledge of FIX (Financial Information eXchange) protocol.

What is FIX: It’s electronic communications protocol which was initiated in 1992 for international real time exchange of financial information related to markets and securities transactions. As you know now a days billions and trillions of dollars traded annually on the trading exchanges. Financial institutions entities are investing too much of money optimizing electronic trading application and employing direct market access (DMA) in hope of increase to submit orders to speedily to the financial markets. It’s very important to manages delivery of trading orders and keeping low latency increasingly requires very strong understanding of FIX protocol.

I understand, you wanted to see actual implementation of it without reading more details about it but if you are still very curious to know more about it just google it you will see many details of FIX protocol. Finding details of FIX protocol through Google is very easy but actual implementation is rare where you could see end to end working application. Before writing this application I searched lot never find any good tutorial example which would give basics of FIX protocol and simple to understand. That’s why I am writing this tutorial to get how FIX protocol works. Let’s jump on it:

Basically to develop end to end and perform test you need two application:

  • FIX Acceptor (Called as FIX Server) – Server process the FIX message its nothing but exchange you sent your order for processing
  • FIX Initiator (Called as FIX Client) – Client are broker who send order to the exachange in FIX format.

Note: To develop this application we will use QuickFIX/J which is 100% java open source FIX engine and very famous in the industry. All jars available through maven repository except below jars:

  • Create maven project FIXProtocolAcceptor below is details project structure:

FIX client Server Implementation QuickFix

  • pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javahonk</groupId>
	<artifactId>FIXProtocolAcceptor</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>FIXProtocolServer Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>backport-util-concurrent</groupId>
			<artifactId>backport-util-concurrent</artifactId>
			<version>2.1</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
		<dependency>
			<groupId>mina-core-1.1.0-sources</groupId>
			<artifactId>mina-core-1.1.0-sources</artifactId>
			<version>1.1.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/lib/mina-core-1.1.0-sources.jar</systemPath>
		</dependency>
		<dependency>
			<groupId>org.apache.mina</groupId>
			<artifactId>mina-core</artifactId>
			<version>2.0.9</version>
		</dependency>
		<dependency>
			<groupId>quickfixj-all-1.6.0</groupId>
			<artifactId>quickfixj-all-1.6.0</artifactId>
			<version>1.6.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/lib/quickfixj-all-1.6.0.jar</systemPath>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-jdk14</artifactId>
			<version>1.7.2</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>FIXProtocolAcceptor</finalName>
	</build>
</project>
  • acceptor.cfg:
[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=5001
SocketConnectHost=localhost
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
FileLogPath=log
FileStorePath=.\fixfiles
SocketKeepAlive=Y
SocketTcpNoDelay=Y

[SESSION]
BeginString=FIX.4.2
SenderCompID=FixAcceptor
TargetCompID=FixClient8019
DataDictionary=.\config\FIX42.xml
  • FixAcceptor.java:
package com.javahonk;

import java.io.File;

import quickfix.Application;
import quickfix.DefaultMessageFactory;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.FileStoreFactory;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.MessageCracker;
import quickfix.RejectLogon;
import quickfix.ScreenLogFactory;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.SessionSettings;
import quickfix.SocketAcceptor;
import quickfix.UnsupportedMessageType;
import quickfix.field.AvgPx;
import quickfix.field.ClOrdID;
import quickfix.field.CumQty;
import quickfix.field.ExecID;
import quickfix.field.ExecTransType;
import quickfix.field.ExecType;
import quickfix.field.Headline;
import quickfix.field.LeavesQty;
import quickfix.field.OrdStatus;
import quickfix.field.OrdType;
import quickfix.field.OrderID;
import quickfix.field.OrderQty;
import quickfix.field.Price;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.NewOrderSingle;
import quickfix.fix42.News;

public class FixAcceptor extends MessageCracker implements Application {

	public static void main(String[] args) {
		try {
			File file = new File("./config/acceptor.cfg");
			System.out.println(file.getAbsolutePath());
			SessionSettings settings = new SessionSettings("./config/acceptor.cfg");
			FixAcceptor acceptor = new FixAcceptor();
			ScreenLogFactory screenLogFactory = new ScreenLogFactory(settings);
			DefaultMessageFactory messageFactory = new DefaultMessageFactory();
			FileStoreFactory fileStoreFactory = new FileStoreFactory(settings);
			SocketAcceptor socketAcceptor = new SocketAcceptor(acceptor,fileStoreFactory, settings, screenLogFactory,messageFactory);
			socketAcceptor.start();
			System.out.println("press any key to stop the FIX Acceptor Server....s");
			System.in.read();
			socketAcceptor.stop();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void fromAdmin(Message arg0, SessionID arg1) throws FieldNotFound,
			IncorrectDataFormat, IncorrectTagValue, RejectLogon {
		System.out.println("fromAdmin " + arg0);
	}

	@Override
	public void fromApp(Message message, SessionID sessionID)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {
		crack(message, sessionID);

	}

	@Override
	public void onCreate(SessionID arg0) {
	}

	@Override
	public void onLogon(SessionID sessionID) {
		System.out.println("onLogon of "+sessionID);

	}

	@Override
	public void onLogout(SessionID arg0) {

	}

	@Override
	public void toAdmin(Message arg0, SessionID arg1) {
	}

	@Override
	public void toApp(Message arg0, SessionID arg1) throws DoNotSend {
	}

	//@Override
	public void onMessage(NewOrderSingle order, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		// sending some news to the client.
		System.out.println("Inside onmessage method");
		try {
			Session.sendToTarget(new News(new Headline("Hello to OTC Expiration")), sessionID);
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
		Symbol symbol = new Symbol();
		Side side = new Side();
		OrdType ordType = new OrdType();
		OrderQty orderQty = new OrderQty();
		Price price = new Price();
		ClOrdID clOrdID = new ClOrdID();

		order.get(symbol);
		order.get(side);
		order.get(orderQty);
		order.get(price);
		order.get(clOrdID);
		order.get(ordType);


		ExecutionReport executionReport = new ExecutionReport(
				getOrderIDCounter(), getExecutionIDCounter(),
				new ExecTransType(ExecTransType.NEW), new ExecType(
						ExecType.FILL), new OrdStatus(OrdStatus.FILLED),
				symbol, side, new LeavesQty(0),
				new CumQty(orderQty.getValue()), new AvgPx(price.getValue()));
		executionReport.set(clOrdID);
		executionReport.set(orderQty);
		try {
			Session.sendToTarget(executionReport, sessionID);
			System.out.println("NewOrderSingle Execution  Completed...s");
		} catch (SessionNotFound ex) {
			ex.printStackTrace();
			System.out.println("Error during order execution" + ex.getMessage());
		}
	}

	private int orderIDCounter;
	private int executionIDCounter;

	public OrderID getOrderIDCounter() {
		orderIDCounter++;
		return new OrderID(String.valueOf(orderIDCounter));
	}

	public ExecID getExecutionIDCounter() {
		executionIDCounter++;
		return new ExecID(String.valueOf(executionIDCounter));
	}
}

Note: Remaining files you download from the bottom link

  • Now let’s create FIX client for this you will have to create separate project name: FIXProtocolInitiator below is complete project structure:

FIX client Server Implementation QuickFix

  • pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javahonk</groupId>
	<artifactId>FIXProtocolInitiator</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>FIXProtocolInitiator Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-core</artifactId>
			<version>5.5.0</version>
		</dependency>

		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-xmpp</artifactId>
			<version>5.5.1</version>
		</dependency>
		<dependency>
			<groupId>backport-util-concurrent</groupId>
			<artifactId>backport-util-concurrent</artifactId>
			<version>2.1</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
		<dependency>
			<groupId>mina-core-1.1.0-sources</groupId>
			<artifactId>mina-core-1.1.0-sources</artifactId>
			<version>1.1.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/lib/mina-core-1.1.0-sources.jar</systemPath>
		</dependency>
		<dependency>
			<groupId>org.apache.mina</groupId>
			<artifactId>mina-core</artifactId>
			<version>1.1.0</version>
		</dependency>
		<dependency>
			<groupId>quickfixj-all-1.4.0</groupId>
			<artifactId>quickfixj-all-1.4.0</artifactId>
			<version>1.4.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/lib/quickfixj-all-1.4.0.jar</systemPath>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-jdk14</artifactId>
			<version>1.7.2</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>FIXProtocolInitiator</finalName>
	</build>
</project>
  • initiator.cfg:
[DEFAULT]
ConnectionType=initiator
HeartBtInt=60
ReconnectInterval=1
FileStorePath=.\fixfiles\initiator
FileLogPath=.\log
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
SocketReuseAddress=Y
SocketKeepAlive=Y
SocketTcpNoDelay=Y
SocketConnectHost=localhost

[SESSION]
BeginString=FIX.4.2
SenderCompID=FixClient8019
TargetCompID=FixAcceptor
SocketConnectPort=5001
  • FixInitator.java:
package com.javahonk;


import java.util.ArrayList;
import java.util.Date;

import quickfix.ApplicationAdapter;
import quickfix.ConfigError;
import quickfix.DefaultMessageFactory;
import quickfix.FieldNotFound;
import quickfix.FileStoreFactory;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.ScreenLogFactory;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.SessionSettings;
import quickfix.SocketInitiator;
import quickfix.UnsupportedMessageType;
import quickfix.field.ClOrdID;
import quickfix.field.ExecType;
import quickfix.field.HandlInst;
import quickfix.field.OrdType;
import quickfix.field.OrderQty;
import quickfix.field.Price;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.field.TransactTime;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.NewOrderSingle;

public class FixInitator extends ApplicationAdapter {

	private SocketInitiator socketInitiator;
	
	public static void main(String[] args) throws ConfigError {
		
		FixInitator fixIniator = new FixInitator();
		SessionSettings sessionSettings = new SessionSettings("./config/initiator.cfg");
		ApplicationAdapter application = new FixInitator();
		FileStoreFactory fileStoreFactory = new FileStoreFactory(sessionSettings);
		ScreenLogFactory screenLogFactory = new ScreenLogFactory(sessionSettings);
		DefaultMessageFactory defaultMessageFactory = new DefaultMessageFactory();
		fixIniator.socketInitiator = new SocketInitiator(application,fileStoreFactory, sessionSettings, screenLogFactory,defaultMessageFactory);
		fixIniator.socketInitiator.start();

		try {
			Thread.sleep(3000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		ArrayList<SessionID> sessions = fixIniator.socketInitiator.getSessions();
		
		NewOrderSingle order = new NewOrderSingle(new ClOrdID("APPL12456S"),
				new HandlInst(HandlInst.MANUAL_ORDER), new Symbol("APPL"),
				new Side(Side.BUY), new TransactTime(new Date()), new OrdType(OrdType.MARKET));
		
		order.set(new OrderQty(4500));
		order.set(new Price(200.9d));
		SessionID sessionID = sessions.get(0);
		System.out.println("Sending Order to Server");
		try {
			Session.sendToTarget(order, sessionID);
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		System.out.println("Going to stop socketInitiator");
		fixIniator.socketInitiator.stop();
	}

	@Override
	public void onLogon(SessionID sessionId) {
		super.onLogon(sessionId);
		System.out.println("Logon requested by client");
	}

	@Override
	public void fromAdmin(quickfix.Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			RejectLogon {
		super.fromAdmin(message, sessionId);
		System.out.println("Inside fromAdmin");
	}

	@Override
	public void onCreate(SessionID sessionId) {
		super.onCreate(sessionId);
		System.out.println("Inside onCreate");
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		if (null != this.socketInitiator) {
			this.socketInitiator.stop();
		}
	}

	@Override
	public void fromApp(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {

		if (message instanceof ExecutionReport) {
			ExecutionReport executionReport = (ExecutionReport) message;
			try {
				ExecType executionType = (ExecType) executionReport.getExecType();
				System.out.println(executionType);
				System.out.println("Received execution report for the requested order from Exchange \n");
			} catch (FieldNotFound e) {
				e.printStackTrace();
			}
		}
		
	}
}
  • To keep this tutorial short you could copy others file shows in project from download link below. Not its time to run this application. First start FIXProtocolAcceptor which is exchange server in our case and it’s java application so you could run inside eclipse as java application, if everything set up correctly you will see below output on the console:

FIX client Server Implementation QuickFix

  • As you see sever is started and its ready to accept the order now let’s start our client and send some order to the server. To start client right click FixInitator.java class as java application you will see below output as it’s showing order send successfully to the exchange:

FIX client Server Implementation QuickFix

  • Server output:

FIX client Server Implementation QuickFix

  • That’s it.

download Download Project: FIXProtocolAcceptor FIXProtocolInitiator

5 thoughts on “FIX client Server Implementation QuickFix”
  1. I was not able to compile the FixAcceptor until I removed the @Override annotations. This is because the project is configured to use Java 1.5, in which @Override cannot be used on interface methods. So please update the project to use Java 6.

    Still, this example is the fastest way to get started with QuickFixJ. Thanks a lot!

      1. when i import FIXProtocolAcceptor multiple problems have occured
        Could not calculate build plan:Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:2.6

        please help me

  2. Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project FIXProtocolAcceptor: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

    To see the full stack trace of the errors, re-run Maven with the -e switch.
    Re-run Maven using the -X switch to enable full debug logging.

    For more information about the errors and possible solutions, please read the following articles:
    [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

  3. when i import FIXProtocolAcceptor multiple problems have occured
    Could not calculate build plan:Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:2.6

    please help me

Leave a Reply

Your email address will not be published. Required fields are marked *