package org.marketcetera.quickfix.messagefactory; import org.marketcetera.core.ClassVersion; import org.marketcetera.quickfix.CurrentFIXDataDictionary; import quickfix.FieldNotFound; import quickfix.Message; import quickfix.DataDictionary; import quickfix.field.*; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * @author toli * @version $Id: FIXMessageAugmentor_40.java 16154 2012-07-14 16:34:05Z colin $ */ @ClassVersion("$Id: FIXMessageAugmentor_40.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ public class FIXMessageAugmentor_40 extends NoOpFIXMessageAugmentor { // list of messages that need transactTime protected Set<String> applicableMsgTypes = new HashSet<String>(); public FIXMessageAugmentor_40() { applicableMsgTypes.addAll(Arrays.asList(TT_APPLICABLE_MESSAGE_CODES)); } private static String[] TT_APPLICABLE_MESSAGE_CODES = new String[] { MsgType.ADVERTISEMENT, MsgType.EXECUTION_REPORT, MsgType.ALLOCATION_INSTRUCTION_ACK, MsgType.ALLOCATION_INSTRUCTION }; public Message newOrderSingleAugment(Message inMessage) { inMessage = super.newOrderSingleAugment(inMessage); return handleOnCloseBehaviour(inMessage); } public Message executionReportAugment(Message inMessage) throws FieldNotFound { inMessage.setField(new ExecTransType(ExecTransType.NEW)); return inMessage; } /** If the {@link CxlType} field is defined then set it */ public Message cancelRequestAugment(Message inMessage) { super.cancelRequestAugment(inMessage); DataDictionary dictionary = CurrentFIXDataDictionary.getCurrentFIXDataDictionary().getDictionary(); if(dictionary.isMsgField(dictionary.getMsgType("OrderCancelRequest"), //$NON-NLS-1$ CxlType.FIELD)) { inMessage.setField(new CxlType(CxlType.FULL_REMAINING_QUANTITY)); } return inMessage; } public Message cancelReplaceRequestAugment(Message inMessage) { inMessage = super.cancelReplaceRequestAugment(inMessage); return handleOnCloseBehaviour(inMessage); } public boolean needsTransactTime(Message inMsg) { String theType = null; try { theType = inMsg.getHeader().getString(MsgType.FIELD); } catch (FieldNotFound ex) { return false; } return applicableMsgTypes.contains(theType); } protected Set<String> getApplicableMsgTypes() { return applicableMsgTypes; } /** * MarketOnClose order handling: FIX up to 4.2 doesn't have {@link TimeInForce#AT_THE_CLOSE} * so we need to check if the order is a market order and of {@link OrdType#MARKET} * and modify it appropriately to set the OrdType to be {@link OrdType#MARKET_ON_CLOSE} * * Same goes for {@link OrdType#LIMIT_ON_CLOSE} orders. * * @param inMessage * @return */ private Message handleOnCloseBehaviour(Message inMessage) { try { if((OrdType.MARKET == inMessage.getChar(OrdType.FIELD)) && (TimeInForce.AT_THE_CLOSE == inMessage.getChar(TimeInForce.FIELD))) { inMessage.setField(new OrdType(OrdType.MARKET_ON_CLOSE)); inMessage.setField(new TimeInForce(TimeInForce.DAY)); } else if((OrdType.LIMIT == inMessage.getChar(OrdType.FIELD)) && (TimeInForce.AT_THE_CLOSE == inMessage.getChar(TimeInForce.FIELD))) { inMessage.setField(new OrdType(OrdType.LIMIT_ON_CLOSE)); inMessage.setField(new TimeInForce(TimeInForce.DAY)); } } catch (FieldNotFound fieldNotFound) { return inMessage; } return inMessage; } }