package org.marketcetera.trade; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import java.math.BigDecimal; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.junit.BeforeClass; import org.junit.Test; import org.marketcetera.event.HasFIXMessage; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.quickfix.*; import org.marketcetera.util.misc.ClassVersion; import quickfix.FieldNotFound; import quickfix.Message; import quickfix.field.*; import quickfix.field.converter.BooleanConverter; import quickfix.field.converter.UtcTimestampConverter; import quickfix.fix44.OrderCancelReplaceRequest; /* $License$ */ /** * Tests {@link org.marketcetera.trade.OrderReplace} * * @author anshul@marketcetera.com * @version $Id: OrderReplaceTest.java 16154 2012-07-14 16:34:05Z colin $ * @since 1.0.0 */ @ClassVersion("$Id: OrderReplaceTest.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ public class OrderReplaceTest extends TypesTestBase { /** * Verifies default attributes of objects returned via * {@link Factory#createOrderReplace(ExecutionReport)} * * @throws Exception if there were errors */ @Test public void pojoDefaults() throws Exception { //Null report parameter defaults. OrderReplace order = sFactory.createOrderReplace(null); assertOrderReplace(order, NOT_NULL, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); //Verify toString() doesn't fail order.toString(); //Test an empty report. Message report = createEmptyExecReport(); order = sFactory.createOrderReplace( sFactory.createExecutionReport (report, null, Originator.Server, null, null)); assertOrderReplace(order, NOT_NULL, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); //Verify toString() doesn't fail order.toString(); //Test a report with all values in it String orderID = "clorder-2"; String destOrderID = "brokerd1"; Side side = Side.Buy; BigDecimal orderQty = new BigDecimal("100"); BigDecimal price = new BigDecimal("67.45"); BigDecimal lastPrice = new BigDecimal("23.43"); Instrument instrument = new Equity("IBM"); String account = "what?"; String text = "shaddup"; OrderType orderType = OrderType.Limit; TimeInForce fillOrKill = TimeInForce.FillOrKill; BrokerID cID = new BrokerID("iam"); //Create an exec report. report = createExecReport(orderID, side, orderQty, price, lastPrice, instrument, account, text, orderType, fillOrKill, destOrderID, OrderCapacity.Agency, PositionEffect.Open); //Create the order from the report. order = sFactory.createOrderReplace( sFactory.createExecutionReport (report, cID, Originator.Server, null, null)); assertOrderReplace(order, NOT_NULL, new OrderID(orderID), destOrderID, OrderType.Limit, side, orderQty, price, instrument, instrument.getSecurityType(), fillOrKill, account, text, cID, PositionEffect.Open, OrderCapacity.Agency, null); //Verify toString() doesn't fail order.toString(); assertNotSame(order, sFactory.createOrderReplace( sFactory.createExecutionReport (report, cID, Originator.Server, null, null))); //Test a replace for a partial fill //Create an exec report. report = createExecReport(orderID, side, orderQty, price, lastPrice, instrument, account, text, orderType, fillOrKill, destOrderID, OrderCapacity.Agency, PositionEffect.Open); report.setDecimal(AvgPx.FIELD, new BigDecimal("23.2")); report.setDecimal(CumQty.FIELD, new BigDecimal("10")); report.setDecimal(LeavesQty.FIELD, new BigDecimal("9")); report.setField(new OrdStatus(OrdStatus.PARTIALLY_FILLED)); //Create the order from the report. order = sFactory.createOrderReplace( sFactory.createExecutionReport (report, cID, Originator.Server, null, null)); assertOrderReplace(order, NOT_NULL, new OrderID(orderID), destOrderID, OrderType.Limit, side, orderQty, price, instrument, instrument.getSecurityType(), fillOrKill, account, text, cID, PositionEffect.Open, OrderCapacity.Agency, null); //Verify toString() doesn't fail order.toString(); assertNotSame(order, sFactory.createOrderReplace( sFactory.createExecutionReport (report, cID, Originator.Server, null, null))); } /** * Verifies setters of objects returned via * {@link Factory#createOrderReplace(ExecutionReport)} * * @throws Exception if there were errors */ @Test public void pojoSetters()throws Exception { //Test with non-null exec report OrderReplace order = sFactory.createOrderReplace( sFactory.createExecutionReport (createEmptyExecReport(), null, Originator.Server, null, null)); checkSetters(order); //Test with null exec report order = sFactory.createOrderReplace(null); checkSetters(order); } /** * Verifies conversion of System FIX message to OrderReplace via * {@link org.marketcetera.trade.Factory#createOrderReplace(quickfix.Message, BrokerID)} * * @throws Exception if there were errors. */ @Test public void systemFIXWrap() throws Exception { FIXMessageFactory factory = getSystemMessageFactory(); //An order with no fields set Message msg = factory.getUnderlyingMessageFactory().create( factory.getBeginString(), MsgType.ORDER_CANCEL_REPLACE_REQUEST); OrderReplace order = sFactory.createOrderReplace(msg, null); assertOrderValues(order, null, null); OrderID expectedOrderID = NOT_NULL; assertOrderBaseValues(order, expectedOrderID, null, null, null, null, null, null); assertNROrderValues(order, null, null, null, null, null); assertRelatedOrderValues(order, null, null); //Verify toString() doesn't fail order.toString(); checkSetters(order); //A limit order with all the fields set. BrokerID brokerID = new BrokerID("meh"); OrderID orderID = new OrderID("testOrderID"); String destOrderID = "brokerd1"; BigDecimal qty = new BigDecimal("23434.56989"); BigDecimal price = new BigDecimal("98923.2345"); SecurityType securityType = SecurityType.CommonStock; Instrument instrument = new Equity("IBM"); String account = "nonplus"; String text = "prominus"; PositionEffect positionEffect = PositionEffect.Close; msg = factory.newCancelReplaceFromMessage(createExecReport( orderID.getValue(), Side.Buy, qty, new BigDecimal("45.67"), price, instrument, account, text, OrderType.Limit, TimeInForce.AtTheClose, destOrderID, OrderCapacity.Individual, positionEffect)); order = sFactory.createOrderReplace(msg, brokerID); assertOrderReplace(order, expectedOrderID, orderID, destOrderID, OrderType.Limit, Side.Buy, qty, msg.getField(new Price()).getValue(), instrument, securityType, TimeInForce.AtTheClose, account, text, brokerID, positionEffect, OrderCapacity.Individual, null); //Verify toString() doesn't fail order.toString(); checkSetters(order); //A market order with all fields set. Side side = Side.Sell; OrderType orderType = OrderType.Market; TimeInForce tif = TimeInForce.FillOrKill; OrderCapacity orderCapacity = OrderCapacity.Proprietary; msg = factory.newCancelReplaceFromMessage(createExecReport( orderID.getValue(), side, qty, new BigDecimal("45.67"), null, instrument, account, text, orderType, tif, destOrderID, orderCapacity, positionEffect)); order = sFactory.createOrderReplace(msg, null); assertOrderReplace(order, expectedOrderID, orderID, destOrderID, orderType, side, qty, msg.getField(new Price()).getValue(), instrument, securityType, tif, account, text, null, positionEffect, orderCapacity, null); //Verify toString() doesn't fail order.toString(); checkSetters(order); //Check custom fields //Set fields of every type. Map<String,String> expectedMap = new HashMap<String, String>(); Date date = new Date(); BigDecimal bigDecimal = new BigDecimal("35234.35989"); char charValue = '0'; int intValue = 1; boolean boolValue = false; msg.setField(new ExpireTime(date)); expectedMap.put(String.valueOf(ExpireTime.FIELD), UtcTimestampConverter.convert(date, true)); msg.setField(new AllocQty(bigDecimal)); expectedMap.put(String.valueOf(AllocQty.FIELD), bigDecimal.toString()); msg.setField(new SettlType(String.valueOf(charValue))); expectedMap.put(String.valueOf(SettlType.FIELD), String.valueOf(charValue)); msg.setField(new Product(intValue)); expectedMap.put(String.valueOf(Product.FIELD), String.valueOf(intValue)); msg.setField(new SolicitedFlag(boolValue)); expectedMap.put(String.valueOf(SolicitedFlag.FIELD), BooleanConverter.convert(boolValue)); order = sFactory.createOrderReplace(msg, brokerID); BigDecimal expectedPrice = msg.getField(new Price()).getValue(); assertOrderReplace(order, expectedOrderID, orderID, destOrderID, orderType, side, qty, expectedPrice, instrument, securityType, tif, account, text, brokerID, positionEffect, orderCapacity, expectedMap); } /** * Verifies failures when wrapping a FIX message in an order. * * @throws Exception if there were errors. */ @Test public void systemFIXWrapFailures() throws Exception { final BrokerID brokerID = new BrokerID("meh"); //Null check for message parameter new ExpectedFailure<NullPointerException>() { protected void run() throws Exception { sFactory.createOrderReplace(null, brokerID); } }; final Message msg = createEmptyExecReport(); //Non System FIX Versions. for (String string: new String[]{ FIXDataDictionary.FIX_4_0_BEGIN_STRING, FIXDataDictionary.FIX_4_1_BEGIN_STRING, FIXDataDictionary.FIX_4_2_BEGIN_STRING, FIXDataDictionary.FIX_4_3_BEGIN_STRING, FIXDataDictionary.FIX_4_4_BEGIN_STRING}) { msg.getHeader().setField(new BeginString(string)); new ExpectedFailure<MessageCreationException>( Messages.NON_SYSTEM_FIX_MESSAGE, string){ @Override protected void run() throws Exception { sFactory.createOrderReplace(msg,null); } }; } //No version field msg.getHeader().removeField(BeginString.FIELD); MessageCreationException exception = new ExpectedFailure<MessageCreationException>( Messages.SYSTEM_FIX_MESSAGE_NO_BEGIN_STRING, msg.toString()){ @Override protected void run() throws Exception { sFactory.createOrderReplace(msg,null); } }.getException(); assertNotNull(exception.getCause()); assertTrue(exception.getCause() instanceof FieldNotFound); //Has groups msg.getHeader().setField(new BeginString( FIXDataDictionary.FIX_SYSTEM_BEGIN_STRING)); OrderCancelReplaceRequest.NoAllocs group = new OrderCancelReplaceRequest.NoAllocs(); group.setField(new AllocAccount("blah")); msg.addGroup(group); new ExpectedFailure<MessageCreationException>( Messages.MESSAGE_HAS_GROUPS, group.getFieldTag(), msg.toString()){ @Override protected void run() throws Exception { sFactory.createOrderReplace(msg,null); } }; //Incorrect message type final Message incorrectType = getSystemMessageFactory().newBasicOrder(); new ExpectedFailure<MessageCreationException>( Messages.NOT_CANCEL_REPLACE_ORDER, incorrectType.toString()){ @Override protected void run() throws Exception { sFactory.createOrderReplace(incorrectType, null); } }; } /** * Set the current data dictionary so that various FIXMessageFactory * methods work. * * @throws Exception if there were errors. */ @BeforeClass public static void setupCurrentFIXDictionary() throws Exception { FIXDataDictionaryManager.initialize(FIXVersion.FIX44, FIXVersion.FIX44.getDataDictionaryURL()); CurrentFIXDataDictionary.setCurrentFIXDataDictionary( FIXDataDictionaryManager.getFIXDataDictionary(FIXVersion.FIX44)); } private Message createExecReport(String inOrderID, Side inSide, BigDecimal inQty, BigDecimal inPrice, BigDecimal inLastPrice, Instrument inInstrument, String inAccount, String inText, OrderType inOrderType, TimeInForce inFillOrKill, String inDestOrderID, OrderCapacity inOrderCapacity, PositionEffect inPositionEffect) throws FieldNotFound { Message report = getSystemMessageFactory().newExecutionReport( inDestOrderID, inOrderID, "exec-2", OrderStatus.New.getFIXValue(), inSide.getFIXValue(), inQty, inPrice, new BigDecimal("23.53"), inLastPrice, new BigDecimal("98.34"), new BigDecimal("34.32"), inInstrument, inAccount, inText); report.setField(new OrdType(inOrderType.getFIXValue())); report.setField(new quickfix.field.TimeInForce( inFillOrKill.getFIXValue())); report.setField(new quickfix.field.OrderCapacity( inOrderCapacity.getFIXValue())); report.setField(new quickfix.field.PositionEffect( inPositionEffect.getFIXValue())); return report; } private void checkSetters(OrderReplace inOrder) { checkOrderSetters(inOrder); checkOrderBaseSetters(inOrder); checkNRSetters(inOrder); checkRelatedOrderSetters(inOrder); } /** verify custom fields are preserved, and that nothing else is added from the execution report */ @Test public void testSecurityExchangePreserved() throws Exception { Message erMsg = FIXVersion.FIX42.getMessageFactory().newExecutionReport("orderID", "clOrderID", "execID", //$NON-NLS-1$ OrdStatus.NEW, Side.Buy.getFIXValue(), new BigDecimal("10"), new BigDecimal("100.23"), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, new Equity("IBM"), //$NON-NLS-1$ "accountName", null); //$NON-NLS-1$ erMsg.setString(SecurityExchange.FIELD, "box"); ExecutionReport er = sFactory.createExecutionReport(erMsg, null, Originator.Server, null, null); OrderReplace replace = sFactory.createOrderReplace(er); assertNotNull("didn't get custom fields", replace.getCustomFields()); // basically, should only have 1 field: SecurityExchange assertEquals("has extra fields: "+ Arrays.toString(replace.getCustomFields().keySet().toArray()), 1, replace.getCustomFields().size()); } @Test /** Create ER for previous order that has OrderID of 12345 * Set an OrigClOrdID on it of 12222 * Create a replace form this ER, the OrigClOrdID should be 12345, not the "very original" of 12222 */ public void testCreateOrderReplace() throws Exception { Message erMsg = FIXVersion.FIX42.getMessageFactory().newExecutionReport("7600", "12345", "execID", //$NON-NLS-1$ OrdStatus.NEW, Side.Buy.getFIXValue(), new BigDecimal("10"), new BigDecimal("100.23"), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, new Equity("IBM"), //$NON-NLS-1$ "accountName", null); //$NON-NLS-1$ erMsg.setString(OrigClOrdID.FIELD, "12222"); erMsg.setInt(HandlInst.FIELD, HandlInst.AUTOMATED_EXECUTION_ORDER_PUBLIC); ExecutionReport er = Factory.getInstance().createExecutionReport(erMsg, new BrokerID("broker"), Originator.Server, new UserID(7600L), new UserID(7500L)); assertEquals("12222", er.getOriginalOrderID().getValue()); assertEquals("12222", ((HasFIXMessage) er).getMessage().getString(OrigClOrdID.FIELD)); // now create a replace, shouldn't have the "very original" order id of 12222 OrderReplace replace = Factory.getInstance().createOrderReplace(er); assertEquals("12345", replace.getOriginalOrderID().getValue()); assertEquals("shouldn have only 1 custom fields", 1, replace.getCustomFields().size()); assertNotNull("HandlInst not set", replace.getCustomFields().get(HandlInst.FIELD+"")); } }