package org.marketcetera.marketdata.core.provider;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import org.marketcetera.core.LoggerConfiguration;
import org.marketcetera.event.*;
import org.marketcetera.event.impl.QuoteEventBuilder;
import org.marketcetera.event.impl.TopOfBookEventBuilder;
import org.marketcetera.marketdata.Content;
import org.marketcetera.marketdata.DateUtils;
import org.marketcetera.marketdata.OrderBook;
import org.marketcetera.trade.Equity;
import org.marketcetera.trade.Instrument;
/* $License$ */
/**
* Tests {@link MarketdataCacheElement}.
*
* @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a>
* @version $Id: MarketdataCacheElementTest.java 16901 2014-05-11 16:14:11Z colin $
* @since 2.4.0
*/
public class MarketdataCacheElementTest
{
/**
* Runs once before all tests.
*
* @throws Exception if an unexpected error occurs
*/
public static void once()
throws Exception
{
LoggerConfiguration.logSetup();
}
/**
* Runs before each test.
*
* @throws Exception if an unexpected error occurs
*/
@Before
public void setup()
throws Exception
{
equityCache = new MarketdataCacheElement(equity);
equityOrderbook = new OrderBook(equity);
}
/**
* Tests {@link MarketdataCacheElement#update(org.marketcetera.marketdata.Content, org.marketcetera.event.Event...) update top of book}.
*
* @throws Exception if an unexpected error occurs
*/
@Test
public void updateTopOfBook()
throws Exception
{
// top of book is currently empty
verifyTopOfBook(generateTopOfBook(equity,
null,
null),
(TopOfBookEvent)equityCache.getSnapshot(Content.TOP_OF_BOOK));
AskEvent ask1 = generateAsk(equity);
BidEvent bid1 = generateBid(equity);
AskEvent ask2 = generateAsk(equity);
BidEvent bid2 = generateBid(equity);
assertFalse(ask1.equals(ask2));
assertFalse(bid1.equals(bid2));
// no existing top
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
ask1));
verifyTopOfBook(generateTopOfBook(null,
ask1),
equityOrderbook.getTopOfBook());
// existing top with ask only (new ask better)
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
ask2));
verifyTopOfBook(generateTopOfBook(null,
ask2),
equityOrderbook.getTopOfBook());
// existing top with bid and ask
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
bid1));
verifyTopOfBook(generateTopOfBook(bid1,
ask2),
equityOrderbook.getTopOfBook());
// replace bid and ask at the same time
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
bid2,ask1));
verifyTopOfBook(generateTopOfBook(bid2,
ask1),
equityOrderbook.getTopOfBook());
// remove bid
BidEvent bid3 = QuoteEventBuilder.delete(bid2);
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
bid3));
verifyTopOfBook(generateTopOfBook(null,
ask1),
equityOrderbook.getTopOfBook());
// remove ask
AskEvent ask3 = QuoteEventBuilder.delete(ask1);
equityOrderbook.processAll(equityCache.update(Content.TOP_OF_BOOK,
ask3));
verifyTopOfBook(null,
equityOrderbook.getTopOfBook());
}
/**
* Generates a <code>TopOfBookEvent</code> with the given bid and ask.
*
* @param inBid a <code>BidEvent</code> value or <code>null</code>
* @param inAsk an <code>AskEvent</code> value or <code>null</code>
* @return a <code>TopOfBookEvent</code> or <code>null</code> if both the bid and ask are <code>null</code>
* @throws Exception if an unexpected error occurs
*/
private TopOfBookEvent generateTopOfBook(BidEvent inBid,
AskEvent inAsk)
throws Exception
{
Instrument instrument = null;
if(inBid != null){
instrument = inBid.getInstrument();
} else if(inAsk != null) {
instrument = inAsk.getInstrument();
}
return generateTopOfBook(instrument,
inBid,
inAsk);
}
/**
*
*
*
* @param inInstrument
* @param inBid
* @param inAsk
* @return
* @throws Exception
*/
private TopOfBookEvent generateTopOfBook(Instrument inInstrument,
BidEvent inBid,
AskEvent inAsk)
throws Exception
{
TopOfBookEventBuilder builder = TopOfBookEventBuilder.topOfBookEvent()
.withInstrument(inInstrument)
.withAsk(inAsk)
.withBid(inBid);
return builder.create();
}
/**
* Verifies that the given expected quote matches the given actual quote.
*
* @param inExpectedQuote a <code>QuoteEvent</code> value
* @param inActualQuote a <code>QuoteEvent</code> value
* @throws Exception if an unexpected error occurs
*/
private void verifyQuote(QuoteEvent inExpectedQuote,
QuoteEvent inActualQuote)
throws Exception
{
if(inExpectedQuote == null) {
assertNull(inActualQuote);
return;
}
assertNotNull(inExpectedQuote);
assertNotNull(inActualQuote);
assertEquals(inExpectedQuote.getAction(),
inActualQuote.getAction());
assertEquals(inExpectedQuote.getExchange(),
inActualQuote.getExchange());
assertEquals(inExpectedQuote.getExchangeTimestamp(),
inActualQuote.getExchangeTimestamp());
assertEquals(inExpectedQuote.getInstrument(),
inActualQuote.getInstrument());
assertEquals(inExpectedQuote.getMessageId(),
inActualQuote.getMessageId());
assertEquals(inExpectedQuote.getPrice(),
inActualQuote.getPrice());
assertEquals(inExpectedQuote.getProvider(),
inActualQuote.getProvider());
assertEquals(inExpectedQuote.getQuoteDate(),
inActualQuote.getQuoteDate());
assertEquals(inExpectedQuote.getSize(),
inActualQuote.getSize());
assertEquals(inExpectedQuote.getSource(),
inActualQuote.getSource());
assertEquals(inExpectedQuote.getTimestamp(),
inActualQuote.getTimestamp());
}
/**
* Verifies that the given expected <code>TopOfBookEvent</code> matches the given actual <code>TopOfBookEvent</code> value.
*
* @param inExpectedTop a <code>TopOfBookEvent</code> value
* @param inActualTop a <code>TopOfBookEvent</code> value
* @throws Exception if an unexpected error occurs
*/
private void verifyTopOfBook(TopOfBookEvent inExpectedTop,
TopOfBookEvent inActualTop)
throws Exception
{
if(inExpectedTop == null) {
assertNull(inActualTop.getAsk());
assertNull(inActualTop.getBid());
return;
}
assertNotNull(inActualTop);
verifyQuote(inExpectedTop.getBid(),
inActualTop.getBid());
}
/**
* Generates an <code>AskEvent</code> for the given <code>Instrument</code>.
*
* @param inInstrument an <code>Instrument</code> value
* @return an <code>AskEvent</code> value
*/
private AskEvent generateAsk(Instrument inInstrument)
{
QuoteEventBuilder<AskEvent> builder = QuoteEventBuilder.askEvent(inInstrument)
.withAction(QuoteAction.ADD)
.withExchange("Q")
.withPrice(EventTestBase.generateDecimalValue())
.withSize(EventTestBase.generateDecimalValue())
.withQuoteDate(DateUtils.dateToString(new Date()));
return builder.create();
}
/**
* Generates a <code>BidEvent</code> for the given <code>Instrument</code>.
*
* @param inInstrument an <code>Instrument</code> value
* @return a <code>BidEvent</code> value
*/
private BidEvent generateBid(Instrument inInstrument)
{
QuoteEventBuilder<BidEvent> builder = QuoteEventBuilder.bidEvent(inInstrument)
.withAction(QuoteAction.ADD)
.withExchange("Q")
.withPrice(EventTestBase.generateDecimalValue())
.withSize(EventTestBase.generateDecimalValue())
.withQuoteDate(DateUtils.dateToString(new Date()));
return builder.create();
}
/**
* test cache element value
*/
private MarketdataCacheElement equityCache;
/**
* test orderbook used to verify events
*/
private OrderBook equityOrderbook;
/**
* test equity
*/
private Equity equity = new Equity("METC");
}