QuickFixJ

QuickFIX/J Book a FX Trade

Posted on Updated on

In our last tutorial we created a basic initiator and an acceptor. In this post we will enhance our code and we will book a single order.

First we will enhance our executor class which is TestTradeAppExecutor.java. Important thing to note :

  1. Extends MessageCracker – which provides callback methods
  2. Implementation of fromApp cracks the message which invokes onMessage callback
  3. onMessage is overridden and it prepares the execution report (for a successful scenario)

TestTradeAppExecutor.java


package com.mumz.test.fix.executor;

import java.util.HashMap;
import java.util.Map;

import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.MessageCracker;
import quickfix.RejectLogon;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.UnsupportedMessageType;
import quickfix.field.AvgPx;
import quickfix.field.CumQty;
import quickfix.field.ExecID;
import quickfix.field.ExecTransType;
import quickfix.field.ExecType;
import quickfix.field.LeavesQty;
import quickfix.field.OrdStatus;
import quickfix.field.OrdType;
import quickfix.field.OrderID;
import quickfix.field.Price;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.NewOrderSingle;

/**
 * The Class TestTradeAppExecutor.
 * 
 * @author prabhat.jha
 */
public class TestTradeAppExecutor extends MessageCracker implements Application {

	private Map<String, Double> priceMap = null;

	public TestTradeAppExecutor() {
		priceMap = new HashMap<String, Double>();
		priceMap.put("EUR/USD", 1.234);
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#onCreate(quickfix.SessionID)
	 */
	@Override
	public void onCreate(SessionID sessionId) {
		System.out.println("Executor Session Created with SessionID = "
				+ sessionId);
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#onLogon(quickfix.SessionID)
	 */
	@Override
	public void onLogon(SessionID sessionId) {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#onLogout(quickfix.SessionID)
	 */
	@Override
	public void onLogout(SessionID sessionId) {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#toAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toAdmin(Message message, SessionID sessionId) {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#fromAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromAdmin(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			RejectLogon {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#toApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toApp(Message message, SessionID sessionId) throws DoNotSend {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see quickfix.Application#fromApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromApp(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {
		crack(message, sessionId);
	}

	public void onMessage(NewOrderSingle message, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		OrdType orderType = message.getOrdType();
		Symbol currencyPair = message.getSymbol();
		/*
		 * Assuming that we are directly dealing with Market
		 */
		Price price = null;
		if (OrdType.FOREX_MARKET == orderType.getValue()) {
			if(this.priceMap.containsKey(currencyPair.getValue())){
				price = new Price(this.priceMap.get(currencyPair.getValue()));
			} else {
				price = new Price(1.4589);
			}
			
		} 
		//We are hardcoding this to 1, but in real world this may be something like a sequence.
		OrderID orderNumber = new OrderID("1");
		//Id of the report, a unique identifier, once again this will be somthing like a sequence
		ExecID execId = new ExecID("1");
		//In this case this is a new order with no exception hence mark it as NEW
		ExecTransType exectutionTransactioType = new ExecTransType(ExecTransType.NEW);
		//This execution report is for confirming a new Order
		ExecType purposeOfExecutionReport =new ExecType(ExecType.FILL);
		//Represents status of the order, since this order was successful mark it as filled.
		OrdStatus orderStatus = new OrdStatus(OrdStatus.FILLED);
		//Represents the currencyPair
		Symbol symbol = currencyPair;
		//Represents side
		Side side = message.getSide();
		//What is the quantity left for the day, we will take 100 as a hardcoded value, we can also keep a note of this from say limit module.
		LeavesQty leavesQty = new LeavesQty(100);
		//Total quantity of all the trades booked in this applicaition, here it is hardcoded to be 100.
		CumQty cummulativeQuantity = new CumQty(100);
		//Average Price, say make it 1.235
		AvgPx avgPx = new AvgPx(1.235);
		ExecutionReport executionReport = new ExecutionReport(orderNumber,execId, exectutionTransactioType,
				purposeOfExecutionReport, orderStatus, symbol, side, leavesQty, cummulativeQuantity, avgPx);
		executionReport.set(price);
		try {
			Session.sendToTarget(executionReport, sessionID);
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
	}
}

Second we will enhance our TestTradeAppInitiator so that it logs the order id which has been sent from our server. Important things to note:

  1. Extends MessageCracker – which provides callback methods
  2. Implementation of fromApp cracks the message which invokes onMessage callback
  3. onMessage is overridden and it retrieves information from execution report.

TestTradeAppInitiator

package com.mumz.test.fix.initiator;

import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.SessionID;
import quickfix.UnsupportedMessageType;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.MessageCracker;

/***
 * The Class TestTradeAppInitiator.
 * @author prabhat.jha
 */
public class TestTradeAppInitiator extends MessageCracker implements Application {

	/** (non-Javadoc)
	 * @see quickfix.Application#onCreate(quickfix.SessionID)
	 */
	@Override
	public void onCreate(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogon(quickfix.SessionID)
	 */
	@Override
	public void onLogon(SessionID sessionId) {
		System.out.println("On logged on");
	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogout(quickfix.SessionID)
	 */
	@Override
	public void onLogout(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toAdmin(Message message, SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#fromAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromAdmin(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			RejectLogon {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toApp(Message message, SessionID sessionId) throws DoNotSend {

	}

	/*** (non-Javadoc)
	 * @see quickfix.Application#fromApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromApp(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {
		crack(message, sessionId);
	}
	
	@Override
	public void onMessage(ExecutionReport message, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		System.out.println("Received Execution report from server");
		System.out.println("Order Id : " + message.getOrderID().getValue());
		System.out.println("Order Status : " + message.getOrdStatus().getValue());
		System.out.println("Order Price : " + message.getPrice().getValue());
	}
}

Third let’s change our test code to send an order for booking.
TestTradeAppInitiatorApp.java


package com.mumz.test.fix.initiator;

import java.io.IOException;
import java.util.Scanner;

import quickfix.Application;
import quickfix.ConfigError;
import quickfix.DefaultMessageFactory;
import quickfix.FileLogFactory;
import quickfix.FileStoreFactory;
import quickfix.MessageFactory;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.SessionSettings;
import quickfix.SocketInitiator;
import quickfix.field.ClOrdID;
import quickfix.field.HandlInst;
import quickfix.field.OrdType;
import quickfix.field.OrderQty;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.field.TransactTime;
import quickfix.fix42.NewOrderSingle;

/**
 * The Class TestTradeAppInitiatorApp.
 * 
 * @author prabhat.jha
 */
public class TestTradeAppInitiatorApp {
	
	/**
	 * The main method.
	 * 
	 * @param args
	 *            the args
	 */
	public static void main(String[] args) {
		SocketInitiator socketInitiator = null;
		try {
			SessionSettings initiatorSettings = new SessionSettings(
					"C:/Prabhat/test/QuickFixJ/initiator/initiatorSettings.txt");
			Application initiatorApplication = new TestTradeAppInitiator();
			FileStoreFactory fileStoreFactory = new FileStoreFactory(
					initiatorSettings);
			FileLogFactory fileLogFactory = new FileLogFactory(
					initiatorSettings);
			MessageFactory messageFactory = new DefaultMessageFactory();
			socketInitiator = new SocketInitiator(initiatorApplication, fileStoreFactory, initiatorSettings, fileLogFactory, messageFactory);
			socketInitiator.start();
			SessionID sessionId = socketInitiator.getSessions().get(0);
			Session.lookupSession(sessionId).logon();
			while(!Session.lookupSession(sessionId).isLoggedOn()){
				System.out.println("Waiting for login success");
				Thread.sleep(1000);
			}
			System.out.println("Logged In...");
			
			Thread.sleep(5000);
			bookSingleOrder(sessionId);
			
			System.out.println("Type to quit");
			Scanner scanner = new Scanner(System.in);
			scanner.next();
			Session.lookupSession(sessionId).disconnect("Done",false);
			socketInitiator.stop();
		} catch (ConfigError e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void bookSingleOrder(SessionID sessionID){
		//In real world this won't be a hardcoded value rather than a sequence.
		ClOrdID orderId = new ClOrdID("1");
		//to be executed on the exchange
		HandlInst instruction = new HandlInst(HandlInst.AUTOMATED_EXECUTION_ORDER_PRIVATE);
		//Since its FX currency pair name
		Symbol mainCurrency = new Symbol("EUR/USD");
		//Which side buy, sell
		Side side = new Side(Side.BUY);
		//Time of transaction
		TransactTime transactionTime = new TransactTime();
		//Type of our order, here we are assuming this is being executed on the exchange
		OrdType orderType = new OrdType(OrdType.FOREX_MARKET);
		NewOrderSingle newOrderSingle = new NewOrderSingle(orderId,instruction,mainCurrency, side, transactionTime,orderType);
		//Quantity
		newOrderSingle.set(new OrderQty(100));
		try {
			Session.sendToTarget(newOrderSingle, sessionID);
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
	}
}

That’s all. I have added comments in the code for better readability, hope you find it useful.

QuickFIXJ Initiator Acceptor Integration

Posted on Updated on

This post is beginning of a set of tutorial which we will write as part of building a web based application which will use QuickFIX/J for trade booking. By end of this tutorial you should have an initiator and acceptor with valid login working. In previous post we created an initiator. Though in this post we will once again take a look at initiator code but please refer the link for information related to fields present in settings and also to check which all jars are required for building FIX application using QuickFIX/J.

Before we proceed further let’s clear some jargon:

  1. Initiator: Your FIX client
  2. Acceptor: Your FIX server

First we will write an Application which is the basic building block whether you write an initiator or acceptor. Let’s write our very simple initiator TestTradeAppInitiator.java. Currently we will have a default plain implementation and as we proceed building our application we will add more functionality.

TestTradeAppInitiator.java


package com.mumz.test.fix.initiator;

import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.SessionID;
import quickfix.UnsupportedMessageType;

/***
 * The Class TestTradeAppInitiator.
 * @author prabhat.jha
 */
public class TestTradeAppInitiator implements Application {

	/** (non-Javadoc)
	 * @see quickfix.Application#onCreate(quickfix.SessionID)
	 */
	@Override
	public void onCreate(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogon(quickfix.SessionID)
	 */
	@Override
	public void onLogon(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogout(quickfix.SessionID)
	 */
	@Override
	public void onLogout(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toAdmin(Message message, SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#fromAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromAdmin(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			RejectLogon {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toApp(Message message, SessionID sessionId) throws DoNotSend {

	}

	/*** (non-Javadoc)
	 * @see quickfix.Application#fromApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromApp(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {

	}
}

Second is our initiator settings.

initiatorSettings.txt

#default settings for sessions
[DEFAULT]#This will applies to all sessions
ConnectionType=initiator
LogonTimeout=30
ReconnectInterval=5
ResetOnLogon=Y
FileLogPath=C:\test\app\QuickFixJ\initiator\logs
[SESSION]#A single session
BeginString=FIX.4.2
SenderCompID=MY-INITIATOR-SERVICE
TargetCompID=MY-ACCEPTOR-SERVICE
StartDay=sunday
EndDay=friday
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
CheckLatency=N
SocketConnectPort=12000
SocketConnectHost=127.0.0.1
UseDataDictionary=Y
DataDictionary=C:\test\app\QuickFixJ\initiator\FIX42.xml
FileStorePath=C:\test\app\QuickFixJ\initiator\ICE

Third we will write our very simple acceptor TestTradeAppExecutor.java.

TestTradeAppExecutor


package com.mumz.test.fix.executor;

import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.SessionID;
import quickfix.UnsupportedMessageType;

/***
 * The Class TestTradeAppExecutor.
 * @author prabhat.jha
 */
public class TestTradeAppExecutor implements Application {
	
	/** (non-Javadoc)
	 * @see quickfix.Application#onCreate(quickfix.SessionID)
	 */
	@Override
	public void onCreate(SessionID sessionId) {
		System.out.println("Executor Session Created with SessionID = " + sessionId);
	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogon(quickfix.SessionID)
	 */
	@Override
	public void onLogon(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#onLogout(quickfix.SessionID)
	 */
	@Override
	public void onLogout(SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toAdmin(Message message, SessionID sessionId) {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#fromAdmin(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromAdmin(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			RejectLogon {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#toApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void toApp(Message message, SessionID sessionId) throws DoNotSend {

	}

	/** (non-Javadoc)
	 * @see quickfix.Application#fromApp(quickfix.Message, quickfix.SessionID)
	 */
	@Override
	public void fromApp(Message message, SessionID sessionId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
			UnsupportedMessageType {
		
	}
}

Fourth step is to write settings for acceptor.

acceptorSettings.txt

#default settings for sessions
[DEFAULT]    # ——-> This will applies to all sessions
ConnectionType=acceptor
ResetOnLogon=Y
FileLogPath=C:\test\app\QuickFixJ\acceptor\logs
LogonTimeout=6000
ReconnectInterval=6030
[SESSION] #A single session
BeginString=FIX.4.2
SenderCompID=MY-ACCEPTOR-SERVICE
TargetCompID=MY-INITIATOR-SERVICE
StartDay=sunday
EndDay=friday
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
CheckLatency=N
SocketAcceptPort=12000
UseDataDictionary=Y
DataDictionary=C:\test\app\QuickFixJ\acceptor\FIX42.xml
FileStorePath=C:\test\app\QuickFixJ\acceptor\ICE

Fifth we will write our simple class which will start our executor. On our way building a complete application we will revisit and cleanup the way we are starting our executor, for now let it be a simple java class.

TestTradeAppExecutorApp.java


package com.mumz.test.fix.executor;

import quickfix.Application;
import quickfix.ConfigError;
import quickfix.DefaultMessageFactory;
import quickfix.FileLogFactory;
import quickfix.FileStoreFactory;
import quickfix.MessageFactory;
import quickfix.SessionSettings;
import quickfix.SocketAcceptor;

/**
 * The Class TestTradeAppExecutorApp.
 * 
 * @author prabhat.jha
 */
public class TestTradeAppExecutorApp {

	/**
	 * The main method.
	 * 
	 * @param args
	 *            the args
	 */
	public static void main(String[] args) {
		SocketAcceptor socketAcceptor = null;
		try {
			SessionSettings executorSettings = new SessionSettings(
					"C:/test/app/QuickFixJ/acceptor/acceptorSettings.txt");
			Application application = new TestTradeAppExecutor();
			FileStoreFactory fileStoreFactory = new FileStoreFactory(
					executorSettings);
			MessageFactory messageFactory = new DefaultMessageFactory();
			FileLogFactory fileLogFactory = new FileLogFactory(executorSettings);
			socketAcceptor = new SocketAcceptor(application, fileStoreFactory,
					executorSettings, fileLogFactory, messageFactory);
			socketAcceptor.start();
		} catch (ConfigError e) {
			e.printStackTrace();
		}
	}
}

Fifth and final step is to create a simple java class for running our initiator.

TestTradeAppExecutorApp.java

package com.mumz.test.fix.initiator;

import quickfix.Application;
import quickfix.ConfigError;
import quickfix.DefaultMessageFactory;
import quickfix.FileLogFactory;
import quickfix.FileStoreFactory;
import quickfix.MessageFactory;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionSettings;
import quickfix.SocketInitiator;

/**
 * The Class TestTradeAppInitiatorApp.
 * 
 * @author prabhat.jha
 */
public class TestTradeAppInitiatorApp {

	/**
	 * The main method.
	 * 
	 * @param args
	 *            the args
	 */
	public static void main(String[] args) {
		SocketInitiator socketInitiator = null;
		try {
			SessionSettings initiatorSettings = new SessionSettings(
					"C:/test/app/QuickFixJ/initiator/initiatorSettings.txt");
			Application initiatorApplication = new TestTradeAppInitiator();
			FileStoreFactory fileStoreFactory = new FileStoreFactory(
					initiatorSettings);
			FileLogFactory fileLogFactory = new FileLogFactory(
					initiatorSettings);
			MessageFactory messageFactory = new DefaultMessageFactory();
			socketInitiator = new SocketInitiator(initiatorApplication, fileStoreFactory, initiatorSettings, fileLogFactory, messageFactory);
			socketInitiator.start();
			SessionID sessionId = socketInitiator.getSessions().get(0);
			Session.lookupSession(sessionId).logon();
		} catch (ConfigError e) {
			e.printStackTrace();
		}
	}
}

That’s all, while executing this example, first run TestTradeAppExecutorApp and then TestTradeAppInitiatorApp.

If everything is proper you should see logs and ICE folders created in your initiator and executor directory. Your initiator log file should contain something like this:

20120731-05:04:53: Session FIX.4.2:MY-INITIATOR-SERVICE->MY-ACCEPTOR-SERVICE schedule is weekly, SUN 00:00:00-UTC – FRI 00:00:00-UTC
20120731-05:04:53: Created session: FIX.4.2:MY-INITIATOR-SERVICE->MY-ACCEPTOR-SERVICE

And in your acceptor log something like:

20120731-05:04:48: Session FIX.4.2:MY-ACCEPTOR-SERVICE->MY-INITIATOR-SERVICE schedule is weekly, SUN 00:00:00-UTC – FRI 00:00:00-UTC
20120731-05:04:48: Created session: FIX.4.2:MY-ACCEPTOR-SERVICE->MY-INITIATOR-SERVICE

Send and Receive Message from FIX Server using QuickFIX/J

Posted on Updated on

In this tutorial we will use QuickFIX/J to connect to a remote FIX server and send logon message.

To consume messages from FIX server we need an Initiator.

What we need :

  1. JDK1.6.0
  2. log4j-1.2.15.jar
  3. quickfixj-all-1.5.2.jar
  4. slf4j-api-1.6.3.jar
  5. mina-core-1.1.7.jar

First we need to specify the Session and Default Settings to QuickFIX/J.

Create a file called as sessionSettings.txt.

Copy the content from below in your file. Don’t worry if you cannot understand all or any of these, we will explore them later.

[DEFAULT]# Settings which apply to all the Sessions.
ConnectionType=initiator
LogonTimeout=30
ReconnectInterval=30
ResetOnLogon=Y
FileLogPath=C:\Work\QuickFIXJ\logs
[SESSION]# Settings specifically for one session
BeginString=FIX.4.2
SenderCompID=THIS VALUE IS THE CLIENT ID
TargetCompID=THIS VALUE IS THE FIX SERVER ID
StartDay=sunday
EndDay=friday
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
CheckLatency=N
MaxLatency=240
SocketConnectPort=PORT NUMBER OF THE SERVER
SocketConnectHost=IP ADDRESS OF YOUR SERVER
UseDataDictionary=Y
DataDictionary=C:\Work\QuickFIXJ\datadictionary\FIX42.xml
FileStorePath=C:\Work\QuickFIXJ\sessioninfo
  1. ConnectionType – This specifies if you are creating an acceptor (Server) or initiator (Client).
  2. LogonTimeout – Time in seconds before your session will expire, keep sending heartbeat request if you don’t want it to expire.
  3. ReconnectInterval – Time in seconds before reconnecting.
  4. ResetOnLogon – FIX messages have a sequence ID, which shouldn’t be used for uniqueness as specification doesn’t guarantee anything about them. If Y is provided every time logon message is sent, server will reset the sequence.
  5. FileLogPath – Path where logs will be written.
  6. BeginString – Should always specifies your FIX version.
  7. SenderCompID – A String which identifies client uniquely.
  8.  TargetCompID – A String which identifies Server uniquely.
  9. Start and End Day – Start and End of your session if session is week long, used with Start and End Time.
  10. Start and End Time – Time when session starts and ends.
  11. HeartBtInt – Time in seconds which specifies the interval between heartbeat.
  12. CheckLatency – If this is set to True then you have to provide MaxLatency, value should be large enough to cater to network latency.
  13. SocketConnectPort – Port of FIX Server.
  14. SocketConnectHost – IP Address of the FIX Server.
  15. UseDataDictionary – Specifies if data dictionary will be used.
  16. FileStorePath – Session info will be saved here.

You can read more about configuration at Official Documentation.

Next Step is to write the Java code.

Every FIX application should have an implementation of Application interface, Application interface contains call back methods.
MessageCracker provides callback methods for receiving messages from Server.

public class TestApplicationImpl extends MessageCracker implements Application {
	@Override
	public void fromAdmin(Message arg0, SessionID arg1) throws FieldNotFound,
			IncorrectDataFormat, IncorrectTagValue, RejectLogon {
		System.out.println("Successfully called fromAdmin for sessionId : "
				+ arg0);
	}

	@Override
	public void fromApp(Message arg0, SessionID arg1) throws FieldNotFound,
			IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
		System.out.println("Successfully called fromApp for sessionId : "
				+ arg0);
	}

	@Override
	public void onCreate(SessionID arg0) {
		System.out.println("Successfully called onCreate for sessionId : "
				+ arg0);
	}

	@Override
	public void onLogon(SessionID arg0) {
		System.out.println("Successfully logged on for sessionId : " + arg0);
	}

	@Override
	public void onLogout(SessionID arg0) {
		System.out.println("Successfully logged out for sessionId : " + arg0);
	}

	@Override
	public void toAdmin(Message message, SessionID sessionId) {
		System.out.println("Inside toAdmin");
	}

	@Override
	public void toApp(Message arg0, SessionID arg1) throws DoNotSend {
		System.out.println("Message : " + arg0 + " for sessionid : " + arg1);
	}

	@Override
	public void onMessage(NewOrderSingle message, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		System.out.println("Inside onMessage for New Order Single");
		super.onMessage(message, sessionID);
	}

	@Override
	public void onMessage(SecurityDefinition message, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		System.out.println("Inside onMessage for SecurityDefinition");
		super.onMessage(message, sessionID);
	}

	@Override
	public void onMessage(Logon message, SessionID sessionID)
			throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
		System.out.println("Inside Logon Message");
		super.onMessage(message, sessionID);
	}
}

Next step is to connect to FIX server and send Logon Message

public class TestQuickFixJConnectivity {
	public static void main(String[] args) {
		SocketInitiator socketInitiator = null;
		try {
			SessionSettings sessionSettings = new SessionSettings("C:\\Work\\QuickFixJ\\sessionSettings.txt");
			Application application = new TestApplicationImpl();
			FileStoreFactory fileStoreFactory = new FileStoreFactory(sessionSettings);
			FileLogFactory logFactory = new FileLogFactory(sessionSettings);
			MessageFactory messageFactory = new DefaultMessageFactory();
			socketInitiator = new SocketInitiator(application,
					fileStoreFactory, sessionSettings, logFactory,
					messageFactory);
			socketInitiator.start();
			SessionID sessionId = socketInitiator.getSessions().get(0);
			sendLogonRequest(sessionId);
			int i = 0;
			do {
				try {
					Thread.sleep(1000);
					System.out.println(socketInitiator.isLoggedOn());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				i++;
			} while ((!socketInitiator.isLoggedOn()) && (i < 30));
		} catch (ConfigError e) {
			e.printStackTrace();
		} catch (SessionNotFound e) {
			e.printStackTrace();
		} catch (Exception exp) {
			exp.printStackTrace();
		} finally {
			if (socketInitiator != null) {
				socketInitiator.stop(true);
			}
		}
	}
	private static void sendLogonRequest(SessionID sessionId)
			throws SessionNotFound {
		Logon logon = new Logon();
		Header header = logon.getHeader();
		header.setField(new BeginString("FIX.4.2"));
		logon.set(new HeartBtInt(30));
		logon.set(new ResetSeqNumFlag(true));
		boolean sent = Session.sendToTarget(logon, sessionId);
		System.out.println("Logon Message Sent : " + sent);
	}
}