/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.integration.tool.portfolio; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Factory; import org.testng.annotations.Test; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.financial.tool.ToolContext; import com.opengamma.master.portfolio.PortfolioMaster; import com.opengamma.master.portfolio.PortfolioSearchRequest; import com.opengamma.master.position.PositionMaster; import com.opengamma.master.position.PositionSearchRequest; import com.opengamma.master.security.SecurityMaster; import com.opengamma.master.security.SecuritySearchRequest; import com.opengamma.masterdb.portfolio.DbPortfolioMaster; import com.opengamma.masterdb.position.DbPositionMaster; import com.opengamma.masterdb.security.DbSecurityMaster; import com.opengamma.util.test.AbstractDbTest; import com.opengamma.util.test.DbTest; import com.opengamma.util.test.TestGroup; /** * Test the portfolio loader tool behaves as expected. Data should be read from a file and * inserted into the correct database masters. */ @Test(groups = TestGroup.INTEGRATION) public class PortfolioLoaderToolTest extends AbstractDbTest { private static final Logger s_logger = LoggerFactory.getLogger(PortfolioLoaderToolTest.class); private ToolContext _toolContext; private PortfolioMaster _portfolioMaster; private PositionMaster _positionMaster; private SecurityMaster _securityMaster; private File _tempFile; @Factory(dataProvider = "databases", dataProviderClass = DbTest.class) public PortfolioLoaderToolTest(final String databaseType, final String databaseVersion) { super(databaseType, databaseVersion); s_logger.info("running testcases for {}", databaseType); } //------------------------------------------------------------------------- @Override public void doSetUp() throws Exception { _tempFile = File.createTempFile("portfolio-", ".csv"); s_logger.info("Created temp file: " + _tempFile.getAbsolutePath()); _portfolioMaster = new DbPortfolioMaster(getDbConnector()); _positionMaster = new DbPositionMaster(getDbConnector()); _securityMaster = new DbSecurityMaster(getDbConnector()); _toolContext = new ToolContext(); _toolContext.setPortfolioMaster(_portfolioMaster); _toolContext.setPositionMaster(_positionMaster); _toolContext.setSecurityMaster(_securityMaster); } @Override public void doTearDown() { _toolContext = null; _positionMaster = null; _portfolioMaster = null; // Clean up the file we were using if (_tempFile != null && _tempFile.exists()) { s_logger.info("Removing file: " + _tempFile.getAbsolutePath()); _tempFile.delete(); } } //------------------------------------------------------------------------- @Test(expectedExceptions = IllegalArgumentException.class) public void testToolContextMustBeProvided() { new PortfolioLoader(null, "My portfolio", "Equity", _tempFile.getAbsolutePath(), true, false, false, false, true, true, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testPortfolioNameMustBeProvided() { new PortfolioLoader(_toolContext, null, "Equity", _tempFile.getAbsolutePath(), true, false, false, false, true, true, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testFilenameMustBeProvided() { new PortfolioLoader(_toolContext, "My portfolio", "Equity", null, true, false, false, false, true, true, null); } @Test(expectedExceptions = OpenGammaRuntimeException.class) public void testFileMustHaveRecognisedExtension() { new PortfolioLoader(_toolContext, "My portfolio", "Equity", "some_file.goobledygook", true, false, false, false, true, true, null).execute(); } @Test public void testLoadEquityPortfolio() throws IOException { final String data = "\"companyName\",\"currency\",\"exchange\",\"exchangeCode\",\"externalIdBundle\",\"name\",\"position:quantity\",\"securityType\",\"shortName\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"EXXON MOBIL CORP\",\"USD\",\"NEW YORK STOCK EXCHANGE INC.\",\"XNYS\",\"BLOOMBERG_BUID~EQ0010054600001000, BLOOMBERG_TICKER~XOM US Equity, CUSIP~30231G102, ISIN~US30231G1022, SEDOL1~2326618\",\"EXXON MOBIL CORP\",\"1264\",\"EQUITY\",\"XOM\",\"CPID~123\",,,,,,,,\n" + "\"APPLE INC\",\"USD\",\"NASDAQ/NGS (GLOBAL SELECT MARKET)\",\"XNGS\",\"BLOOMBERG_BUID~EQ0010169500001000, BLOOMBERG_TICKER~AAPL US Equity, CUSIP~037833100, ISIN~US0378331005, SEDOL1~2046251\",\"APPLE INC\",\"257\",\"EQUITY\",\"AAPL\",\"CPID~234\",,,,,,,,\n" + "\"MICROSOFT CORP\",\"USD\",\"NASDAQ/NGS (GLOBAL SELECT MARKET)\",\"XNGS\",\"BLOOMBERG_BUID~EQ0010174300001000, BLOOMBERG_TICKER~MSFT US Equity, CUSIP~594918104, ISIN~US5949181045, SEDOL1~2588173\",\"MICROSOFT CORP\",\"3740\",\"EQUITY\",\"MSFT\",\"CPID~345\",,,,,,,,"; doPortfolioLoadTest("Equity Portfolio", "Equity", data, 1, 3, 3); } @Test public void testLoadEquityPortfolioMultiplePositionsSameSecurity() throws IOException { final String data = "\"companyName\",\"currency\",\"exchange\",\"exchangeCode\",\"externalIdBundle\",\"name\",\"position:quantity\",\"securityType\",\"shortName\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"EXXON MOBIL CORP\",\"USD\",\"NEW YORK STOCK EXCHANGE INC.\",\"XNYS\",\"BLOOMBERG_BUID~EQ0010054600001000, BLOOMBERG_TICKER~XOM US Equity, CUSIP~30231G102, ISIN~US30231G1022, SEDOL1~2326618\",\"EXXON MOBIL CORP\",\"1264\",\"EQUITY\",\"XOM\",\"CPID~123\",,,,,,,,\n" + "\"APPLE INC\",\"USD\",\"NASDAQ/NGS (GLOBAL SELECT MARKET)\",\"XNGS\",\"BLOOMBERG_BUID~EQ0010169500001000, BLOOMBERG_TICKER~AAPL US Equity, CUSIP~037833100, ISIN~US0378331005, SEDOL1~2046251\",\"APPLE INC\",\"257\",\"EQUITY\",\"AAPL\",\"CPID~234\",,,,,,,,\n" + "\"MICROSOFT CORP\",\"USD\",\"NASDAQ/NGS (GLOBAL SELECT MARKET)\",\"XNGS\",\"BLOOMBERG_BUID~EQ0010174300001000, BLOOMBERG_TICKER~MSFT US Equity, CUSIP~594918104, ISIN~US5949181045, SEDOL1~2588173\",\"MICROSOFT CORP\",\"3740\",\"EQUITY\",\"MSFT\",\"CPID~345\",,,,,,,,\n" + "\"MICROSOFT CORP\",\"USD\",\"NASDAQ/NGS (GLOBAL SELECT MARKET)\",\"XNGS\",\"BLOOMBERG_BUID~EQ0010174300001000, BLOOMBERG_TICKER~MSFT US Equity, CUSIP~594918104, ISIN~US5949181045, SEDOL1~2588173\",\"MICROSOFT CORP\",\"3740\",\"EQUITY\",\"MSFT\",\"CPID~345\",,,,,,,,"; doPortfolioLoadTest("Equity Portfolio", "Equity", data, 1, 4, 3); } @Test public void testLoadEquityIndexFutureOptionPortfolio() throws IOException { final String data = "\"currency\",\"exchange\",\"exerciseType\",\"expiry\",\"externalIdBundle\",\"underlyingId\",\"optionType\",\"position:quantity\",\"securityType\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"USD\",\"NEW YORK STOCK EXCHANGE INC.\",\"EX_TYPE\",\"2050-01-01T00:00:00+00:00[Europe/London]\",\"EIFO_ID~EIFO1234\",\"UNDERLYING_ID~ul9999\",\"PUT\",\"1264\",\"EQUITY_INDEX_FUTURE_OPTION\",\"CPID~123\",,,,,,,,\n"; doPortfolioLoadTest("EquityIndexFutureOption Portfolio", "EquityIndexFutureOption", data, 1, 1, 1); } @Test public void testLoadEquityIndexDividendFutureOptionPortfolio() throws IOException { final String data = "\"currency\",\"exchange\",\"exerciseType\",\"expiry\",\"externalIdBundle\",\"underlyingId\",\"optionType\",\"position:quantity\",\"securityType\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"USD\",\"NEW YORK STOCK EXCHANGE INC.\",\"EX_TYPE\",\"2050-01-01T00:00:00+00:00[Europe/London]\",\"EIFO_ID~EIFO1234\",\"UNDERLYING_ID~ul9999\",\"PUT\",\"1264\",\"EQUITY_INDEX_DIVIDEND_FUTURE_OPTION\",\"CPID~123\",,,,,,,,\n"; doPortfolioLoadTest("EquityIndexDividendFutureOption Portfolio", "EquityIndexDividendFutureOption", data, 1, 1, 1); } @Test public void testLoadCashFlowPortfolio() throws IOException { final String data = "\"amount\",\"currency\",\"settlement\",\"externalIdBundle\",\"position:quantity\",\"securityType\",\"shortName\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "150000,\"USD\",\"2014-01-01T00:00:00+00:00[Europe/London]\",\"SOME_ID~CF001\",\"4\",\"CASHFLOW\",,\"CPID~123\",,,,,,,,\n" + "60000,\"EUR\",\"2014-02-02T00:00:00+00:00[Europe/London]\",\"SOME_ID~CF002\",\"2\",\"CASHFLOW\",,\"CPID~234\",,,,,,,,\n"; doPortfolioLoadTest("Cashflow Portfolio", "CashFlow", data, 1, 2, 2); } @Test public void testLoadCommodityFutureOptionPortfolio() throws IOException { final String data = "\"currency\",\"tradingExchange\",\"settlementExchange\",\"exerciseType\",\"expiry\",\"externalIdBundle\",\"underlyingId\",\"optionType\",\"position:quantity\",\"securityType\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"USD\",\"CME\",\"CME\",\"EX_TYPE\",\"2050-01-01T00:00:00+00:00[Europe/London]\",\"EIFO_ID~EIFO1234\",\"UNDERLYING_ID~ul9999\",\"PUT\",\"1264\",\"COMMODITY_FUTUREOPTION\",\"CPID~123\",,,,,,,,\n"; doPortfolioLoadTest("CommodityFutureOption Portfolio", "CommodityFutureOption", data, 1, 1, 1); } @Test public void testStandardCdsPortfolio() throws IOException { final String data = "adjustCashSettlementDate,adjustEffectiveDate,adjustMaturityDate,businessDayConvention,buy,cashSettlementDate,coupon,couponFrequency,dayCount,debtSeniority,effectiveDate,externalIdBundle,immAdjustMaturityDate,includeAccruedPremium,maturityDate,name,notional,position:quantity,protectionBuyer,protectionSeller,protectionStart,quotedSpread,recoveryRate,referenceEntity,regionId,restructuringClause,startDate,stubType,trade:counterpartyExternalId,trade:premium,trade:premiumCurrency,trade:premiumDate,trade:premiumTime,trade:quantity,trade:tradeDate,trade:tradeTime,upfrontAmount\n" + "FALSE,FALSE,FALSE,Following,TRUE,2013-03-24T00:00:00.0Z,100,Semi-annual,ACT/360,SNRFOR,2013-03-21T00:00:00.0Z,CSV_LOADER~41355.6232870372,FALSE,TRUE,2020-03-20T00:00:00.0Z,STEM GBP 100 7Y,GBP 1000000,1,EXTERNAL_CODE~ProtBuyer_1,EXTERNAL_CODE~ProtSeller_1,TRUE,100,0.4,MARKIT_RED_CODE~5AB67W,FINANCIAL_REGION~CARIBBEAN,MR,2013-03-20T00:00:00.0Z,SHORT_START,EXTERNAL_CODE~ProtSeller_1,,,,,1,2013-03-22,,GBP 50000"; doPortfolioLoadTest("Standard CDS Portfolio", "StandardVanillaCDS", data, 1, 1, 1); } @Test public void testCdsIndexPortfolio() throws IOException { final String data = "adjustSettlementDate,adjustEffectiveDate,adjustMaturityDate,businessDayConvention,buy,settlementDate,coupon,couponFrequency,dayCount,effectiveDate,externalIdBundle,immAdjustMaturityDate,includeAccruedPremium,indexCoupon,maturityDate,name,notional,position:quantity,protectionBuyer,protectionSeller,protectionStart,quotedSpread,recoveryRate,referenceEntity,startDate,stubType,trade:counterpartyExternalId,trade:premium,trade:premiumCurrency,trade:premiumDate,trade:premiumTime,trade:quantity,trade:tradeDate,trade:tradeTime,upfrontPayment\n" + "FALSE,FALSE,FALSE,Following,TRUE,2013-03-24T00:00:00.0Z,100,Semi-annual,ACT/360,2013-03-21T00:00:00.0Z,CSV_LOADER~41355.6232870372,FALSE,TRUE,0.01,2020-03-20T00:00:00.0Z,STEM GBP 100 7Y,GBP 1000000,1,EXTERNAL_CODE~ProtBuyer_1,EXTERNAL_CODE~ProtSeller_1,TRUE,100,0.4,MARKIT_RED_CODE~5AB67W,2013-03-20T00:00:00.0Z,SHORT_START,EXTERNAL_CODE~ProtSeller_1,,,,,1,2013-03-22,,GBP 50000"; doPortfolioLoadTest("CDS Index Portfolio", "CreditDefaultSwapIndex", data, 1, 1, 1); } @Test public void testLoadFxFutureOptionPortfolio() throws IOException { final String data = "\"currency\",\"tradingExchange\",\"settlementExchange\",\"exerciseType\",\"expiry\",\"externalIdBundle\",\"underlyingId\",\"optionType\",\"position:quantity\",\"securityType\",\"trade:counterpartyExternalId\",\"trade:deal\",\"trade:premium\",\"trade:premiumCurrency\",\"trade:premiumDate\",\"trade:premiumTime\",\"trade:quantity\",\"trade:tradeDate\",\"trade:tradeTime\"\n" + "\"USD\",\"CME\",\"CME\",\"EX_TYPE\",\"2050-01-01T00:00:00+00:00[Europe/London]\",\"EIFO_ID~EIFO1234\",\"UNDERLYING_ID~ul9999\",\"PUT\",\"1264\",\"FX_FUTUREOPTION\",\"CPID~123\",,,,,,,,\n"; doPortfolioLoadTest("FxFutureOption Portfolio", "FxFutureOption", data, 1, 1, 1); } private void doPortfolioLoadTest(final String portfolioName, final String securityType, final String data, final int expectedPortfolios, final int expectedPositions, final int expectedSecurities) { populateFileWithData(data); new PortfolioLoader(_toolContext, portfolioName, securityType, _tempFile.getAbsolutePath(), true, false, false, false, true, true, null).execute(); assertEquals(_portfolioMaster.search(new PortfolioSearchRequest()).getPortfolios().size(), expectedPortfolios); assertEquals(_positionMaster.search(new PositionSearchRequest()).getPositions().size(), expectedPositions); assertEquals(_securityMaster.search(new SecuritySearchRequest()).getSecurities().size(), expectedSecurities); } private void populateFileWithData(final String data) { try(BufferedWriter writer = new BufferedWriter(new FileWriter(_tempFile))) { writer.write(data); writer.flush(); } catch (final IOException e) { fail("Unable to write data to file: " + _tempFile.getAbsolutePath()); } } }