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 :
- JDK1.6.0
- log4j-1.2.15.jar
- quickfixj-all-1.5.2.jar
- slf4j-api-1.6.3.jar
- 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
- ConnectionType – This specifies if you are creating an acceptor (Server) or initiator (Client).
- LogonTimeout – Time in seconds before your session will expire, keep sending heartbeat request if you don’t want it to expire.
- ReconnectInterval – Time in seconds before reconnecting.
- 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.
- FileLogPath – Path where logs will be written.
- BeginString – Should always specifies your FIX version.
- SenderCompID – A String which identifies client uniquely.
- TargetCompID – A String which identifies Server uniquely.
- Start and End Day – Start and End of your session if session is week long, used with Start and End Time.
- Start and End Time – Time when session starts and ends.
- HeartBtInt – Time in seconds which specifies the interval between heartbeat.
- CheckLatency – If this is set to True then you have to provide MaxLatency, value should be large enough to cater to network latency.
- SocketConnectPort – Port of FIX Server.
- SocketConnectHost – IP Address of the FIX Server.
- UseDataDictionary – Specifies if data dictionary will be used.
- 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); } }
Very interesting! As someone who has just started playing around with QuickFIX/J this is great, Would greatly appreciate any further code samples you may have or to be able to contact you with some questions.
As a small aside, I don’t think QuickFIX/J is using log4j any more.
They are using log4j still, my bad!
Thanks… what kind of sample code are you looking for ?
What you have here is an excellent start. It would be great if you could give a bit more detail, implementing a full cycle. Logon, send buy or sell order, logoff and some examples of the typical issues you might have and how to handle it, like sequence numbers getting out of sync for example.
The banzai example supplied does do a lot of this but the code is not well commented and it is made more complex by GUI handling etc. This is also an issue with FIXpusher.
BTW I think there is a problem with this line of code in your example:
Application application = new BarXApplication();
Shouldn’t that be:
Application application = new TestApplicationImpl(); ?
Keep up the great work!
Thanks, I have corrected that. Also I have added couple more posts related to FIX, hope that helps.
I just noticed your new posts, going to play around with the code a bit now. This is really helpful and very much appreciated! QuickFixJ is not the easiest software to understand and your posts help a lot, I think you have a knack for writing clear code 🙂
THANKS A LOT MAN!
Good day! Would you mind if I share your blog with my myspace group?
There’s a lot of folks that I think would really enjoy your content. Please let me know. Many thanks
sure thanks
Thanks a lot, searched for this kind of an example
everywhere 🙂
Hi Prabhat, After creating all these files you have stated
above, which folders do you put the files in? Is it in the main
quickfixj folder or the other folders inside the parent quickfixj
folder?
Hi Prabhat, thank you for the informative post. Do you know
how to specify a password as part of the logon process? I am
connecting to a TT fix adapter.
Lovely post. Really helped me a lot. Thanks a lot!
You’ve done a great job,thanks for your sample ,it helps a lot.
When I tried this code it didn’t work as it sends a message
before the session is established. The error in the log was “No
responder, not sending message”. Adding a Thread.sleep(5000); after
the line socketInitiator.start(); fixes this.
Hi, I appreciate your Great efforts. I have a doubt !!!
If my server sends different versions of FIX messages, how can I change the configuration file. Also without making configuration files, shall I use the Configuration as a method to dynamically change the values ?
Hi Prabhat,
Is it possible to roll over quickfixj messages.log and event.log? If yes, How can I achive this?
In your example “DataDictionary=C:\Work\QuickFIXJ\datadictionary\FIX42.xml” line defines the path to FIX42.xml. I think this file plays a roll in generating messages.log and event.log.