package org.marketcetera.event.util; import static org.junit.Assert.*; import java.math.BigDecimal; import java.util.Date; import org.junit.Test; import org.marketcetera.event.EventTestBase; import org.marketcetera.event.MarketstatEvent; import org.marketcetera.event.OptionMarketstatEvent; import org.marketcetera.event.impl.MarketstatEventBuilder; import org.marketcetera.marketdata.DateUtils; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.options.ExpirationType; import org.marketcetera.trade.*; /* $License$ */ /** * Tests {@link MarketstatEventCache}. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: MarketstatEventCacheTest.java 16460 2013-01-21 21:55:10Z colin $ * @since 2.0.0 */ public class MarketstatEventCacheTest { /** * Tests the {@link MarketstatEventCache} constructor. * * * @throws Exception if an unexpected error occurs */ @Test public void constructor() throws Exception { new ExpectedFailure<NullPointerException>() { @Override protected void run() throws Exception { new MarketstatEventCache(null); } }; new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { new MarketstatEventCache(EventTestBase.generateUnsupportedInstrument()); } }; verifyCache(new MarketstatEventCache(equity), null); verifyCache(new MarketstatEventCache(option), null); } /** * Tests the ability to cache values. * * @throws Exception if an unexpected error occurs */ @Test public void cachedValues() throws Exception { final MarketstatEventBuilder equityBuilder = MarketstatEventBuilder.marketstat(equity); final MarketstatEventBuilder optionBuilder = MarketstatEventBuilder.marketstat(option); final MarketstatEventBuilder futureBuilder = MarketstatEventBuilder.marketstat(future); final MarketstatEventBuilder currencyBuilder = MarketstatEventBuilder.marketstat(currency); final MarketstatEventCache equityCache = new MarketstatEventCache(equity); final MarketstatEventCache optionCache = new MarketstatEventCache(option); final MarketstatEventCache futureCache = new MarketstatEventCache(future); final MarketstatEventCache currencyCache = new MarketstatEventCache(currency); new ExpectedFailure<IllegalArgumentException>() { @Override protected void run() throws Exception { optionCache.cache(equityBuilder.create()); } }; new ExpectedFailure<IllegalArgumentException>() { @Override protected void run() throws Exception { equityCache.cache(optionBuilder.create()); } }; new ExpectedFailure<IllegalArgumentException>() { @Override protected void run() throws Exception { futureCache.cache(equityBuilder.create()); } }; new ExpectedFailure<IllegalArgumentException>() { @Override protected void run() throws Exception { currencyCache.cache(equityBuilder.create()); } }; // these values are not nullable, so set them up now optionBuilder.withExpirationType(ExpirationType.EUROPEAN); optionBuilder.withUnderlyingInstrument(equity); doCacheTest(equityBuilder, equityCache); doCacheTest(optionBuilder, optionCache); doCacheTest(futureBuilder, futureCache); doCacheTest(currencyBuilder, currencyCache); } /** * Executes a set of cache tests with the given builder and cache. * * @param inBuilder a <code>MarketstatEventBuilder</code> value * @param inCache a <code>MarketstatEventCache</code> value * @throws Exception if an unexpected error occurs */ private void doCacheTest(final MarketstatEventBuilder inBuilder, final MarketstatEventCache inCache) throws Exception { new ExpectedFailure<NullPointerException>() { @Override protected void run() throws Exception { inCache.cache(null); } }; MarketstatEvent event = inBuilder.create(); inCache.cache(event); verifyCache(inCache, event); // test values that are always different Thread.sleep(250); event = inBuilder.withSource(this).create(); inCache.cache(event); verifyCache(inCache, event); event = inBuilder.withSource(null).create(); inCache.cache(event); verifyCache(inCache, event); // start changing values that may or may not change // close price assertNull(event.getClose()); event = inBuilder.withClosePrice(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); BigDecimal amount = event.getClose(); inCache.cache(inBuilder.withClosePrice(null).create()); verifyCache(inCache, event); inBuilder.withClosePrice(amount); long timestamp = System.currentTimeMillis(); int counter = 0; // close date assertNull(event.getCloseDate()); event = inBuilder.withCloseDate(DateUtils.dateToString(new Date(timestamp + (counter++ * 1000)))).create(); inCache.cache(event); verifyCache(inCache, event); String date = event.getCloseDate(); inCache.cache(inBuilder.withCloseDate(null).create()); verifyCache(inCache, event); inBuilder.withCloseDate(date); // close exchange assertNull(event.getCloseExchange()); event = inBuilder.withCloseExchange("close exchange").create(); inCache.cache(event); verifyCache(inCache, event); String exchange = event.getCloseExchange(); inCache.cache(inBuilder.withCloseExchange(null).create()); verifyCache(inCache, event); inBuilder.withCloseExchange(exchange); // high price assertNull(event.getHigh()); event = inBuilder.withHighPrice(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getHigh(); inCache.cache(inBuilder.withHighPrice(null).create()); verifyCache(inCache, event); inBuilder.withHighPrice(amount); // high exchange assertNull(event.getHighExchange()); event = inBuilder.withHighExchange("high exchange").create(); inCache.cache(event); verifyCache(inCache, event); exchange = event.getHighExchange(); inCache.cache(inBuilder.withHighExchange(null).create()); verifyCache(inCache, event); inBuilder.withHighExchange(exchange); // low price assertNull(event.getLow()); event = inBuilder.withLowPrice(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getLow(); inCache.cache(inBuilder.withLowPrice(null).create()); verifyCache(inCache, event); inBuilder.withLowPrice(amount); // low exchange assertNull(event.getLowExchange()); event = inBuilder.withLowExchange("low exchange").create(); inCache.cache(event); verifyCache(inCache, event); exchange = event.getLowExchange(); inCache.cache(inBuilder.withLowExchange(null).create()); verifyCache(inCache, event); inBuilder.withLowExchange(exchange); // open price assertNull(event.getOpen()); event = inBuilder.withOpenPrice(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getOpen(); inCache.cache(inBuilder.withOpenPrice(null).create()); verifyCache(inCache, event); inBuilder.withOpenPrice(amount); // open exchange assertNull(event.getOpenExchange()); event = inBuilder.withOpenExchange("open exchange").create(); inCache.cache(event); verifyCache(inCache, event); exchange = event.getOpenExchange(); inCache.cache(inBuilder.withOpenExchange(null).create()); verifyCache(inCache, event); inBuilder.withOpenExchange(exchange); // previous close price assertNull(event.getPreviousClose()); event = inBuilder.withPreviousClosePrice(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getPreviousClose(); inCache.cache(inBuilder.withPreviousClosePrice(null).create()); verifyCache(inCache, event); inBuilder.withPreviousClosePrice(amount); // previous close date assertNull(event.getPreviousCloseDate()); event = inBuilder.withPreviousCloseDate(DateUtils.dateToString(new Date(timestamp + (counter++ * 1000)))).create(); inCache.cache(event); verifyCache(inCache, event); date = event.getPreviousCloseDate(); inCache.cache(inBuilder.withPreviousCloseDate(null).create()); verifyCache(inCache, event); inBuilder.withPreviousCloseDate(date); // trade high time assertNull(event.getTradeHighTime()); event = inBuilder.withTradeHighTime(DateUtils.dateToString(new Date(timestamp + (counter++ * 1000)))).create(); inCache.cache(event); verifyCache(inCache, event); date = event.getTradeHighTime(); inCache.cache(inBuilder.withTradeHighTime(null).create()); verifyCache(inCache, event); inBuilder.withTradeHighTime(date); // trade low time assertNull(event.getTradeLowTime()); event = inBuilder.withTradeLowTime(DateUtils.dateToString(new Date(timestamp + (counter++ * 1000)))).create(); inCache.cache(event); verifyCache(inCache, event); date = event.getTradeLowTime(); inCache.cache(inBuilder.withTradeLowTime(null).create()); verifyCache(inCache, event); inBuilder.withTradeLowTime(date); // trade volume assertNull(event.getVolume()); event = inBuilder.withVolume(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getVolume(); inCache.cache(inBuilder.withVolume(null).create()); verifyCache(inCache, event); inBuilder.withVolume(amount); // trade value assertNull(event.getValue()); event = inBuilder.withValue(EventTestBase.generateDecimalValue()).create(); inCache.cache(event); verifyCache(inCache, event); amount = event.getValue(); inCache.cache(inBuilder.withValue(null).create()); verifyCache(inCache, event); inBuilder.withValue(amount); if(event instanceof OptionMarketstatEvent) { OptionMarketstatEvent optionEvent = (OptionMarketstatEvent)event; // deliverable assertFalse(optionEvent.hasDeliverable()); optionEvent = (OptionMarketstatEvent)inBuilder.hasDeliverable(true).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); // expiration type optionEvent = (OptionMarketstatEvent)inBuilder.withExpirationType(ExpirationType.AMERICAN).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); // multiplier assertNull(optionEvent.getMultiplier()); optionEvent = (OptionMarketstatEvent)inBuilder.withMultiplier(EventTestBase.generateDecimalValue()).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); amount = optionEvent.getMultiplier(); inCache.cache(inBuilder.withMultiplier(null).create()); verifyCache(inCache, optionEvent); inBuilder.withMultiplier(amount); // provider symbol assertNull(optionEvent.getProviderSymbol()); optionEvent = (OptionMarketstatEvent)inBuilder.withProviderSymbol("Symbol").create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); String symbol = optionEvent.getProviderSymbol(); inCache.cache(inBuilder.withProviderSymbol(null).create()); verifyCache(inCache, optionEvent); inBuilder.withProviderSymbol(symbol); // underlying instrument optionEvent = (OptionMarketstatEvent)inBuilder.withUnderlyingInstrument(option).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); // volume change assertNull(optionEvent.getVolumeChange()); optionEvent = (OptionMarketstatEvent)inBuilder.withVolumeChange(EventTestBase.generateDecimalValue()).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); // interest change assertNull(optionEvent.getInterestChange()); optionEvent = (OptionMarketstatEvent)inBuilder.withInterestChange(EventTestBase.generateDecimalValue()).create(); inCache.cache(optionEvent); verifyCache(inCache, optionEvent); } } /** * Verifies that the given <code>MarketstatEventCache</code> produces the * given expected event. * * @param inActualCache a <code>MarketstatEventCache</code> value * @param inExpectedEvent a <code>MarketstatEvent</code> value */ private static void verifyCache(MarketstatEventCache inActualCache, MarketstatEvent inExpectedEvent) { if(inExpectedEvent == null) { assertNull(inActualCache.get()); return; } MarketstatEvent actualEvent = inActualCache.get(); assertNotNull(actualEvent); // messageId and timestamp are intentionally not tested here because the contract // does not guarantee their contents assertEquals(inExpectedEvent.getClose(), actualEvent.getClose()); assertEquals(inExpectedEvent.getCloseDate(), actualEvent.getCloseDate()); assertEquals(inExpectedEvent.getCloseExchange(), actualEvent.getCloseExchange()); assertEquals(inExpectedEvent.getHigh(), actualEvent.getHigh()); assertEquals(inExpectedEvent.getHighExchange(), actualEvent.getHighExchange()); assertEquals(inExpectedEvent.getInstrument(), actualEvent.getInstrument()); assertEquals(inExpectedEvent.getLow(), actualEvent.getLow()); assertEquals(inExpectedEvent.getLowExchange(), actualEvent.getLowExchange()); assertEquals(inExpectedEvent.getOpen(), actualEvent.getOpen()); assertEquals(inExpectedEvent.getOpenExchange(), actualEvent.getOpenExchange()); assertEquals(inExpectedEvent.getPreviousClose(), actualEvent.getPreviousClose()); assertEquals(inExpectedEvent.getPreviousCloseDate(), actualEvent.getPreviousCloseDate()); assertEquals(inExpectedEvent.getSource(), actualEvent.getSource()); assertEquals(inExpectedEvent.getTradeHighTime(), actualEvent.getTradeHighTime()); assertEquals(inExpectedEvent.getTradeLowTime(), actualEvent.getTradeLowTime()); assertEquals(inExpectedEvent.getVolume(), actualEvent.getVolume()); assertEquals(inExpectedEvent.getValue(), actualEvent.getValue()); if(inExpectedEvent instanceof OptionMarketstatEvent) { assertTrue(actualEvent instanceof OptionMarketstatEvent); OptionMarketstatEvent expectedOptionEvent = (OptionMarketstatEvent)inExpectedEvent; OptionMarketstatEvent actualOptionEvent = (OptionMarketstatEvent)actualEvent; assertEquals(expectedOptionEvent.getInterestChange(), actualOptionEvent.getInterestChange()); assertEquals(expectedOptionEvent.getVolumeChange(), actualOptionEvent.getVolumeChange()); assertEquals(expectedOptionEvent.hasDeliverable(), actualOptionEvent.hasDeliverable()); assertEquals(expectedOptionEvent.getMultiplier(), actualOptionEvent.getMultiplier()); assertEquals(expectedOptionEvent.getProviderSymbol(), actualOptionEvent.getProviderSymbol()); assertEquals(expectedOptionEvent.getUnderlyingInstrument(), actualOptionEvent.getUnderlyingInstrument()); assertEquals(expectedOptionEvent.getExpirationType(), actualOptionEvent.getExpirationType()); } } /** * test equity */ private final Equity equity = new Equity("METC"); /** * test option */ private final Option option = new Option(equity.getSymbol(), DateUtils.dateToString(new Date()), EventTestBase.generateDecimalValue(), OptionType.Call); /** * test future */ private final Future future = new Future("IB", FutureExpirationMonth.FEBRUARY, 2012); /** * test currency */ private final Currency currency = new Currency("USD/GBP"); }