Java tutorial
/* * $Header: //depot/FXCM/New_CurrentSystem/Main/FXCM_SRC/TRADING_SDK/tradestation/src/main/fxts/stations/transport/tradingapi/processors/ExecutionReportProcessor.java#6 $ * * Copyright (c) 2008 FXCM, LLC. * 32 Old Slip, New York NY, 10005 USA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: Andre Mermegas * Created: Nov 13, 2006 10:41:51 AM * * $History: $ */ package fxts.stations.transport.tradingapi.processors; import com.fxcm.external.api.util.MessageAnalyzer; import com.fxcm.fix.FXCMOrdStatusFactory; import com.fxcm.fix.FXCMOrdTypeFactory; import com.fxcm.fix.IFixDefs; import com.fxcm.fix.NotDefinedException; import com.fxcm.fix.OrdStatusFactory; import com.fxcm.fix.SideFactory; import com.fxcm.fix.trade.ExecutionReport; import com.fxcm.messaging.ITransportable; import com.fxcm.messaging.util.ThreadSafeNumberFormat; import fxts.stations.datatypes.Message; import fxts.stations.datatypes.Order; import fxts.stations.datatypes.Position; import fxts.stations.datatypes.Side; import fxts.stations.trader.TradeApp; import fxts.stations.trader.ui.dialogs.MessageDialog; import fxts.stations.transport.ITradeDesk; import fxts.stations.transport.tradingapi.Liaison; import fxts.stations.transport.tradingapi.TradingServerSession; import fxts.stations.transport.tradingapi.resources.OraCodeFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import java.text.DecimalFormat; import java.util.Date; import java.util.Map; /** * */ public class ExecutionReportProcessor implements IProcessor { private static final DecimalFormat FORMAT = new ThreadSafeNumberFormat().getInstance(); private final Log mLogger; public ExecutionReportProcessor() { mLogger = LogFactory.getLog(ExecutionReportProcessor.class); } private void doDelete(ExecutionReport aExeRpt) { ITradeDesk tradeDesk = Liaison.getInstance().getTradeDesk(); tradeDesk.syncServerTime(aExeRpt.getTransactTime().toDate()); Map<String, Order> orderMap = TradingServerSession.getInstance().getStopLimitOrderMap(); Order order = orderMap.get(aExeRpt.getOrderID()); if (order == null) { tradeDesk.removeOrder(aExeRpt.getOrderID()); } else { Position openPosition = tradeDesk.getOpenPosition(order.getTradeId()); Order openOrder = tradeDesk.getOrderByTradeId(order.getTradeId()); if (openPosition != null) { Position position = tradeDesk.getOpenPosition(order.getTradeId()); if (order.isLimit()) { position.setLimit(0); } else if (order.isStop() || order.isTrailingStop()) { position.setStop(0); position.setTrailStop(0); } tradeDesk.updateOpenPosition(position); } else if (openOrder != null) { openOrder.setCustomText(order.getCustomText()); if (order.isLimit()) { openOrder.setLimitRate(0); } else if (order.isStop() || order.isTrailingStop()) { openOrder.setStopRate(0); openOrder.setTrailStop(0); } tradeDesk.updateOrder(openOrder); } } } private void doNewOrder(ExecutionReport aExeRpt) { ITradeDesk tradeDesk = Liaison.getInstance().getTradeDesk(); Map<String, Order> orderMap = TradingServerSession.getInstance().getStopLimitOrderMap(); if (aExeRpt.getTotNumReports() > 0 || aExeRpt.getMassStatusReqID() == null) { Order newOrder = fillOrder(aExeRpt); // go through order map to see if a stop / limit came before the entry order in // processing stream and set it. for (Order order : orderMap.values()) { if (order.getTradeId() != null && order.getTradeId().equals(aExeRpt.getFXCMPosID())) { if (order.isLimit()) { newOrder.setLimitRate(order.getOrderRate()); newOrder.setLimitOrderID(order.getOrderID()); } else if (order.isStop()) { newOrder.setStopRate(order.getOrderRate()); newOrder.setStopOrderID(order.getOrderID()); } } } tradeDesk.addOrder(newOrder); } } private boolean doReject(ExecutionReport aExeRpt) { if (isDisconnect(aExeRpt)) { JOptionPane.showMessageDialog(TradeApp.getInst().getMainFrame(), aExeRpt.getFXCMErrorDetails(), "Problem with your order..please reconnect.", JOptionPane.ERROR_MESSAGE); TradingServerSession.getInstance().logout(); } else { if (aExeRpt.getFXCMOrdStatus() != FXCMOrdStatusFactory.REQUOTED) { final String fxcmErrorDetails = aExeRpt.getFXCMErrorDetails(); mLogger.debug("fxcmErrorDetails = " + fxcmErrorDetails); SwingUtilities.invokeLater(new Runnable() { public void run() { Message m = new Message(new Date(), "FXCM", "Problem with your order..", OraCodeFactory.toMessage(fxcmErrorDetails)); MessageDialog dialog = new MessageDialog(TradeApp.getInst().getMainFrame()); Liaison.getInstance().getTradeDesk().addMessage(m); dialog.setMessage(m); dialog.showModal(); } }); Liaison.getInstance().getTradeDesk().removeOrder(aExeRpt.getOrderID()); } } return false; } private void doStopLimit(ExecutionReport aExeRpt) { ITradeDesk tradeDesk = Liaison.getInstance().getTradeDesk(); Map<String, Order> orderMap = TradingServerSession.getInstance().getStopLimitOrderMap(); Position openPosition = tradeDesk.getOpenPosition(String.valueOf(aExeRpt.getFXCMPosID())); Order openOrder = tradeDesk.getOrderByTradeId(String.valueOf(aExeRpt.getFXCMPosID())); orderMap.put(aExeRpt.getOrderID(), fillOrder(aExeRpt)); if (openPosition != null) { //we got a stop/limit order if (MessageAnalyzer.isLimitOrder(aExeRpt)) { openPosition.setLimit(aExeRpt.getPrice()); openPosition.setLimitOrderID(aExeRpt.getOrderID()); } else if (MessageAnalyzer.isStopOrder(aExeRpt)) { openPosition.setStop(aExeRpt.getStopPx()); openPosition.setStopOrderID(aExeRpt.getOrderID()); openPosition.setTrailStop(0); openPosition.setStopMove(0); } else if (MessageAnalyzer.isTrailingStopCloseOrder(aExeRpt)) { if (aExeRpt.getFXCMOrdType() == FXCMOrdTypeFactory.TRAILING_STOP) { openPosition.setTrailingRate(aExeRpt.getLastPx()); if (aExeRpt.getPegInstructions().getPegOffsetValue() > 0) { openPosition.setStop(aExeRpt.getPegInstructions().getPegOffsetValue()); } else { //handle case where it doesnt transition from trail stop back to regular stop openPosition.setStop(aExeRpt.getLastPx()); } openPosition.setTrailStop(aExeRpt.getPegInstructions().getFXCMPegFluctuatePts()); openPosition.setStopMove(aExeRpt.getPegInstructions().getFXCMPegFluctuatePts()); // initialize the stopmove to static trailing stop number openPosition.setStopOrderID(aExeRpt.getOrderID()); } else if (aExeRpt.getFXCMOrdType() == FXCMOrdTypeFactory.TRAILING_LIMIT) { openPosition.setLimit(aExeRpt.getPrice()); openPosition.setLimitOrderID(aExeRpt.getOrderID()); } } tradeDesk.updateOpenPosition(openPosition); } else if (openOrder != null) { if (MessageAnalyzer.isLimitOrder(aExeRpt)) { if (aExeRpt.getPrice() == 0) { openOrder.setLimitRate(aExeRpt.getPegInstructions().getPegOffsetValue()); } else { openOrder.setLimitRate(aExeRpt.getPrice()); } openOrder.setLimitOrderID(aExeRpt.getOrderID()); } else if (MessageAnalyzer.isStopOrder(aExeRpt)) { if (aExeRpt.getPrice() == 0) { openOrder.setStopRate(aExeRpt.getPegInstructions().getPegOffsetValue()); } else { openOrder.setStopRate(aExeRpt.getPrice()); } openOrder.setStopOrderID(aExeRpt.getOrderID()); } else if (MessageAnalyzer.isTrailingStopCloseOrder(aExeRpt)) { openOrder.setOfferRate(aExeRpt.getLastPx()); if (aExeRpt.getPegInstructions().getPegOffsetValue() > 0) { openOrder.setStopRate(aExeRpt.getPegInstructions().getPegOffsetValue()); } else { //handle case where it doesnt transition from trail stop back to regular stop openOrder.setStopRate(aExeRpt.getPrice()); } openOrder.setTrailStop(aExeRpt.getPegInstructions().getFXCMPegFluctuatePts()); openOrder.setStopOrderID(aExeRpt.getOrderID()); } tradeDesk.updateOrder(openOrder); } } private void doUpdateOrder(ExecutionReport aExeRpt) { ITradeDesk tradeDesk = Liaison.getInstance().getTradeDesk(); Order openOrder = tradeDesk.getOrderByTradeId(String.valueOf(aExeRpt.getFXCMPosID())); if (openOrder == null) { openOrder = tradeDesk.getOrder(aExeRpt.getOrderID()); } if (openOrder != null) { openOrder.setCustomText(aExeRpt.getSecondaryClOrdID()); openOrder.setOrderRate(aExeRpt.getPrice()); openOrder.setStatus(aExeRpt.getFXCMOrdStatus().getLabel()); openOrder.setType(aExeRpt.getFXCMOrdType().getCode()); openOrder.setAmount((long) aExeRpt.getOrderQty()); openOrder.setTime(aExeRpt.getTransactTime().toDate()); tradeDesk.updateOrder(openOrder); } } private Order fillOrder(ExecutionReport aExeRpt) { Order order = new Order(); order.setCustomText(aExeRpt.getSecondaryClOrdID()); order.setAccountID(String.valueOf(aExeRpt.getParties().getFXCMAcctID())); order.setAccount(aExeRpt.getAccount()); order.setAmount((long) aExeRpt.getOrderQty()); try { order.setCurrency(aExeRpt.getInstrument().getSymbol()); } catch (NotDefinedException e) { e.printStackTrace(); } order.setCurrencyTradable(true); order.setOrderID(aExeRpt.getOrderID()); order.setOrdType(aExeRpt.getOrdType().getCode()); order.setStop(MessageAnalyzer.isStopOrder(aExeRpt)); order.setLimit(MessageAnalyzer.isLimitOrder(aExeRpt)); order.setTrailingStop(MessageAnalyzer.isTrailingStopCloseOrder(aExeRpt)); order.setTrailStop(aExeRpt.getPegInstructions().getFXCMPegFluctuatePts()); if (aExeRpt.getSide() == SideFactory.BUY) { order.setSide(Side.BUY); } else { order.setSide(Side.SELL); } order.setOrderRate(aExeRpt.getPrice()); order.setStatus(aExeRpt.getFXCMOrdStatus().getLabel()); order.setType(aExeRpt.getFXCMOrdType().getCode()); order.setStage('O'); order.setTime(aExeRpt.getTransactTime().toDate()); order.setTradeId(String.valueOf(aExeRpt.getFXCMPosID())); return order; } private boolean isAnyStopLimit(ExecutionReport aExeRpt) { return MessageAnalyzer.isStopLimitCloseOrder(aExeRpt) || MessageAnalyzer.isTrailingStopCloseOrder(aExeRpt); } private boolean isDelete(ExecutionReport aExeRpt) { return aExeRpt.getFXCMOrdStatus() != null && aExeRpt.getFXCMOrdStatus().isDeleted(); } private boolean isDisconnect(ExecutionReport aExeRpt) { return aExeRpt.getFXCMErrorDetails() != null && aExeRpt.getFXCMErrorDetails().indexOf("Connection lost, please close this window and login") > 0; } private boolean isNewOrder(ExecutionReport aExeRpt) { return Liaison.getInstance().getTradeDesk().getOrder(aExeRpt.getOrderID()) == null; } private boolean isReject(ExecutionReport aExeRpt) { return aExeRpt.getOrdStatus() == OrdStatusFactory.REJECTED && IFixDefs.FXCMREQUESTREJECTREASON_DATA_NOT_FOUND != aExeRpt.getFXCMRequestRejectReason(); } private boolean isUpdateOrder(ExecutionReport aExeRpt) { return Liaison.getInstance().getTradeDesk().getOrder(aExeRpt.getOrderID()) != null; } public void process(ITransportable aTransportable) { ExecutionReport exe = (ExecutionReport) aTransportable; mLogger.debug("client: inc execution report = " + exe); mLogger.debug("********************************************"); mLogger.debug(exe.getRequestID() + " :: " + exe.getOrderID()); mLogger.debug("ListID = " + exe.getListID()); mLogger.debug("ExpireTime = " + exe.getExpireTime()); mLogger.debug("EffectiveTime = " + exe.getEffectiveTime()); mLogger.debug("OrdType = " + exe.getOrdType()); mLogger.debug("Side = " + exe.getSide()); mLogger.debug("TimeInforce = " + exe.getTimeInForce()); mLogger.debug("ExpireTime = " + exe.getExpireTime()); mLogger.debug("FXCMOrdType = " + exe.getFXCMOrdType()); mLogger.debug("ContingencyID = " + exe.getFXCMContingencyID()); mLogger.debug("SecondaryClOrdID = " + exe.getSecondaryClOrdID()); mLogger.debug("FXCMPosID = " + exe.getFXCMPosID()); mLogger.debug("OrigClOrdID = " + exe.getOrigClOrdID()); mLogger.debug("Price = " + exe.getPrice()); mLogger.debug("StopPx = " + exe.getStopPx()); mLogger.debug("TransactTime = " + exe.getTransactTime()); mLogger.debug("ExecType = " + exe.getExecType()); mLogger.debug("FXCMOrdStatus = " + exe.getFXCMOrdStatus()); mLogger.debug("OrdStatus = " + exe.getOrdStatus()); mLogger.debug("OrderQty = " + FORMAT.format(exe.getOrderQty())); mLogger.debug("CumQty = " + FORMAT.format(exe.getCumQty())); mLogger.debug("LastQty = " + FORMAT.format(exe.getLastQty())); mLogger.debug("LeavesQty = " + FORMAT.format(exe.getLeavesQty())); mLogger.debug("********************************************"); if (isReject(exe)) { doReject(exe); } else if (isDelete(exe)) { doDelete(exe); } else if (isAnyStopLimit(exe)) { doStopLimit(exe); } else if (isUpdateOrder(exe)) { doUpdateOrder(exe); } else if (isNewOrder(exe)) { doNewOrder(exe); } if (requiresNotification(exe)) { TradingServerSession.getInstance().doneProcessing(); } } private boolean requiresNotification(ExecutionReport aExeRpt) { return aExeRpt.isLastRptRequested() && TradingServerSession.getInstance().getRequestID().equals(aExeRpt.getMassStatusReqID()); } }