package org.marketcetera.event.impl;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Before;
import org.junit.Test;
import org.marketcetera.event.*;
import org.marketcetera.event.Messages;
import org.marketcetera.marketdata.DateUtils;
import org.marketcetera.module.ExpectedFailure;
import org.marketcetera.options.ExpirationType;
import org.marketcetera.trade.*;
import org.marketcetera.util.test.EqualityAssert;
/* $License$ */
/**
* Tests {@link TradeEventBuilder} and {@link TradeEvent} implementations.
*
* @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a>
* @version $Id: TradeEventTest.java 16154 2012-07-14 16:34:05Z colin $
* @since 2.0.0
*/
public class TradeEventTest
implements Messages
{
/**
* Run before each test.
*
* @throws Exception if an unexpected error occurs
*/
@Before
public void setup()
throws Exception
{
instrument = equity;
useInstrument = false;
}
/**
* Tests the ability to create various types of {@link TradeEventBuilder} objects.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void builderTypes()
throws Exception
{
instrument = option; useInstrument = false;
verify(setDefaults(getBuilder()));
instrument = option; useInstrument = true;
verify(setDefaults(getBuilder()));
instrument = equity; useInstrument = false;
verify(setDefaults(getBuilder()));
instrument = equity; useInstrument = true;
verify(setDefaults(getBuilder()));
instrument = future; useInstrument = false;
verify(setDefaults(getBuilder()));
instrument = future; useInstrument = true;
verify(setDefaults(getBuilder()));
// create a new kind of instrument
new ExpectedFailure<UnsupportedOperationException>() {
@Override
protected void run()
throws Exception
{
TradeEventBuilder.tradeEvent(EventTestBase.generateUnsupportedInstrument());
}
};
}
/**
* Tests that the builder checks the instrument type when creating a builder.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void wrongInstrumentType()
throws Exception
{
// create equity builders and supply an option instrument
new ExpectedFailure<IllegalArgumentException>(VALIDATION_EQUITY_REQUIRED.getText()) {
@Override
protected void run()
throws Exception
{
setDefaults(TradeEventBuilder.equityTradeEvent()).withInstrument(option).create();
}
};
verify(setDefaults(TradeEventBuilder.equityTradeEvent()).withInstrument(equity));
// now check option builders with an equity instrument
new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) {
@Override
protected void run()
throws Exception
{
setDefaults(TradeEventBuilder.optionTradeEvent()).withInstrument(equity).create();
}
};
verify(setDefaults(TradeEventBuilder.optionTradeEvent()).withInstrument(option));
// now check future builders with an equity instrument
new ExpectedFailure<IllegalArgumentException>(VALIDATION_FUTURE_REQUIRED.getText()) {
@Override
protected void run()
throws Exception
{
setDefaults(TradeEventBuilder.futureTradeEvent()).withInstrument(equity).create();
}
};
verify(setDefaults(TradeEventBuilder.futureTradeEvent()).withInstrument(future));
}
/**
* Tests {@link TradeEventBuilder#hasDeliverable(boolean)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void hasDeliverable()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
builder.hasDeliverable(false);
assertEquals(false,
builder.getOption().hasDeliverable());
builder.hasDeliverable(true);
assertEquals(true,
builder.getOption().hasDeliverable());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withExchange(String)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withExchange()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
String exchange = null;
builder.withExchange(exchange);
assertEquals(exchange,
builder.getMarketData().getExchange());
exchange = "";
builder.withExchange(exchange);
assertEquals(exchange,
builder.getMarketData().getExchange());
exchange = "exchange";
builder.withExchange(exchange);
assertEquals(exchange,
builder.getMarketData().getExchange());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withExpirationType(ExpirationType)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withExpirationType()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
builder.withExpirationType(null);
assertNull(builder.getOption().getExpirationType());
for(ExpirationType expirationType : ExpirationType.values()) {
builder.withExpirationType(expirationType);
assertEquals(expirationType,
builder.getOption().getExpirationType());
}
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withProviderSymbol(String)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withProviderSymbol()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
String symbol = null;
builder.withProviderSymbol(symbol);
assertEquals(symbol,
builder.getOption().getProviderSymbol());
assertEquals(symbol,
builder.getFuture().getProviderSymbol());
symbol = "";
builder.withProviderSymbol(symbol);
assertEquals(symbol,
builder.getOption().getProviderSymbol());
assertEquals(symbol,
builder.getFuture().getProviderSymbol());
symbol = "MSQ/W/X";
builder.withProviderSymbol(symbol);
assertEquals(symbol,
builder.getOption().getProviderSymbol());
assertEquals(symbol,
builder.getFuture().getProviderSymbol());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withEventType(org.marketcetera.event.EventType)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withEventType()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
EventType type = null;
builder.withEventType(type);
assertEquals(type,
builder.getMarketData().getEventType());
type = EventType.UNKNOWN;
builder.withEventType(type);
assertEquals(type,
builder.getMarketData().getEventType());
type = EventType.SNAPSHOT_PART;
builder.withEventType(type);
assertEquals(type,
builder.getMarketData().getEventType());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withContractSize(int)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withContractSize()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
builder.withContractSize(Integer.MIN_VALUE);
assertEquals(Integer.MIN_VALUE,
builder.getFuture().getContractSize());
builder.withContractSize(0);
assertEquals(0,
builder.getFuture().getContractSize());
builder.withContractSize(Integer.MAX_VALUE);
assertEquals(Integer.MAX_VALUE,
builder.getFuture().getContractSize());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withInstrument(Instrument)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withInstrument()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
instrument = null;
builder.withInstrument(instrument);
assertEquals(instrument,
builder.getMarketData().getInstrument());
assertEquals(instrument,
builder.getMarketData().getInstrumentAsString());
assertEquals(instrument,
builder.getOption().getInstrument());
instrument = equity;
builder.withInstrument(instrument);
assertEquals(instrument,
builder.getMarketData().getInstrument());
assertEquals(instrument.getSymbol(),
builder.getMarketData().getInstrumentAsString());
assertFalse(instrument.equals(builder.getOption().getInstrument()));
instrument = option;
builder = setDefaults(getBuilder());
builder.withInstrument(instrument);
assertEquals(instrument,
builder.getMarketData().getInstrument());
assertEquals(instrument.getSymbol(),
builder.getMarketData().getInstrumentAsString());
assertEquals(instrument,
builder.getOption().getInstrument());
verify(builder);
instrument = future;
builder = setDefaults(getBuilder());
builder.withInstrument(instrument);
assertEquals(instrument,
builder.getMarketData().getInstrument());
assertEquals(instrument.getSymbol(),
builder.getMarketData().getInstrumentAsString());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withMessageId(long)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withMessageId()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = getBuilder();
setDefaults(builder);
builder.withMessageId(Long.MIN_VALUE);
assertEquals(Long.MIN_VALUE,
builder.getMarketData().getMessageId());
builder.withMessageId(-1);
assertEquals(-1,
builder.getMarketData().getMessageId());
builder.withMessageId(Long.MAX_VALUE);
assertEquals(Long.MAX_VALUE,
builder.getMarketData().getMessageId());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withMultiplier(int)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withMultiplier()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
builder.withMultiplier(new BigDecimal(Integer.MIN_VALUE));
assertEquals(new BigDecimal(Integer.MIN_VALUE),
builder.getOption().getMultiplier());
builder.withMultiplier(BigDecimal.ZERO);
assertEquals(BigDecimal.ZERO,
builder.getOption().getMultiplier());
builder.withMultiplier(new BigDecimal(Integer.MAX_VALUE));
assertEquals(new BigDecimal(Integer.MAX_VALUE),
builder.getOption().getMultiplier());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withPrice(BigDecimal)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withPrice()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
BigDecimal price = null;
builder.withPrice(price);
assertNull(builder.getMarketData().getPrice());
price = new BigDecimal(-10);
builder.withPrice(price);
assertEquals(price,
builder.getMarketData().getPrice());
price = BigDecimal.ZERO;
builder.withPrice(price);
assertEquals(price,
builder.getMarketData().getPrice());
price = BigDecimal.TEN;
builder.withPrice(price);
assertEquals(price,
builder.getMarketData().getPrice());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withTradeDate(String)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withTradeDate()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
String date = null;
builder.withTradeDate(date);
assertEquals(date,
builder.getMarketData().getExchangeTimestamp());
date = "";
builder.withTradeDate(date);
assertEquals(date,
builder.getMarketData().getExchangeTimestamp());
date = "not-a-date";
builder.withTradeDate(date);
assertEquals(date,
builder.getMarketData().getExchangeTimestamp());
date = DateUtils.dateToString(new Date());
builder.withTradeDate(date);
assertEquals(date,
builder.getMarketData().getExchangeTimestamp());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withSize(BigDecimal)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withSize()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
BigDecimal size = null;
builder.withSize(size);
assertNull(builder.getMarketData().getSize());
size = new BigDecimal(-10);
builder.withSize(size);
assertEquals(size,
builder.getMarketData().getSize());
size = BigDecimal.ZERO;
builder.withSize(size);
assertEquals(size,
builder.getMarketData().getSize());
size = BigDecimal.TEN;
builder.withSize(size);
assertEquals(size,
builder.getMarketData().getSize());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withSource(Object)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withSource()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = getBuilder();
setDefaults(builder);
// null source
builder.withSource(null);
assertEquals(null,
builder.getMarketData().getSource());
// non-null source
builder.withSource(this);
assertEquals(this,
builder.getMarketData().getSource());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withTimestamp(Date)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withTimestamp()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = getBuilder();
setDefaults(builder);
// null timestamp
builder.withTimestamp(null);
assertEquals(null,
builder.getMarketData().getTimestamp());
// regular timestamp
Date timestamp = new Date();
builder.withTimestamp(timestamp);
assertEquals(timestamp,
builder.getMarketData().getTimestamp());
// make a weird timestamp
timestamp = new Date(-1);
builder.withTimestamp(timestamp);
assertEquals(timestamp,
builder.create().getTimestamp());
verify(builder);
}
/**
* Tests {@link TradeEventBuilder#withUnderlyingInstrument(Instrument)}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void withUnderylingInstrument()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = setDefaults(getBuilder());
instrument = null;
builder.withUnderlyingInstrument(instrument);
assertEquals(instrument,
builder.getOption().getUnderlyingInstrument());
instrument = equity;
builder.withUnderlyingInstrument(instrument);
assertEquals(instrument,
builder.getOption().getUnderlyingInstrument());
instrument = option;
builder = setDefaults(getBuilder());
builder.withUnderlyingInstrument(instrument);
assertEquals(instrument,
builder.getOption().getUnderlyingInstrument());
verify(builder);
instrument = future;
builder = setDefaults(getBuilder());
builder.withUnderlyingInstrument(instrument);
verify(builder);
}
/**
* Tests event <code>hashCode</code> and <code>equals</code>.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void hashCodeAndEquals()
throws Exception
{
TradeEventBuilder<TradeEvent> builder = getBuilder();
TradeEvent event1 = setDefaults(builder).create();
TradeEvent event2 = builder.create();
TradeEvent event3 = setDefaults(builder).create();
assertEquals(event1.getMessageId(),
event2.getMessageId());
assertFalse(event2.getMessageId() == event3.getMessageId());
EqualityAssert.assertEquality(event1,
event2,
event3,
null,
this);
}
/**
* Verifies that the given builder can produce an event of the
* correct type with the builder's attributes.
*
* <p>Note that the builder is assumed to be in a state that
* can produce an event without error.
*
* @param inBuilder a <code>TradeEventBuilder</code> value
* @return a <code>TradeEvent</code> value
* @throws Exception if an unexpected error occurs
*/
private TradeEvent verify(TradeEventBuilder<TradeEvent> inBuilder)
throws Exception
{
assertNotNull(inBuilder);
assertNotNull(inBuilder.toString());
TradeEvent event = inBuilder.create();
assertNotNull(event);
assertNotNull(event.toString());
assertEquals(inBuilder.getMarketData().getExchange(),
event.getExchange());
assertEquals(inBuilder.getMarketData().getExchangeTimestamp(),
event.getExchangeTimestamp());
assertEquals(inBuilder.getMarketData().getExchangeTimestamp(),
event.getTradeDate());
assertEquals(inBuilder.getMarketData().getInstrument(),
event.getInstrument());
// check the instrumentAsString method
assertEquals(inBuilder.getMarketData().getInstrumentAsString(),
event.getInstrumentAsString());
// there is a special case for messageId - if equal to Long.MIN_VALUE
// then it will be some value >= 0
if(inBuilder.getMarketData().getMessageId() == Long.MIN_VALUE) {
assertTrue(event.getMessageId() >= 0);
} else {
assertEquals(inBuilder.getMarketData().getMessageId(),
event.getMessageId());
}
assertEquals(inBuilder.getMarketData().getPrice(),
event.getPrice());
assertEquals(inBuilder.getMarketData().getSize(),
event.getSize());
assertEquals(inBuilder.getMarketData().getSource(),
event.getSource());
assertEquals(inBuilder.getMarketData().getEventType(),
event.getEventType());
assertFalse(event.getEventType() == EventType.SNAPSHOT_FINAL);
event.setEventType(EventType.SNAPSHOT_FINAL);
assertEquals(EventType.SNAPSHOT_FINAL,
event.getEventType());
// there's a special case for timestamp, too
if(inBuilder.getMarketData().getTimestamp() == null) {
assertNotNull(event.getTimestamp());
assertEquals(event.getTimestamp().getTime(),
event.getTimeMillis());
} else {
assertEquals(inBuilder.getMarketData().getTimestamp(),
event.getTimestamp());
assertEquals(inBuilder.getMarketData().getTimeMillis(),
event.getTimeMillis());
}
if(event instanceof OptionEvent) {
OptionEvent optionEvent = (OptionEvent)event;
assertEquals(inBuilder.getOption().getExpirationType(),
optionEvent.getExpirationType());
assertEquals(inBuilder.getOption().getInstrument(),
optionEvent.getInstrument());
assertEquals(inBuilder.getOption().getInstrument().getSymbol(),
optionEvent.getInstrumentAsString());
assertEquals(inBuilder.getOption().getMultiplier(),
optionEvent.getMultiplier());
assertEquals(inBuilder.getOption().getUnderlyingInstrument(),
optionEvent.getUnderlyingInstrument());
assertEquals(inBuilder.getOption().hasDeliverable(),
optionEvent.hasDeliverable());
assertEquals(inBuilder.getOption().getProviderSymbol(),
optionEvent.getProviderSymbol());
}
if(event instanceof FutureEvent) {
FutureEvent futureEvent = (FutureEvent)event;
assertEquals(inBuilder.getFuture().getProviderSymbol(),
futureEvent.getProviderSymbol());
assertEquals(inBuilder.getFuture().getContractSize(),
futureEvent.getContractSize());
}
Object newSource = new Object();
event.setSource(newSource);
assertEquals(newSource,
event.getSource());
return event;
}
/**
* Sets valid defaults in the given builder.
*
* @param inBuilder a <code>TradeEventBuilder</code> value
* @return a <code>TradeEventBuilder</code> value
* @throws Exception if an unexpected error occurs
*/
private TradeEventBuilder<TradeEvent> setDefaults(TradeEventBuilder<TradeEvent> inBuilder)
throws Exception
{
long millis = System.currentTimeMillis();
long millisInADay = 1000 * 60 * 60 * 24;
int counter = 0;
inBuilder.hasDeliverable(false);
inBuilder.withExchange("exchange");
inBuilder.withExpirationType(ExpirationType.AMERICAN);
inBuilder.withInstrument(instrument);
inBuilder.withMessageId(idCounter.incrementAndGet());
inBuilder.withMultiplier(BigDecimal.ZERO);
inBuilder.withProviderSymbol("MSQ/K/X");
inBuilder.withEventType(EventType.UPDATE_FINAL);
inBuilder.withPrice(BigDecimal.ONE);
inBuilder.withTradeDate(DateUtils.dateToString(new Date(millis + (millisInADay * counter++))));
inBuilder.withSize(BigDecimal.TEN);
inBuilder.withTimestamp(new Date());
inBuilder.withUnderlyingInstrument(instrument);
inBuilder.withContractSize(3600);
return inBuilder;
}
/**
* Gets the builder to use for testing.
*
* @return a <code>TradeEventBuilder</code> value
*/
private TradeEventBuilder<TradeEvent> getBuilder()
{
if(useInstrument) {
return TradeEventBuilder.tradeEvent(instrument);
} else {
if(instrument instanceof Equity) {
return TradeEventBuilder.equityTradeEvent();
} else if(instrument instanceof Option) {
return TradeEventBuilder.optionTradeEvent();
} else if(instrument instanceof Future) {
return TradeEventBuilder.futureTradeEvent();
}
}
throw new UnsupportedOperationException();
}
/**
* if set to true, will cause the builder to be created
*/
private boolean useInstrument;
/**
* test instrument with {@link TradeEventBuilder#tradeEvent(Instrument)}.
*/
private final Equity equity = new Equity("METC");
/**
* test option
*/
private final Option option = new Option("MSFT",
"20100319",
BigDecimal.ONE,
OptionType.Call);
/**
* test instrument with {@link TradeEventBuilder#tradeEvent(Instrument)}.
*/
private final Future future = new Future("METC",
FutureExpirationMonth.MARCH,
15);
/**
* instrument used during tests
*/
private Instrument instrument = equity;
/**
* id counter used to guarantee unique events
*/
private static final AtomicLong idCounter = new AtomicLong(0);
}