/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.web.analytics.blotter; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import java.math.BigDecimal; import java.util.Set; import org.joda.beans.MetaBean; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.threeten.bp.LocalDate; import org.threeten.bp.LocalTime; import org.threeten.bp.OffsetTime; import org.threeten.bp.ZoneOffset; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.opengamma.core.id.ExternalSchemes; import com.opengamma.financial.security.equity.EquitySecurity; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; import com.opengamma.master.portfolio.ManageablePortfolio; import com.opengamma.master.portfolio.ManageablePortfolioNode; import com.opengamma.master.portfolio.PortfolioDocument; import com.opengamma.master.portfolio.impl.InMemoryPortfolioMaster; import com.opengamma.master.position.ManageablePosition; import com.opengamma.master.position.ManageableTrade; import com.opengamma.master.position.PositionDocument; import com.opengamma.master.position.impl.InMemoryPositionMaster; import com.opengamma.master.security.SecurityDocument; import com.opengamma.master.security.impl.InMemorySecurityMaster; import com.opengamma.util.money.Currency; import com.opengamma.util.test.TestGroup; /** * Test. */ @Test(groups = TestGroup.UNIT) public class FungibleTradeBuilderTest { private static final ExternalIdBundle APPLE_BUNDLE; private static final ExternalIdBundle INTEL_BUNDLE; private static final EquitySecurity APPLE_SECURITY; private static final EquitySecurity INTEL_SECURITY; static { APPLE_BUNDLE = ExternalIdBundle.of(ExternalSchemes.BLOOMBERG_TICKER, "AAPL US Equity"); INTEL_BUNDLE = ExternalIdBundle.of(ExternalSchemes.BLOOMBERG_TICKER, "INTC US Equity"); APPLE_SECURITY = new EquitySecurity("exch", "exchCode", "Apple", Currency.USD); INTEL_SECURITY = new EquitySecurity("exch", "exchCode", "Intel", Currency.USD); APPLE_SECURITY.setExternalIdBundle(APPLE_BUNDLE); INTEL_SECURITY.setExternalIdBundle(INTEL_BUNDLE); } private InMemoryPortfolioMaster _portfolioMaster; private InMemoryPositionMaster _positionMaster; private FungibleTradeBuilder _tradeBuilder; private ManageablePortfolioNode _savedNode; private ManageablePosition _savedPosition; private ManageablePortfolio _savedPortfolio; @BeforeMethod public void setUp() throws Exception { _portfolioMaster = new InMemoryPortfolioMaster(); _positionMaster = new InMemoryPositionMaster(); InMemorySecurityMaster securityMaster = new InMemorySecurityMaster(); securityMaster.add(new SecurityDocument(APPLE_SECURITY)); securityMaster.add(new SecurityDocument(INTEL_SECURITY)); BigDecimal quantity = BigDecimal.valueOf(20); ManageablePosition position = new ManageablePosition(quantity, APPLE_SECURITY.getExternalIdBundle()); position.addTrade(new ManageableTrade(quantity, APPLE_BUNDLE, LocalDate.of(2012, 12, 1), OffsetTime.of(LocalTime.of(9, 30), ZoneOffset.UTC), ExternalId.of(AbstractTradeBuilder.CPTY_SCHEME, "existingCpty"))); _savedPosition = _positionMaster.add(new PositionDocument(position)).getPosition(); ManageablePortfolioNode root = new ManageablePortfolioNode("root"); ManageablePortfolioNode node = new ManageablePortfolioNode("node"); node.addPosition(_savedPosition.getUniqueId()); root.addChildNode(node); ManageablePortfolio portfolio = new ManageablePortfolio("portfolio", root); _savedPortfolio = _portfolioMaster.add(new PortfolioDocument(portfolio)).getPortfolio(); Set<MetaBean> metaBeans = Sets.<MetaBean>newHashSet(ManageableTrade.meta()); _tradeBuilder = new FungibleTradeBuilder(_positionMaster, _portfolioMaster, securityMaster, metaBeans, BlotterUtils.getStringConvert()); _savedNode = _savedPortfolio.getRootNode().getChildNodes().get(0); } private BeanDataSource createTradeData(String securityTicker, String id) { String securityId = ExternalId.of(ExternalSchemes.BLOOMBERG_TICKER, securityTicker).toString(); return BlotterTestUtils.beanData("uniqueId", id, "type", FungibleTradeBuilder.TRADE_TYPE_NAME, "tradeDate", "2012-12-21", "tradeTime", "14:25", "securityIdBundle", securityId, "premium", "1234", "premiumCurrency", "USD", "premiumDate", "2012-12-22", "premiumTime", "13:30", "quantity", "30", "counterparty", "cptyName", "attributes", Maps.newHashMap()); } /** * add a trade to a portfolio node that doesn't have an existing position in the trade's security. * node has a position in a different security of the same type */ @Test public void addTradeNoExistingPosition() { UniqueId tradeId = _tradeBuilder.addTrade(createTradeData("INTC US Equity", null), _savedNode.getUniqueId()); ManageableTrade testTrade = _positionMaster.getTrade(tradeId); assertEquals(LocalDate.of(2012, 12, 21), testTrade.getTradeDate()); assertEquals(OffsetTime.of(LocalTime.of(14, 25), ZoneOffset.UTC), testTrade.getTradeTime()); assertEquals(INTEL_BUNDLE, testTrade.getSecurityLink().getExternalId()); assertEquals(1234d, testTrade.getPremium()); assertEquals(Currency.USD, testTrade.getPremiumCurrency()); assertEquals(LocalDate.of(2012, 12, 22), testTrade.getPremiumDate()); assertEquals(OffsetTime.of(LocalTime.of(13, 30), ZoneOffset.UTC), testTrade.getPremiumTime()); assertEquals(BigDecimal.valueOf(30), testTrade.getQuantity()); assertEquals(ExternalId.of(AbstractTradeBuilder.CPTY_SCHEME, "cptyName"), testTrade.getCounterpartyExternalId()); assertTrue(testTrade.getAttributes().isEmpty()); ManageablePosition testPosition = _positionMaster.get(testTrade.getParentPositionId()).getPosition(); assertEquals(INTEL_BUNDLE, testPosition.getSecurityLink().getExternalId()); assertEquals(testTrade.getQuantity(), testPosition.getQuantity()); assertEquals(1, testPosition.getTrades().size()); assertEquals(testTrade, testPosition.getTrades().get(0)); ManageablePortfolio testPortfolio = _portfolioMaster.get(_savedNode.getPortfolioId()).getPortfolio(); ManageablePortfolioNode testNode = testPortfolio.getRootNode().getChildNodes().get(0); assertEquals(2, testNode.getPositionIds().size()); assertEquals(_savedPosition.getUniqueId().getObjectId(), testNode.getPositionIds().get(0)); assertEquals(testPosition.getUniqueId().getObjectId(), testNode.getPositionIds().get(1)); } /** * add a trade to a portfolio node that already has a position in the trade's security */ @Test public void addTradeToExistingPosition() { UniqueId tradeId = _tradeBuilder.addTrade(createTradeData("AAPL US Equity", null), _savedNode.getUniqueId()); ManageableTrade testTrade = _positionMaster.getTrade(tradeId); assertEquals(LocalDate.of(2012, 12, 21), testTrade.getTradeDate()); assertEquals(OffsetTime.of(LocalTime.of(14, 25), ZoneOffset.UTC), testTrade.getTradeTime()); assertEquals(APPLE_BUNDLE, testTrade.getSecurityLink().getExternalId()); assertEquals(1234d, testTrade.getPremium()); assertEquals(Currency.USD, testTrade.getPremiumCurrency()); assertEquals(LocalDate.of(2012, 12, 22), testTrade.getPremiumDate()); assertEquals(OffsetTime.of(LocalTime.of(13, 30), ZoneOffset.UTC), testTrade.getPremiumTime()); assertEquals(BigDecimal.valueOf(30), testTrade.getQuantity()); assertEquals(ExternalId.of(AbstractTradeBuilder.CPTY_SCHEME, "cptyName"), testTrade.getCounterpartyExternalId()); assertTrue(testTrade.getAttributes().isEmpty()); ManageablePosition testPosition = _positionMaster.get(testTrade.getParentPositionId()).getPosition(); assertEquals(APPLE_BUNDLE, testPosition.getSecurityLink().getExternalId()); assertEquals(BigDecimal.valueOf(50), testPosition.getQuantity()); assertEquals(2, testPosition.getTrades().size()); assertEquals(testTrade, testPosition.getTrades().get(1)); ManageablePortfolio testPortfolio = _portfolioMaster.get(_savedNode.getPortfolioId()).getPortfolio(); ManageablePortfolioNode testNode = testPortfolio.getRootNode().getChildNodes().get(0); assertEquals(1, testNode.getPositionIds().size()); assertEquals(_savedPosition.getUniqueId().getObjectId(), testNode.getPositionIds().get(0)); } /** * update a trade - the position's quantity should also be adjusted */ @Test public void updateTrade() { ManageableTrade previousTrade = _savedPosition.getTrades().get(0); BeanDataSource tradeData = createTradeData("AAPL US Equity", previousTrade.getUniqueId().toString()); UniqueId updatedId = _tradeBuilder.updateTrade(tradeData); ManageableTrade updatedTrade = _positionMaster.getTrade(updatedId); assertEquals(LocalDate.of(2012, 12, 21), updatedTrade.getTradeDate()); assertEquals(OffsetTime.of(LocalTime.of(14, 25), ZoneOffset.UTC), updatedTrade.getTradeTime()); assertEquals(APPLE_BUNDLE, updatedTrade.getSecurityLink().getExternalId()); assertEquals(1234d, updatedTrade.getPremium()); assertEquals(Currency.USD, updatedTrade.getPremiumCurrency()); assertEquals(LocalDate.of(2012, 12, 22), updatedTrade.getPremiumDate()); assertEquals(OffsetTime.of(LocalTime.of(13, 30), ZoneOffset.UTC), updatedTrade.getPremiumTime()); assertEquals(BigDecimal.valueOf(30), updatedTrade.getQuantity()); assertEquals(ExternalId.of(AbstractTradeBuilder.CPTY_SCHEME, "cptyName"), updatedTrade.getCounterpartyExternalId()); assertTrue(updatedTrade.getAttributes().isEmpty()); } /** * update a position that doesn't have any trades. position's quantity should match trade and trade should be added */ @Test public void updatePositionWithNoTrades() { ManageablePosition position = new ManageablePosition(BigDecimal.valueOf(42), APPLE_SECURITY.getExternalIdBundle()); ManageablePosition savedPosition = _positionMaster.add(new PositionDocument(position)).getPosition(); assertEquals(BigDecimal.valueOf(42), savedPosition.getQuantity()); _tradeBuilder.updatePosition(createTradeData("AAPL US Equity", null), savedPosition.getUniqueId()); ManageablePosition updatedPosition = _positionMaster.get(savedPosition.getUniqueId().getObjectId(), VersionCorrection.LATEST).getPosition(); assertEquals(BigDecimal.valueOf(30), updatedPosition.getQuantity()); assertEquals(1, updatedPosition.getTrades().size()); ManageableTrade trade = updatedPosition.getTrades().get(0); assertEquals(LocalDate.of(2012, 12, 21), trade.getTradeDate()); assertEquals(OffsetTime.of(LocalTime.of(14, 25), ZoneOffset.UTC), trade.getTradeTime()); assertEquals(APPLE_BUNDLE, trade.getSecurityLink().getExternalId()); assertEquals(1234d, trade.getPremium()); assertEquals(Currency.USD, trade.getPremiumCurrency()); assertEquals(LocalDate.of(2012, 12, 22), trade.getPremiumDate()); assertEquals(OffsetTime.of(LocalTime.of(13, 30), ZoneOffset.UTC), trade.getPremiumTime()); assertEquals(BigDecimal.valueOf(30), trade.getQuantity()); assertEquals(ExternalId.of(AbstractTradeBuilder.CPTY_SCHEME, "cptyName"), trade.getCounterpartyExternalId()); assertTrue(trade.getAttributes().isEmpty()); } /** * update the trade and change the security - this should fail */ @Test(expectedExceptions = IllegalArgumentException.class) public void updateTradeChangeSecurity() { ManageableTrade previousTrade = _savedPosition.getTrades().get(0); BeanDataSource tradeData = createTradeData("INTC US Equity", previousTrade.getUniqueId().toString()); _tradeBuilder.updateTrade(tradeData); } }