package org.marketcetera.orderloader.system;
import org.marketcetera.util.misc.ClassVersion;
import org.marketcetera.util.log.I18NBoundMessage1P;
import org.marketcetera.util.log.I18NBoundMessage2P;
import org.marketcetera.core.LoggerConfiguration;
import org.marketcetera.orderloader.*;
import org.marketcetera.orderloader.Messages;
import static org.marketcetera.orderloader.system.SystemProcessor.*;
import static org.marketcetera.orderloader.system.InstrumentFromRow.*;
import static org.marketcetera.orderloader.system.OptionFromRow.*;
import org.marketcetera.trade.*;
import org.marketcetera.module.ExpectedFailure;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.*;
import java.math.BigDecimal;
/* $License$ */
/**
* SystemProcessorTest
*
* @author anshul@marketcetera.com
* @version $Id: SystemProcessorTest.java 16154 2012-07-14 16:34:05Z colin $
* @since 1.0.0
*/
@ClassVersion("$Id: SystemProcessorTest.java 16154 2012-07-14 16:34:05Z colin $")
public class SystemProcessorTest {
@BeforeClass
public static void setupLogger() {
LoggerConfiguration.logSetup();
}
@Test
public void constructor() throws Exception {
//Order Processor cannot be null
new ExpectedFailure<NullPointerException>() {
protected void run() throws Exception {
new SystemProcessor(null, new BrokerID("what"));
}
};
//can supply null brokerID ID
new SystemProcessor(mProcessor, null);
//Verify initial state
OrderParserTest.assertProcessor(create(null), 0, 0);
}
@Test
public void missingRequiredHeaders() throws Exception {
//Order Type
new ExpectedFailure<OrderParsingException>(
Messages.MISSING_REQUIRED_FIELD, FIELD_ORDER_TYPE){
protected void run() throws Exception {
create(null).initialize(FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL);
}
};
//Quantity
new ExpectedFailure<OrderParsingException>(
Messages.MISSING_REQUIRED_FIELD, FIELD_QUANTITY){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, FIELD_SIDE, FIELD_SYMBOL);
}
};
//Side
new ExpectedFailure<OrderParsingException>(
Messages.MISSING_REQUIRED_FIELD, FIELD_SIDE){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, FIELD_QUANTITY, FIELD_SYMBOL);
}
};
//Symbol
new ExpectedFailure<OrderParsingException>(
Messages.MISSING_REQUIRED_FIELD, FIELD_SYMBOL){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, FIELD_QUANTITY, FIELD_SIDE);
}
};
//verify success when all fields are supplied
create(null).initialize(FIELD_ORDER_TYPE, FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL);
}
@Test
public void duplicateHeaders() throws Exception {
//Duplicate order type
new ExpectedFailure<OrderParsingException>(
Messages.DUPLICATE_HEADER, FIELD_ORDER_TYPE, 0, 4){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL, FIELD_ORDER_TYPE);
}
};
//Duplicate custom field
new ExpectedFailure<OrderParsingException>(
Messages.DUPLICATE_HEADER, "9001", 1, 5){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, "9001", FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL, "9001");
}
};
//Duplicate custom field with same numeric value but different string value
new ExpectedFailure<OrderParsingException>(
Messages.DUPLICATE_HEADER, "009001", 1, 5){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, "9001", FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL, "009001");
}
};
}
@Test
public void unknownHeader() throws Exception {
new ExpectedFailure<OrderParsingException>(
Messages.INVALID_CUSTOM_HEADER, "What", 1){
protected void run() throws Exception {
create(null).initialize(FIELD_ORDER_TYPE, "What", FIELD_QUANTITY, FIELD_SIDE, FIELD_SYMBOL);
}
};
}
/**
* Tests order parsing with minimal set of fields
*
* @throws Exception if there were errors.
*/
@Test
public void minimalFields() throws Exception {
RowProcessor processor = create(null);
processor.initialize(FIELD_SIDE, FIELD_SYMBOL, FIELD_ORDER_TYPE, FIELD_QUANTITY);
processor.processOrder(0, Side.Buy.toString(), "ubm", OrderType.Market.toString(), "34.34");
processor.processOrder(1, Side.Sell.toString(), "nubm", OrderType.Limit.toString(), "12.23");
OrderParserTest.assertProcessor(processor, 2, 0);
List<Order> list = mProcessor.getOrders();
assertEquals(2, list.size());
TypesTestBase.assertOrderSingle((OrderSingle)list.get(0),
TypesTestBase.NOT_NULL, Side.Buy, new BigDecimal("34.34"),
null, null, OrderType.Market, new Equity("ubm"), SecurityType.CommonStock, null,
null, null, null, null, null);
TypesTestBase.assertOrderSingle((OrderSingle)list.get(1),
TypesTestBase.NOT_NULL, Side.Sell, new BigDecimal("12.23"),
null, null, OrderType.Limit, new Equity("nubm"), SecurityType.CommonStock, null,
null, null, null, null, null);
}
/**
* Test custom fields.
*
* @throws Exception if there were errors.
*/
@Test
public void customFields() throws Exception {
RowProcessor processor = create(null);
processor.initialize(FIELD_SIDE, FIELD_SYMBOL, FIELD_ORDER_TYPE,
FIELD_QUANTITY, "4001", "5001");
processor.processOrder(0, Side.SellShort.toString(), "zoog",
OrderType.Market.toString(), "1", "yes", "no");
processor.processOrder(1, Side.SellShort.toString(), "zoo",
OrderType.Market.toString(), "10", "", "no");
processor.processOrder(2, Side.Sell.toString(), "moog",
OrderType.Limit.toString(), "10", "moo", null);
OrderParserTest.assertProcessor(processor, 3, 0);
List<Order> list = mProcessor.getOrders();
assertEquals(3, list.size());
Map<String,String> map = new HashMap<String,String>();
map.put("4001", "yes");
map.put("5001", "no");
TypesTestBase.assertOrderSingle((OrderSingle)list.get(0),
TypesTestBase.NOT_NULL, Side.SellShort, BigDecimal.ONE,
null, null, OrderType.Market, new Equity("zoog"), SecurityType.CommonStock, null,
null, null, null, null, map);
map.clear();
map.put("4001", "");
map.put("5001", "no");
TypesTestBase.assertOrderSingle((OrderSingle)list.get(1),
TypesTestBase.NOT_NULL, Side.SellShort, BigDecimal.TEN,
null, null, OrderType.Market, new Equity("zoo"), SecurityType.CommonStock, null,
null, null, null, null, map);
map.clear();
map.put("4001", "moo");
map.put("5001", null);
TypesTestBase.assertOrderSingle((OrderSingle)list.get(2),
TypesTestBase.NOT_NULL, Side.Sell, BigDecimal.TEN,
null, null, OrderType.Limit, new Equity("moog"), SecurityType.CommonStock, null,
null, null, null, null, map);
}
@Test
public void allFields() throws Exception {
BrokerID brokerID = new BrokerID("broke");
RowProcessor processor = create(brokerID);
processor.initialize(FIELD_ACCOUNT, FIELD_ORDER_CAPACITY,
FIELD_ORDER_TYPE, FIELD_POSITION_EFFECT, "666",
FIELD_PRICE, FIELD_QUANTITY, FIELD_SECURITY_TYPE,
FIELD_SIDE, FIELD_SYMBOL, FIELD_TIME_IN_FORCE,
FIELD_EXPIRY, FIELD_STRIKE_PRICE,
FIELD_OPTION_TYPE, "2112");
processor.processOrder(1, "mine", "",
OrderType.Market.toString(), "", "beast", "", "3.33",
SecurityType.CommonStock.toString(),
Side.SellShortExempt.toString(), "vsft",
TimeInForce.Day.toString(), null, null, null, "steel");
//fails due to incorrect price value
String[] failRow1 = {"mine", "",
OrderType.Market.toString(), "", "beast", "nice", "3.33",
SecurityType.CommonStock.toString(),
Side.SellShortExempt.toString(), "vsft",
TimeInForce.Day.toString(), null, null, null, "steel"};
processor.processOrder(2, failRow1);
processor.processOrder(3, "yours", OrderCapacity.Individual.toString(),
OrderType.Limit.toString(), PositionEffect.Close.toString(),
"number", "22.2", "9.99",
SecurityType.Option.toString(),
Side.Buy.toString(), "soft",
TimeInForce.FillOrKill.toString(), "20101010", "12.34", "Call", "of");
//fails due to incorrect OrderCapacity Value
String[] failRow2 = {"yours", OrderCapacity.Unknown.toString(),
OrderType.Limit.toString(), PositionEffect.Close.toString(),
"number", "22.2", "9.99",
SecurityType.Option.toString(),
Side.Buy.toString(), "soft",
TimeInForce.Day.toString(), "20101010", "12.34", "Call", "of"};
processor.processOrder(4, failRow2);
//fails due to incorrect OptionType Value
String[] failRow3 = {"yours", OrderCapacity.Agency.toString(),
OrderType.Limit.toString(), PositionEffect.Close.toString(),
"number", "22.2", "9.99",
SecurityType.Option.toString(),
Side.Buy.toString(), "soft",
TimeInForce.Day.toString(), "20101010", "12.34", "Puff", "of"};
processor.processOrder(5, failRow3);
//fails due to incorrect strike price Value
String[] failRow4 = {"yours", OrderCapacity.Agency.toString(),
OrderType.Limit.toString(), PositionEffect.Close.toString(),
"number", "22.2", "9.99",
SecurityType.Option.toString(),
Side.Buy.toString(), "soft",
TimeInForce.Day.toString(), "20101010", "nostrike", "Call", "of"};
processor.processOrder(6, failRow4);
OrderParserTest.assertProcessor(processor, 2, 4);
//Verify successful orders
List<Order> list = mProcessor.getOrders();
assertEquals(2, list.size());
Map<String,String> map = new HashMap<String,String>();
map.put("666", "beast");
map.put("2112", "steel");
TypesTestBase.assertOrderSingle((OrderSingle)list.get(0),
TypesTestBase.NOT_NULL, Side.SellShortExempt,
new BigDecimal("3.33"), null, TimeInForce.Day, OrderType.Market,
new Equity("vsft"),
SecurityType.CommonStock, "mine", null, null, null, brokerID, map);
map.clear();
map.put("666", "number");
map.put("2112", "of");
TypesTestBase.assertOrderSingle((OrderSingle)list.get(1),
TypesTestBase.NOT_NULL, Side.Buy, new BigDecimal("9.99"),
new BigDecimal("22.2"), TimeInForce.FillOrKill, OrderType.Limit,
new Option("soft", "20101010", new BigDecimal("12.34"), OptionType.Call),
SecurityType.Option, "yours", null, OrderCapacity.Individual,
PositionEffect.Close, brokerID, map);
//Verify failures.
List<FailedOrderInfo> failed = processor.getFailedOrders();
assertEquals(4, failed.size());
FailedOrderInfo info = failed.get(0);
assertEquals(2, info.getIndex());
assertArrayEquals(failRow1, info.getRow());
assertEquals(new I18NBoundMessage1P(Messages.INVALID_PRICE_VALUE,
"nice"), ((OrderParsingException)info.getException()).
getI18NBoundMessage());
info = failed.get(1);
assertEquals(4, info.getIndex());
assertArrayEquals(failRow2, info.getRow());
//Valid Values
Set<OrderCapacity> validValues = EnumSet.allOf(OrderCapacity.class);
validValues.remove(OrderCapacity.Unknown);
assertEquals(new I18NBoundMessage2P(Messages.INVALID_ORDER_CAPACITY,
OrderCapacity.Unknown.toString(), validValues.toString()),
((OrderParsingException)info.getException()).
getI18NBoundMessage());
info = failed.get(2);
assertEquals(5, info.getIndex());
assertArrayEquals(failRow3, info.getRow());
Set<OptionType> validOpTypes = EnumSet.allOf(OptionType.class);
validOpTypes.remove(OptionType.Unknown);
assertEquals(new I18NBoundMessage2P(Messages.INVALID_OPTION_TYPE,
"Puff", validOpTypes.toString()),
((OrderParsingException)info.getException()).
getI18NBoundMessage());
info = failed.get(3);
assertEquals(6, info.getIndex());
assertArrayEquals(failRow4, info.getRow());
assertEquals(new I18NBoundMessage1P(Messages.INVALID_STRIKE_PRICE_VALUE,
"nostrike"),
((OrderParsingException)info.getException()).
getI18NBoundMessage());
}
private RowProcessor create(BrokerID inBrokerID) throws Exception {
mProcessor.getOrders().clear();
return new SystemProcessor(mProcessor, inBrokerID);
}
private final MockOrderProcessor mProcessor = new MockOrderProcessor();
}