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:
- Initiator: Your FIX client
- 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
Great Stuff and very clearly written!
Really useful information for me. Thank you so much.^^*
This is a very useful tutorial. Thanks much for posting it.
You saved my day brother . Thanks
thanks Prabhat, worked like a charm! gave me an easy start with quickfix. I must admit though that being a novice I wasn’t aware that initiator(client) won’t work until acceptor (server) is running and was struggling with logon failure after trying your implementation from the previous post. Maybe worth mentioning in your previous post that it won’t login until server is running whose code is given in the next page.