/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.generator; import java.security.SecureRandom; import java.util.Random; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.core.position.Portfolio; import com.opengamma.core.position.PortfolioNode; import com.opengamma.core.position.Position; import com.opengamma.core.position.Trade; import com.opengamma.core.security.Security; import com.opengamma.core.security.SecuritySource; import com.opengamma.financial.tool.ToolContext; import com.opengamma.master.portfolio.ManageablePortfolio; import com.opengamma.master.portfolio.ManageablePortfolioNode; import com.opengamma.master.portfolio.PortfolioDocument; import com.opengamma.master.portfolio.PortfolioSearchRequest; import com.opengamma.master.portfolio.PortfolioSearchResult; import com.opengamma.master.position.ManageablePosition; import com.opengamma.master.position.ManageableTrade; import com.opengamma.master.position.PositionDocument; import com.opengamma.master.position.PositionMaster; import com.opengamma.master.security.ManageableSecurityLink; import com.opengamma.util.money.Currency; /** * Utility for generating a portfolio of securities. */ public abstract class AbstractPortfolioGeneratorTool { private static final Logger s_logger = LoggerFactory.getLogger(AbstractPortfolioGeneratorTool.class); /** * Default counter party name */ public static final String DEFAULT_COUNTER_PARTY = "COUNTERPARTY"; /** * Default portfolio size used by sub-classes. */ protected static final int PORTFOLIO_SIZE = 200; private Random _random; private SecurityPersister _securityPersister; private ToolContext _toolContext; private Class<? extends AbstractPortfolioGeneratorTool> _classContext; private AbstractPortfolioGeneratorTool _objectContext; private NameGenerator _counterPartyGenerator; private Currency[] _currencies; public AbstractPortfolioGeneratorTool() { _classContext = getClass(); } public PortfolioGenerator createPortfolioGenerator(final NameGenerator portfolioNameGenerator) { return new PortfolioGenerator(createPortfolioNodeGenerator(PORTFOLIO_SIZE), portfolioNameGenerator); } public Portfolio createPortfolio(final String portfolioName) { return createPortfolioGenerator(new StaticNameGenerator(portfolioName)).createPortfolio(); } public PortfolioNodeGenerator createPortfolioNodeGenerator(final int portfolioSize) { throw new UnsupportedOperationException(); } public PortfolioNode createPortfolioNode(final int size) { return createPortfolioNodeGenerator(size).createPortfolioNode(); } public PortfolioNode createPortfolioNode() { return createPortfolioNode(PORTFOLIO_SIZE); } public Random getRandom() { return _random; } public void setRandom(final Random random) { _random = random; } public Currency[] getCurrencies() { return _currencies; } public void setCurrencies(final Currency[] currencies) { _currencies = currencies; } private void setContext(final Class<? extends AbstractPortfolioGeneratorTool> classContext, final AbstractPortfolioGeneratorTool objectContext) { _classContext = classContext; _objectContext = objectContext; } private Class<? extends AbstractPortfolioGeneratorTool> getClassContext() { return _classContext; } private AbstractPortfolioGeneratorTool getObjectContext() { return _objectContext; } public SecurityPersister getSecurityPersister() { return _securityPersister; } public void setSecurityPersister(final SecurityPersister securityPersister) { _securityPersister = securityPersister; } public NameGenerator getCounterPartyGenerator() { return _counterPartyGenerator; } public void setCounterPartyGenerator(final NameGenerator counterPartyGenerator) { _counterPartyGenerator = counterPartyGenerator; } public ToolContext getToolContext() { return _toolContext; } public void setToolContext(final ToolContext toolContext) { _toolContext = toolContext; } protected final void configure(final SecurityGenerator<?> securityGenerator) { if (getRandom() != null) { securityGenerator.setRandom(getRandom()); } if (getCurrencies() != null && getCurrencies().length > 0) { securityGenerator.setCurrencies(getCurrencies()); } if (getToolContext() != null) { securityGenerator.setConfigSource(getToolContext().getConfigSource()); securityGenerator.setConventionSource(getToolContext().getConventionSource()); securityGenerator.setConventionBundleSource(getToolContext().getConventionBundleSource()); securityGenerator.setHolidaySource(getToolContext().getHolidaySource()); securityGenerator.setHistoricalSource(getToolContext().getHistoricalTimeSeriesSource()); securityGenerator.setExchangeMaster(getToolContext().getExchangeMaster()); securityGenerator.setRegionSource(getToolContext().getRegionSource()); securityGenerator.setLegalEntitySource(getToolContext().getLegalEntitySource()); securityGenerator.setSecurityMaster(getToolContext().getSecurityMaster()); securityGenerator.setHistoricalTimeSeriesMaster(getToolContext().getHistoricalTimeSeriesMaster()); } configureChain(securityGenerator); } protected void configureChain(final SecurityGenerator<?> securityGenerator) { if (getObjectContext() != null) { getObjectContext().configureChain(securityGenerator); } } protected void configure(final AbstractPortfolioGeneratorTool tool) { if (getRandom() != null) { tool.setRandom(getRandom()); } if (getToolContext() != null) { tool.setToolContext(getToolContext()); } if (getSecurityPersister() != null) { tool.setSecurityPersister(getSecurityPersister()); } if (getCounterPartyGenerator() != null) { tool.setCounterPartyGenerator(getCounterPartyGenerator()); } } /** * Command line option for specifying the portfolio name to generate. */ public static final String PORTFOLIO_OPT = "portfolio"; /** * Command line option to specifying the asset class to generate the portfolio for. */ public static final String SECURITY_OPT = "security"; /** * Command line option to specify to write to the database masters. */ public static final String WRITE_OPT = "write"; /** * Command line option to specifying the name of the counter party to use for trades. */ public static final String COUNTER_PARTY_OPT = "counterPty"; private static final String CURRENCIES_OPT = "currencies"; private AbstractPortfolioGeneratorTool getInstance(final Class<?> clazz, final String security) { if (!AbstractPortfolioGeneratorTool.class.isAssignableFrom(clazz)) { throw new OpenGammaRuntimeException("Couldn't find generator tool class for " + security); } try { final String className; final int i = security.indexOf('.'); if (i < 0) { className = clazz.getPackage().getName() + "." + security + "PortfolioGeneratorTool"; } else { className = security; } final Class<?> instanceClass; try { s_logger.debug("Trying class {}", className); instanceClass = Class.forName(className); } catch (final ClassNotFoundException e) { return getInstance(clazz.getSuperclass(), security); } s_logger.info("Loading {}", className); final AbstractPortfolioGeneratorTool tool = (AbstractPortfolioGeneratorTool) instanceClass.newInstance(); tool.setContext(getClassContext(), this); return tool; } catch (final Exception e) { throw new OpenGammaRuntimeException("Couldn't create generator tool instance for " + security, e); } } protected AbstractPortfolioGeneratorTool getInstance(final String security) { return getInstance(getClassContext(), security); } public void run(final ToolContext context, final String portfolioName, final String security, final boolean write, final Currency[] currencies) { final AbstractPortfolioGeneratorTool instance = getInstance(security); instance.setToolContext(context); instance.setCounterPartyGenerator(getCounterPartyGenerator()); instance.setRandom(new SecureRandom()); final SecuritySource securitySource; if (write) { s_logger.info("Creating database security writer"); securitySource = context.getSecuritySource(); instance.setSecurityPersister(new MasterSecurityPersister(context.getSecurityMaster())); } else { s_logger.info("Using dummy security writer"); final InMemorySecurityPersister securityPersister = new InMemorySecurityPersister(); instance.setSecurityPersister(securityPersister); securitySource = securityPersister.getSecuritySource(); } if (currencies != null && currencies.length > 0) { instance.setCurrencies(currencies); } s_logger.info("Creating portfolio {}", portfolioName); final Portfolio portfolio = instance.createPortfolio(portfolioName); if (write) { s_logger.info("Writing portfolio to the database"); final ManageablePortfolio newPortfolio = new ManageablePortfolio(portfolio.getName()); newPortfolio.setAttributes(portfolio.getAttributes()); newPortfolio.setRootNode(createPortfolioNode(context.getPositionMaster(), portfolio.getRootNode())); final PortfolioSearchRequest request = new PortfolioSearchRequest(); request.setDepth(0); request.setIncludePositions(false); request.setName(portfolio.getName()); final PortfolioSearchResult result = context.getPortfolioMaster().search(request); PortfolioDocument document = result.getFirstDocument(); if (document != null) { s_logger.info("Overwriting portfolio {}", document.getUniqueId()); document.setPortfolio(newPortfolio); context.getPortfolioMaster().update(document); } else { document = new PortfolioDocument(newPortfolio); context.getPortfolioMaster().add(document); } } else { if (s_logger.isDebugEnabled()) { s_logger.debug("Portfolio {}", portfolioName); writePortfolio(securitySource, portfolio.getRootNode(), ""); } } } private ManageablePortfolioNode createPortfolioNode(final PositionMaster positionMaster, final PortfolioNode node) { final ManageablePortfolioNode newNode = new ManageablePortfolioNode(node.getName()); for (final PortfolioNode child : node.getChildNodes()) { newNode.addChildNode(createPortfolioNode(positionMaster, child)); } for (final Position position : node.getPositions()) { final ManageablePosition newPosition = new ManageablePosition(); newPosition.setAttributes(position.getAttributes()); newPosition.setQuantity(position.getQuantity()); newPosition.setSecurityLink(new ManageableSecurityLink(position.getSecurityLink())); for (final Trade trade : position.getTrades()) { newPosition.addTrade(new ManageableTrade(trade)); } newNode.addPosition(positionMaster.add(new PositionDocument(newPosition)).getUniqueId()); } return newNode; } private void writePortfolio(final SecuritySource securitySource, final PortfolioNode node, final String indent) { s_logger.debug("{}+{}", indent, node.getName()); for (final PortfolioNode childNode : node.getChildNodes()) { writePortfolio(securitySource, childNode, indent + " "); } for (final Position position : node.getPositions()) { final Security security = position.getSecurityLink().resolve(securitySource); s_logger.debug("{} {} x {}", new Object[] {indent, position.getQuantity(), security }); } } private Option required(final Option option) { option.setRequired(true); return option; } @SuppressWarnings("static-access") public void createOptions(final Options options) { options.addOption(required(new Option("p", PORTFOLIO_OPT, true, "sets the name of the portfolio to create"))); options.addOption(required(new Option("s", SECURITY_OPT, true, "selects the asset class to populate the portfolio with"))); options.addOption(new Option("w", WRITE_OPT, false, "writes the portfolio and securities to the masters")); options.addOption(new Option("cp", COUNTER_PARTY_OPT, true, "sets the name of the counter party")); options.addOption(OptionBuilder.hasArgs() .withArgName("Currency") .withDescription("Specify the currencies of the securities to be generated") .withLongOpt(CURRENCIES_OPT) .create("ccy")); } private Currency[] parseCurrencies(final CommandLine commandLine) { if (commandLine.hasOption(CURRENCIES_OPT)) { final String[] currencies = commandLine.getOptionValues(CURRENCIES_OPT); final Currency[] ccys = new Currency[currencies.length]; int i = 0; for (final String ccyStr : currencies) { ccys[i++] = Currency.of(ccyStr.trim()); } return ccys; } else { return null; } } public void run(final ToolContext context, final CommandLine commandLine) { setCounterPartyGenerator(new StaticNameGenerator(commandLine.getOptionValue(COUNTER_PARTY_OPT, DEFAULT_COUNTER_PARTY))); run(context, commandLine.getOptionValue(PORTFOLIO_OPT), commandLine.getOptionValue(SECURITY_OPT), commandLine.hasOption(WRITE_OPT), parseCurrencies(commandLine)); } }