FIX and Java
If you like to work on trading applications, you need to know the
FIX protocol and a FIX
engine like
QuickFIX/J.
This extends our
simple QuickFIX Java example tutorial. This assumes that you understand the first
QuickFIX Java tutorial.
Step 1: The sender or the initiator
FIXSender.java has a
System.out.println(..) in the
fromApp(..,..) method to print the execution report returned by receiver or the acceptor
FIXReceiver.java
package com.example;
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;
public class FIXSender implements Application {
@Override
public void fromAdmin(Message arg0, SessionID arg1) throws FieldNotFound, IncorrectDataFormat,
IncorrectTagValue, RejectLogon {
}
@Override
public void fromApp(Message arg0, SessionID arg1) throws FieldNotFound, IncorrectDataFormat,
IncorrectTagValue, UnsupportedMessageType {
System.out.println("Sender fromApp: " + arg0);
}
@Override
public void onCreate(SessionID arg0) {}
@Override
public void onLogon(SessionID arg0) {}
@Override
public void onLogout(SessionID arg0) {}
@Override
public void toAdmin(Message arg0, SessionID arg1) {}
@Override
public void toApp(Message msg, SessionID sessionId) throws DoNotSend {
System.out.println("Sender toApp: " + msg.toString());
}
}
Step 2: The
onMessage(..,..) method is extended to return an execution report in
FIXReceiver.java
package com.example;
import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.UnsupportedMessageType;
import quickfix.field.AvgPx;
import quickfix.field.ClOrdID;
import quickfix.field.CumQty;
import quickfix.field.ExecID;
import quickfix.field.ExecType;
import quickfix.field.LastPx;
import quickfix.field.LeavesQty;
import quickfix.field.OrdStatus;
import quickfix.field.OrdType;
import quickfix.field.OrderID;
import quickfix.field.OrderQty;
import quickfix.field.Price;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.fix44.ExecutionReport;
import quickfix.fix44.MessageCracker;
import quickfix.fix44.NewOrderSingle;
public class FIXReceiver extends MessageCracker implements Application {
@Override
public void onMessage(NewOrderSingle order, SessionID sessionID) throws FieldNotFound, IncorrectTagValue {
System.out.println("Receiver onMessage.. " + order);
Symbol symbol = new Symbol();
Side side = new Side();
OrdType ordType = new OrdType();
OrderQty orderQty = new OrderQty();
Price price = new Price();
ClOrdID clOrdID = new ClOrdID();
order.get(ordType);
if (ordType.getValue() != OrdType.LIMIT) {
throw new IncorrectTagValue(ordType.getField());
}
order.get(symbol);
order.get(side);
order.get(orderQty);
order.get(price);
order.get(clOrdID);
ExecutionReport executionReport = new ExecutionReport(
new OrderID("1"),
new ExecID("1"),
new ExecType(ExecType.NEW),
new OrdStatus(OrdStatus.FILLED),
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue())
);
executionReport.set(clOrdID);
executionReport.set(orderQty);
executionReport.set(side);
executionReport.set(new LastPx(price.getValue()));
if (order.isSetAccount()) {
executionReport.set(order.getAccount());
}
try {
Session.sendToTarget(executionReport, sessionID);
} catch (SessionNotFound e) {
e.printStackTrace();
}
}
@Override
public void fromAdmin(Message arg0, SessionID arg1) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
RejectLogon {
}
@Override
public void fromApp(Message arg0, SessionID arg1) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue,
UnsupportedMessageType {
System.out.println("Receiver fromApp.. " + arg0);
crack(arg0, arg1); // calls onMessage(..,..)
}
@Override
public void onCreate(SessionID arg0) {
System.out.println("Receiver onCreate.. " + arg0);
}
@Override
public void onLogon(SessionID arg0) {
System.out.println("Receiver onLogon.." + arg0);
}
@Override
public void onLogout(SessionID arg0) {
}
@Override
public void toAdmin(Message arg0, SessionID arg1) {
}
@Override
public void toApp(Message arg0, SessionID arg1) throws DoNotSend {
}
}
Output: Receiver
<20140801-06:43:48, FIX.4.4:FixServer->CLIENT1, event> (Session FIX.4.4:FixServer->CLIENT1 schedule is daily, 00:00:00-UTC - 00:00:00-UTC)
<20140801-06:43:48, FIX.4.4:FixServer->CLIENT1, event> (Created session: FIX.4.4:FixServer->CLIENT1)
Receiver onCreate.. FIX.4.4:FixServer->CLIENT1
press <enter> to quit
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, incoming> (8=FIX.4.4 9=71 35=A 34=7 49=CLIENT1 52=20140801-06:43:54.569 56=FixServer 98=0 108=30 10=156 )
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, event> (Accepting session FIX.4.4:FixServer->CLIENT1 from /127.0.0.1:62832)
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, event> (Acceptor heartbeat set to 30 seconds)
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, event> (Received logon)
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, event> (Responding to Logon request)
<20140801-06:43:54, FIX.4.4:FixServer->CLIENT1, outgoing> (8=FIX.4.4 9=71 35=A 34=7 49=FixServer 52=20140801-06:43:54.605 56=CLIENT1 98=0 108=30 10=147 )
Receiver onLogon..FIX.4.4:FixServer->CLIENT1
<20140801-06:43:56, FIX.4.4:FixServer->CLIENT1, incoming> (8=FIX.4.4 9=122 35=D 34=8 49=CLIENT1 52=20140801-06:43:56.613 56=FixServer 11=DLF 38=45 40=2 44=25.4 54=1 55=BHP 60=20140801-06:43:56.611 10=164 )
Receiver fromApp.. 8=FIX.4.4 9=122 35=D 34=8 49=CLIENT1 52=20140801-06:43:56.613 56=FixServer 11=DLF 38=45 40=2 44=25.4 54=1 55=BHP 60=20140801-06:43:56.611 10=164
Receiver onMessage.. 8=FIX.4.4 9=122 35=D 34=8 49=CLIENT1 52=20140801-06:43:56.613 56=FixServer 11=DLF 38=45 40=2 44=25.4 54=1 55=BHP 60=20140801-06:43:56.611 10=164
<20140801-06:43:56, FIX.4.4:FixServer->CLIENT1, outgoing> (8=FIX.4.4 9=125 35=8 34=8 49=FixServer 52=20140801-06:43:56.700 56=CLIENT1 6=25.4 11=DLF 14=45 17=1 31=25.4 37=1 38=45 39=2 54=1 150=0 151=0 10=073 )
<20140801-06:44:27, FIX.4.4:FixServer->CLIENT1, outgoing> (8=FIX.4.4 9=59 35=0 34=9 49=FixServer 52=20140801-06:44:27.436 56=CLIENT1 10=116 )
<20140801-06:44:27, FIX.4.4:FixServer->CLIENT1, incoming> (8=FIX.4.4 9=59 35=0 34=9 49=CLIENT1 52=20140801-06:44:27.442 56=FixServer 10=113 )
<20140801-06:44:57, FIX.4.4:FixServer->CLIENT1, outgoing> (8=FIX.4.4 9=60 35=0 34=10 49=FixServer 52=20140801-06:44:57.436 56=CLIENT1 10=151 )
<20140801-06:44:57, FIX.4.4:FixServer->CLIENT1, incoming> (8=FIX.4.4 9=60 35=5 34=10 49=CLIENT1 52=20140801-06:44:57.440 56=FixServer 10=151 )
<20140801-06:44:57, FIX.4.4:FixServer->CLIENT1, event> (Received logout request)
<20140801-06:44:57, FIX.4.4:FixServer->CLIENT1, outgoing> (8=FIX.4.4 9=60 35=5 34=11 49=FixServer 52=20140801-06:44:57.443 56=CLIENT1 10=155 )
<20140801-06:44:57, FIX.4.4:FixServer->CLIENT1, event> (Sent logout response)
Output: Sender
<20140801-06:43:53, FIX.4.4:CLIENT1->FixServer, event> (Session FIX.4.4:CLIENT1->FixServer schedule is daily, 00:00:00-UTC - 00:00:00-UTC)
<20140801-06:43:53, FIX.4.4:CLIENT1->FixServer, event> (Created session: FIX.4.4:CLIENT1->FixServer)
<20140801-06:43:54, FIX.4.4:CLIENT1->FixServer, outgoing> (8=FIX.4.4 9=71 35=A 34=7 49=CLIENT1 52=20140801-06:43:54.569 56=FixServer 98=0 108=30 10=156 )
<20140801-06:43:54, FIX.4.4:CLIENT1->FixServer, event> (Initiated logon request)
<20140801-06:43:54, FIX.4.4:CLIENT1->FixServer, incoming> (8=FIX.4.4 9=71 35=A 34=7 49=FixServer 52=20140801-06:43:54.605 56=CLIENT1 98=0 108=30 10=147 )
<20140801-06:43:54, FIX.4.4:CLIENT1->FixServer, event> (Received logon)
Sender toApp: 8=FIX.4.4 9=122 35=D 34=8 49=CLIENT1 52=20140801-06:43:56.613 56=FixServer 11=DLF 38=45 40=2 44=25.4 54=1 55=BHP 60=20140801-06:43:56.611 10=164
<20140801-06:43:56, FIX.4.4:CLIENT1->FixServer, outgoing> (8=FIX.4.4 9=122 35=D 34=8 49=CLIENT1 52=20140801-06:43:56.613 56=FixServer 11=DLF 38=45 40=2 44=25.4 54=1 55=BHP 60=20140801-06:43:56.611 10=164 )
<20140801-06:43:56, FIX.4.4:CLIENT1->FixServer, incoming> (8=FIX.4.4 9=125 35=8 34=8 49=FixServer 52=20140801-06:43:56.700 56=CLIENT1 6=25.4 11=DLF 14=45 17=1 31=25.4 37=1 38=45 39=2 54=1 150=0 151=0 10=073 )
Sender fromApp: 8=FIX.4.4 9=125 35=8 34=8 49=FixServer 52=20140801-06:43:56.700 56=CLIENT1 6=25.4 11=DLF 14=45 17=1 31=25.4 37=1 38=45 39=2 54=1 150=0 151=0 10=073
Labels: FIX, QuickFIX