QuickfixJ: Broker OMS

In this tutorial, we are creating a simple Order Management System (OMS) template for a broker system.  The broker will utilize the MarketIntelligence class created in the last tutorial to simulate a market data source for bid and ask prices for securities on the Hong Kong Stock Exchange.  In order to implement the OMS with QuickfixJ, we will need to create two java classes, one for implementing a QuickfixJ application, and one for launching the application and supplying parameters to the application.  In this tutorial, our broker is Lan Fong Securities, an imaginary, boutique brokerage firm based in Hong Kong, and the client is Baker Street Capital, also an imaginary, London-based boutique investment firm.

Implementing a QuickfixJ application requires two steps.  The first step is to create a class deriving from quickfix.MessageCracker and implementing the quickfix.Application interface. To implement the interface, your class needs to override the following methods:

  • void onCreate(SessionID sessionID)
  • void onLogon(SessionID sessionID)
  • void onLogout(SessionID sessionID)
  • void toAdmin(Message msg, SessionID sessionID)
  • void fromAdmin(Message msg, SessionID sessionID)
  • void toApp(Message msg, SessionID sessionID)
  • void fromApp(Message msg, SessionID sessionID)

For more details, refer to the QuickfixJ documentation.  Lets just jump right in with the application class for the broker:

import java.io.*;
import java.util.*;

// Quickfix Exceptions
import quickfix.DoNotSend;
import quickfix.FieldConvertError;
import quickfix.ConfigError;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.FieldNotFound;
import quickfix.UnsupportedMessageType;
import quickfix.SessionNotFound;
import quickfix.RejectLogon;

// Quickfix Data Types
import quickfix.SessionID;
import quickfix.Message;
import quickfix.Session;
import quickfix.SessionSettings;
import quickfix.FixVersions;
import quickfix.MessageUtils;
import quickfix.field.*;

public class Application extends quickfix.MessageCracker
                         implements quickfix.Application
{
    private MarketIntelligence mi = null;

    public Application(SessionSettings settings)
        throws ConfigError, FieldConvertError
    {
        mi = new MarketIntelligence();
        String ask = mi.getAsk("0001");
        System.out.println(ask);
    }

    // ===================================================
    // Overriden quickfix.MessageCracker onMessage()
    // ===================================================
    public void onMessage(quickfix.fix42.NewOrderSingle order,
                          SessionID sessionID)
        throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue
    {
    }

    // ===================================================
    // quickfix.Application interface implementation
    // ===================================================

    // Called when quickfix creates a new session
    public void onCreate(SessionID sessionID)
    {
    }

    // notification that a valid logon has been established
    // with the countery party
    public void onLogon(SessionID sessionID)
    {
    }

    // notification that a FIX session is no longer online
    public void onLogout(SessionID sessionID)
    {
    }

    // allows for peaking at msgs from this apps FIX engine to
    // the counter party
    public void toAdmin(Message msg, SessionID sessionID)
    {
    }

    // callback notify for when admin msgs are received by FIX from
    // the counter party
    public void fromAdmin(Message msg, SessionID sessionID)
        throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
               RejectLogon
    {
    }
   // callback for app messages this app  send to the counter party
    public void toApp(Message msg, SessionID sessionID)
        throws DoNotSend
    {
    }

    // all app level requests comes through here
    public void fromApp(Message msg, SessionID sessionID)
        throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
               UnsupportedMessageType
    {
        // call base class message parser
        crack(msg, sessionID);
    }
}

In the constructor, a reference to a MarketIntelligence object is created, and we get the ask price for symbol 0001 just for testing.  Six of the seven interface methods are implemented but left blank as they are not used yet.  In the fromApp() method, the crack() method inherited from quickfix.MessageCracker is called.

The next step is to create a java class that acts as a QuickfixJ acceptor, a software component that waits for clients, called initiators, to connect and create a new FIX session.  This class is also responsible for passing parameters to the application class.  Again, it is probably easier to just jump into the code.

import java.io.*;
import java.util.*;

// Quickfix Exceptions
import quickfix.ConfigError;
import quickfix.FieldConvertError;
import quickfix.RuntimeError;

// Quickfix Data Types
import quickfix.SessionID;
import quickfix.SessionSettings;
import quickfix.SocketAcceptor;
import quickfix.mina.acceptor.DynamicAcceptorSessionProvider;
import quickfix.mina.acceptor.DynamicAcceptorSessionProvider.TemplateMapping;
import quickfix.DefaultMessageFactory;
import quickfix.FileStoreFactory;
import quickfix.LogFactory;
import quickfix.ScreenLogFactory;
import quickfix.MessageFactory;
import quickfix.MessageStoreFactory;

public class LanFongOMS
{
    private final SocketAcceptor acceptor;

    public LanFongOMS(SessionSettings settings)
        throws ConfigError, FieldConvertError
    {
        Application app = new Application(settings);
        MessageStoreFactory msgStoreFactory = new FileStoreFactory(settings);
        LogFactory logFactory = new ScreenLogFactory(true, true, true);
        MessageFactory msgFactory = new DefaultMessageFactory();

        acceptor = new SocketAcceptor(app, msgStoreFactory, settings,
                                      logFactory, msgFactory);
    }

    // Accept incoming connections
    public void start() throws RuntimeError, ConfigError
    {
        acceptor.start();
    }

    // Stop accepting incoming connections
    public void stop()
    {
        acceptor.stop();
    }

    // Program entry-point
    public static void main( String args[] )
    {
        SessionSettings sessionSettings = null;
        try{
            if( args.length != 1 ){
                System.err.println(" Usage: LanFongOMS ");
            }
            sessionSettings = loadConfiguration(args[0]);
            Iterator sectionIterator = sessionSettings.sectionIterator();
            while( sectionIterator.hasNext() ){
                SessionID id = sectionIterator.next();
                System.out.println( id.toString() );
            }

            LanFongOMS oms = new LanFongOMS(sessionSettings);
            oms.start();
            System.out.println("press  to quit");
            System.in.read();
            oms.stop();
        }
        catch( Exception ex ){
            System.err.println( "Exception!" );
            System.err.println( ex.getMessage() );
        }
        System.exit(0);
    }

    // Load customer configuration from first argument
    private static SessionSettings loadConfiguration( String configFilePath )
        throws FileNotFoundException
    {
        SessionSettings settings = null;
        try{
            InputStream inputStream = new FileInputStream(configFilePath);
            settings = new SessionSettings(inputStream);
            inputStream.close();
        }
        catch( Exception ex ){
            System.err.println( ex.getMessage() );

        }
        return settings;
    }

}

The code should be quite straight forward.  The entry point main() loads a configuration file taken as a command line argument and creates an instance of the broker’s OMS, which in turn creates a QuickfixJ application object in its constructor.  Back in main(), the acceptor is started that listens on a port number (from the config file) for incoming connections.  When the user at the controlling terminal presses the enter key, the acceptor is stopped and the OMS exists.

Before running the OMS, we need to update the ant build.xml file to support our new code.  The following modifications should suffice:

<target name=”jar” depends=”compile”>
<jar destfile=”LanFongOMS.jar” basedir=”.” includes=”**/*.class”>
<manifest>
<attribute name=”Main-Class” value=”LanFongOMS”/>
</manifest>
</jar>
</target>

<target name=”run” depends=”jar”>
<java classname=”LanFongOMS” fork=”true”>
<classpath refid=”project.class.path”/>
<arg value=”lanfong.cfg”/>
</java>
</target>

Basically, we need to update the jar target to specify the java file containing the entry point function for the JAR manifest, and we need to specify the argument for the OMS, a configuration file (lanfong.cfg).

Now that all of the code has been implemented, we must supply a config file that sets the application specific parameters for the QuickfixJ application.  One field of interest is ConnectionType, which can be set to acceptor or initiator.  In our example, the customer, Baker St. Capital, will connect to its broker, Lan Fong Securities, and thus they are initiator and acceptor, respectively.

[default]
FileStorePath=logs
ConnectionType=acceptor
StartTime=08:00:00
EndTime=19:00:00
HeartBtInt=30
SenderCompID=LANFONG
TargetCompID=BAKERST
UseDataDictionary=Y

[session]
BeginString=FIX.4.2
SocketAcceptPort=9878
SocketAcceptAddress=127.0.0.1
SocketAcceptProtocol=TCP

Other fields of interest are SenderCompID and TargetCompID, which specify the source and target of FIX messages.  Also of interest is the BeginString in the session section.  We use FIX version 4.2, but you could use any version of the FIX protocol supported by QuickfixJ, or even supported multiple versions of the FIX protocol in one config file.  Note that Quickfix sessions are identified as a combination of BeginString, SenderCompID and TargetCompID.  There are many, many more parameters that we can set, so please refer to the documentation for further information about config files.

Finally, we can bring up the Lan Fong Securities OMS:

trantor:quickfix_demo$ ant
Buildfile: build.xml

compile:
    [javac] Compiling 5 source files

jar:
      [jar] Building jar: /Users/globalengineer/Development/quickfix_demo/LanFongOMS.jar

run:
     [java] FIX.4.2:LANFONG->BAKERST
     [java] 41.59
     [java] <20100429-03:59:35, FIX.4.2:LANFONG->BAKERST, event> (Session FIX.4.2:LANFONG->BAKERST schedule is daily, 08:00:00 UTC - 19:00:00 UTC (daily, 08:00:00 UTC - 19:00:00 UTC))
     [java] <20100429-03:59:35, FIX.4.2:LANFONG->BAKERST, event> (Session state is not current; resetting FIX.4.2:LANFONG->BAKERST)
     [java] <20100429-03:59:35, FIX.4.2:LANFONG->BAKERST, event> (Created session: FIX.4.2:LANFONG->BAKERST)
     [java] Apr 28, 2010 11:59:35 PM quickfix.mina.NetworkingOptions logOption
     [java] INFO: Socket option: SocketTcpNoDelay=true
     [java] Apr 28, 2010 11:59:35 PM quickfix.mina.NetworkingOptions logOption
     [java] INFO: Socket option: SocketSynchronousWrites=false
     [java] Apr 28, 2010 11:59:35 PM quickfix.mina.NetworkingOptions logOption
     [java] INFO: Socket option: SocketSynchronousWriteTimeout=30000
     [java] Apr 28, 2010 11:59:35 PM quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections
     [java] INFO: Listening for connections at /127.0.0.1:9878
     [java] press  to quit

Though our OMS does not do anything at this point, it has been brought up and is listening for incoming connections.  Notice that the quote retrieved from the market data source in the application’s class is printed out in the second line of the application output.  In the next installment of this tutorial, we’ll implement the a simple OMS for the client that acts as a QuickfixJ initiator and connects to our broker’s OMS.  Stay tuned!

Advertisements

11 thoughts on “QuickfixJ: Broker OMS

  1. Nice one I am learning java and FIX this is just the sort of project I am looking for. When will the parts be available?

  2. Thanks a lot for just a wonderfull tutorial….i was a newbiee to FIX but now i think i learnt a lot from this tutorial…..waiting for any new post related to quickFixJ.

  3. its awesome, looking for the next blog about the client. Which you have promised long back but not yet done.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s