Search code examples
javafix-protocolquickfixj

How to send FIX message with QuickFIX/J


I need a simple example of how to initialize a session and send one FIX message. I have this initial code:

SessionSettings settings = new SessionSettings( new FileInputStream("fix.cfg"));

Application application = new Application(settings);
MessageStoreFactory messageStoreFactory = new FileStoreFactory(settings);
LogFactory logFactory = new ScreenLogFactory( true, true, true);
MessageFactory messageFactory = new DefaultMessageFactory();

Initiator initiator = new SocketInitiator(application, messageStoreFactory, settings, logFactory, messageFactory);
initiator.start();

Solution

  • From the code above, I see that you have an initiator application (the client) and you need to also create an acceptor application (the server). Below I've attached the two classes that will do what do you want.

    First I'll list the acceptor application:

    public class ServerApplication implements Application {
    
        @Override
        public void onCreate(SessionID sessionID) {
        }
    
        @Override
        public void onLogon(SessionID sessionID) {
        }
    
        @Override
        public void onLogout(SessionID sessionID) {
        }
    
        @Override
        public void toAdmin(Message message, SessionID sessionID) {
        }
    
        @Override
        public void fromAdmin(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon {
        }
    
        @Override
        public void toApp(Message message, SessionID sessionID) throws DoNotSend {
        }
    
        @Override
        public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
            System.out.println("FromApp: " + message);
        }
    
        public static void main(String[] args) throws ConfigError, FileNotFoundException, InterruptedException, SessionNotFound {
            SessionSettings settings = new SessionSettings("res/acceptor.config");
    
            Application application = new ServerApplication();
            MessageStoreFactory messageStoreFactory = new FileStoreFactory(settings);
            LogFactory logFactory = new ScreenLogFactory( true, true, true);
            MessageFactory messageFactory = new DefaultMessageFactory();
    
            Acceptor initiator = new SocketAcceptor(application, messageStoreFactory, settings, logFactory, messageFactory);
            initiator.start();
    
            CountDownLatch latch = new CountDownLatch(1);
            latch.await();
        }
    }
    

    This is a server application that will stay started and listen for messages from the clients which connect to it. Here is the configuration file (acceptor.properties) used by it:

    [default]
    ApplicationID=server
    FileStorePath=storage/messages/
    ConnectionType=acceptor
    StartTime=00:01:00 Europe/Bucharest
    EndTime=23:59:00 Europe/Bucharest
    HeartBtInt=30
    UseDataDictionary=Y
    DataDictionary=FIX42.xml
    ValidateUserDefinedFields=N
    ValidateIncomingMessage=N
    RefreshOnLogon=Y
    
    [session]
    BeginString=FIX.4.2
    SocketAcceptPort=9877
    SenderCompID=server
    TargetCompID=client
    AcceptorTemplate=N
    lockquote
    

    Next is the client application code. It tries to connect to a server and after that it will send a message to it:

    public class ClientApplication implements Application {
    
        private static volatile SessionID sessionID;
    
        @Override
        public void onCreate(SessionID sessionID) {
            System.out.println("OnCreate");
        }
    
        @Override
        public void onLogon(SessionID sessionID) {
            System.out.println("OnLogon");
            ClientApplication.sessionID = sessionID;
        }
    
        @Override
        public void onLogout(SessionID sessionID) {
            System.out.println("OnLogout");
            ClientApplication.sessionID = null;
        }
    
        @Override
        public void toAdmin(Message message, SessionID sessionID) {
            System.out.println("ToAdmin");
        }
    
        @Override
        public void fromAdmin(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon {
            System.out.println("FromAdmin");
        }
    
        @Override
        public void toApp(Message message, SessionID sessionID) throws DoNotSend {
            System.out.println("ToApp: " + message);
        }
    
        @Override
        public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
            System.out.println("FromApp");
        }
    
        public static void main(String[] args) throws ConfigError, FileNotFoundException, InterruptedException, SessionNotFound {
            SessionSettings settings = new SessionSettings("res/initiator.config");
    
            Application application = new ClientApplication();
            MessageStoreFactory messageStoreFactory = new FileStoreFactory(settings);
            LogFactory logFactory = new ScreenLogFactory( true, true, true);
            MessageFactory messageFactory = new DefaultMessageFactory();
    
            Initiator initiator = new SocketInitiator(application, messageStoreFactory, settings, logFactory, messageFactory);
            initiator.start();
    
            while (sessionID == null) {
                Thread.sleep(1000);
            }
    
            final String orderId = "342";
            NewOrderSingle newOrder = new NewOrderSingle(new ClOrdID(orderId), new HandlInst('1'), new Symbol("6758.T"),
                    new Side(Side.BUY), new TransactTime(new Date()), new OrdType(OrdType.MARKET));
            Session.sendToTarget(newOrder, sessionID);
            Thread.sleep(5000);
        }
    }
    

    The configuration file for it (initiator.config) is almost the same as the one used for the acceptor:

    [default]
    ApplicationID=client
    FileStorePath=storage/messages/
    ConnectionType=initiator
    StartTime=00:01:00 Europe/Bucharest
    EndTime=23:59:00 Europe/Bucharest
    HeartBtInt=30
    UseDataDictionary=Y
    DataDictionary=FIX42.xml
    ValidateUserDefinedFields=N
    ValidateIncomingMessage=N
    RefreshOnLogon=Y
    
    [session]
    BeginString=FIX.4.2
    SocketConnectHost=localhost
    SocketConnectPort=9877
    SenderCompID=client
    TargetCompID=server
    

    The configuration files both miss some options, but for testing purposes are enough. Each of the classes has a main method added just for testing the case you wanted.

    Normally you would handle a bit different the way they are started or stopped. The server application listens for messages/connections and is never stopped, while the client application stops right after sending the first message.