In our last tutorial we created a basic initiator and an acceptor. In this post we will enhance our code and we will book a single order.
First we will enhance our executor class which is TestTradeAppExecutor.java. Important thing to note :
- Extends MessageCracker – which provides callback methods
- Implementation of fromApp cracks the message which invokes onMessage callback
- onMessage is overridden and it prepares the execution report (for a successful scenario)
TestTradeAppExecutor.java
[sourcecode language=”java” highlight=”38,119,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166″]
package com.mumz.test.fix.executor;
import java.util.HashMap;
import java.util.Map;
import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.MessageCracker;
import quickfix.RejectLogon;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.UnsupportedMessageType;
import quickfix.field.AvgPx;
import quickfix.field.CumQty;
import quickfix.field.ExecID;
import quickfix.field.ExecTransType;
import quickfix.field.ExecType;
import quickfix.field.LeavesQty;
import quickfix.field.OrdStatus;
import quickfix.field.OrdType;
import quickfix.field.OrderID;
import quickfix.field.Price;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.NewOrderSingle;
/**
* The Class TestTradeAppExecutor.
*
* @author prabhat.jha
*/
public class TestTradeAppExecutor extends MessageCracker implements Application {
private Map<String, Double> priceMap = null;
public TestTradeAppExecutor() {
priceMap = new HashMap<String, Double>();
priceMap.put("EUR/USD", 1.234);
}
/**
* (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 {
crack(message, sessionId);
}
public void onMessage(NewOrderSingle message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
OrdType orderType = message.getOrdType();
Symbol currencyPair = message.getSymbol();
/*
* Assuming that we are directly dealing with Market
*/
Price price = null;
if (OrdType.FOREX_MARKET == orderType.getValue()) {
if(this.priceMap.containsKey(currencyPair.getValue())){
price = new Price(this.priceMap.get(currencyPair.getValue()));
} else {
price = new Price(1.4589);
}
}
//We are hardcoding this to 1, but in real world this may be something like a sequence.
OrderID orderNumber = new OrderID("1");
//Id of the report, a unique identifier, once again this will be somthing like a sequence
ExecID execId = new ExecID("1");
//In this case this is a new order with no exception hence mark it as NEW
ExecTransType exectutionTransactioType = new ExecTransType(ExecTransType.NEW);
//This execution report is for confirming a new Order
ExecType purposeOfExecutionReport =new ExecType(ExecType.FILL);
//Represents status of the order, since this order was successful mark it as filled.
OrdStatus orderStatus = new OrdStatus(OrdStatus.FILLED);
//Represents the currencyPair
Symbol symbol = currencyPair;
//Represents side
Side side = message.getSide();
//What is the quantity left for the day, we will take 100 as a hardcoded value, we can also keep a note of this from say limit module.
LeavesQty leavesQty = new LeavesQty(100);
//Total quantity of all the trades booked in this applicaition, here it is hardcoded to be 100.
CumQty cummulativeQuantity = new CumQty(100);
//Average Price, say make it 1.235
AvgPx avgPx = new AvgPx(1.235);
ExecutionReport executionReport = new ExecutionReport(orderNumber,execId, exectutionTransactioType,
purposeOfExecutionReport, orderStatus, symbol, side, leavesQty, cummulativeQuantity, avgPx);
executionReport.set(price);
try {
Session.sendToTarget(executionReport, sessionID);
} catch (SessionNotFound e) {
e.printStackTrace();
}
}
}
[/sourcecode]
Second we will enhance our TestTradeAppInitiator so that it logs the order id which has been sent from our server. Important things to note:
- Extends MessageCracker – which provides callback methods
- Implementation of fromApp cracks the message which invokes onMessage callback
- onMessage is overridden and it retrieves information from execution report.
TestTradeAppInitiator
[sourcecode language=”java” highlight=”19,78,82,83,84,85,86,87,88″]
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;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.MessageCracker;
/***
* The Class TestTradeAppInitiator.
* @author prabhat.jha
*/
public class TestTradeAppInitiator extends MessageCracker 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) {
System.out.println("On logged on");
}
/** (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 {
crack(message, sessionId);
}
@Override
public void onMessage(ExecutionReport message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
System.out.println("Received Execution report from server");
System.out.println("Order Id : " + message.getOrderID().getValue());
System.out.println("Order Status : " + message.getOrdStatus().getValue());
System.out.println("Order Price : " + message.getPrice().getValue());
}
}
[/sourcecode]
Third let’s change our test code to send an order for booking.
TestTradeAppInitiatorApp.java
[sourcecode language=”java” highlight=”77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98″]
package com.mumz.test.fix.initiator;
import java.io.IOException;
import java.util.Scanner;
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.SessionNotFound;
import quickfix.SessionSettings;
import quickfix.SocketInitiator;
import quickfix.field.ClOrdID;
import quickfix.field.HandlInst;
import quickfix.field.OrdType;
import quickfix.field.OrderQty;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.field.TransactTime;
import quickfix.fix42.NewOrderSingle;
/**
* 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:/Prabhat/test/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();
while(!Session.lookupSession(sessionId).isLoggedOn()){
System.out.println("Waiting for login success");
Thread.sleep(1000);
}
System.out.println("Logged In…");
Thread.sleep(5000);
bookSingleOrder(sessionId);
System.out.println("Type to quit");
Scanner scanner = new Scanner(System.in);
scanner.next();
Session.lookupSession(sessionId).disconnect("Done",false);
socketInitiator.stop();
} catch (ConfigError e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void bookSingleOrder(SessionID sessionID){
//In real world this won’t be a hardcoded value rather than a sequence.
ClOrdID orderId = new ClOrdID("1");
//to be executed on the exchange
HandlInst instruction = new HandlInst(HandlInst.AUTOMATED_EXECUTION_ORDER_PRIVATE);
//Since its FX currency pair name
Symbol mainCurrency = new Symbol("EUR/USD");
//Which side buy, sell
Side side = new Side(Side.BUY);
//Time of transaction
TransactTime transactionTime = new TransactTime();
//Type of our order, here we are assuming this is being executed on the exchange
OrdType orderType = new OrdType(OrdType.FOREX_MARKET);
NewOrderSingle newOrderSingle = new NewOrderSingle(orderId,instruction,mainCurrency, side, transactionTime,orderType);
//Quantity
newOrderSingle.set(new OrderQty(100));
try {
Session.sendToTarget(newOrderSingle, sessionID);
} catch (SessionNotFound e) {
e.printStackTrace();
}
}
}
[/sourcecode]
That’s all. I have added comments in the code for better readability, hope you find it useful.
Leave a Reply