Package com.opengamma.integration.tool.portfolio.xml.v1_0.conversion

Source Code of com.opengamma.integration.tool.portfolio.xml.v1_0.conversion.PortfolioConverter

/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.portfolio.xml.v1_0.conversion;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.opengamma.core.security.Security;
import com.opengamma.id.ExternalId;
import com.opengamma.integration.tool.portfolio.xml.PortfolioPosition;
import com.opengamma.integration.tool.portfolio.xml.XmlExternalIdValidator;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.AdditionalCashflow;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.IdWrapper;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.ListedSecurityDefinition;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.MonetaryAmount;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.Portfolio;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.Position;
import com.opengamma.integration.tool.portfolio.xml.v1_0.jaxb.Trade;
import com.opengamma.master.position.ManageablePosition;
import com.opengamma.master.position.ManageableTrade;
import com.opengamma.master.security.ManageableSecurity;

/**
* Converts a portfolio from the JAXB extracted objects to the standard
* system objects.
*/
public class PortfolioConverter {

  private static final Logger s_logger = LoggerFactory.getLogger(PortfolioConverter.class);

  /**
   * The portfolio to be converted.
   */
  private final Portfolio _portfolio;

  private final XmlExternalIdValidator _xmlExternalIdValidator;

  public PortfolioConverter(Portfolio portfolio, XmlExternalIdValidator xmlExternalIdValidator) {
    _portfolio = portfolio;
    _xmlExternalIdValidator = xmlExternalIdValidator;

  }

  /**
   * Get the set of manageable positions for this portfolio. Note that this may add in positions
   * which were not in the original xml file e.g. where a set of trades were specified but no
   * positions, each trade will be added to a new position.
   *
   * @return the positions, not null
   */
  public Iterable<PortfolioPosition> getPositions() {
    s_logger.info("Starting to process root portfolio: {}", _portfolio.getName());
    return processPortfolio(_portfolio, true, null);
  }

  /**
   * Produce the collection of positions held in a portfolio. A portfolio may consist of any combination of:
   * <ul>
   * <li>recursively nested portfolios</li>
   * <li>positions (which may or may not contain trades)</li>
   * <li>trades</li>
   * </ul>
   * and this method will produce a List of PortfolioPosition objects by examining the above elements.
   * If portfolios are nested, this method will be called recursively noting the portfolio path as the
   * portfolio hieracrhy is decended. Note that this may add in positions which were not in the original
   * xml file e.g. where a set of trades were specified but no
   * positions, each trade will be added to a new position.
   *
   * @param portfolio the portfolio to be examined
   * @param isRoot indicates if the portfolio has no parent i.e. a root node
   * @param parentPath the path to the portfolio (an array of the names of the portfolio's ancestors).
   * @return the positions held by the portfolio
   */
  private List<PortfolioPosition> processPortfolio(Portfolio portfolio, boolean isRoot, String[] parentPath) {

    s_logger.info("Processing portfolio: {}", portfolio.getName());
    List<PortfolioPosition> managedPositions = Lists.newArrayList();

    // This is needed as we don't want the name of the root portfolio to appear in the path. So for
    // a root portfolio we want an empty path, for a child of the root we want just the portfolio name etc.
    String[] portfolioPath = isRoot ? new String[0] : extendPath(parentPath, portfolio.getName());

    for (Portfolio nestedPortfolio : nullCheckIterable(portfolio.getPortfolios())) {

      managedPositions.addAll(processPortfolio(nestedPortfolio, false, portfolioPath));
    }

    for (Position position : nullCheckIterable(portfolio.getPositions())) {

      IdWrapper positionExternalId = position.getExternalSystemId();
      String positionId = positionExternalId != null ? positionExternalId.toExternalId().toString() : "AUTO-CREATED";
      s_logger.debug("Extracting position: [{}]", positionId);

      List<Trade> trades = position.getTrades();
      BigDecimal tradeTotalQuantity = BigDecimal.ZERO;

      // If we have a security defined on the position then we need to
      // check it matches the one from the trades (if there was one)
      ManageableSecurity[] positionSecurity = extractSecurityFromPosition(position.getListedSecurityDefinition());

      for (Trade trade : nullCheckIterable(trades)) {

        s_logger.debug("Extracting trade: {} for position {}", trade.getExternalSystemId().getExternalId(), positionId);
        ManageableSecurity[] tradeSecurity = extractSecurityFromTrade(trade, trades.size());
        if (positionSecurity == null) {

          positionSecurity = tradeSecurity;

        } else if (!Arrays.equals(positionSecurity, tradeSecurity)) {

          throw new PortfolioParsingException("Security must be the same for all trades grouped into a position - " +
                                                  "position has security: [" + positionSecurity[0] +
                                                  "] but found trade with: [" + tradeSecurity[0] + "]");
        }

        tradeTotalQuantity = tradeTotalQuantity.add(trade.getQuantity());
      }

      if (positionSecurity != null) {
        managedPositions.add(createPortfolioPosition(position, positionSecurity, portfolioPath, tradeTotalQuantity));
      } else {
        throw new PortfolioParsingException("No security specified on either trades or position");
      }
    }

    // These trades have not been supplied under positions, but directly in a portfolio
    for (Trade trade : nullCheckIterable(portfolio.getTrades())) {

      // TODO we probably want logic to allow for the aggregation of trades into positions but for now we'll create a position per trade
      ManageableSecurity[] security = extractSecurityFromTrade(trade, 1);
      managedPositions.add(createPortfolioPosition(trade, security, portfolioPath));
    }

    return managedPositions;
  }

  /**
   * Create a new array which is a copy of the path array with
   * the name parameter appended at the end.
   *
   * @param path the path array to be extended
   * @param name the element to append to the array
   * @return the extended array
   */
  private String[] extendPath(String[] path, String name) {

    int oldLength = path.length;
    String[] extended = Arrays.copyOf(path, oldLength  + 1);
    extended[oldLength] = name;
    return extended;
  }

  private ManageableSecurity[] extractSecurityFromPosition(ListedSecurityDefinition listedSecurityDefinition) {

    if (listedSecurityDefinition != null) {
      s_logger.debug("Extracting securities for position");
      return listedSecurityDefinition.getSecurityExtractor().extract();
    } else {
      return null;
    }
  }

  private ManageableSecurity[] extractSecurityFromTrade(Trade trade, int tradesSize) {


    if (tradesSize > 1 && !trade.canBePositionAggregated()) {
      throw new PortfolioParsingException("Trade type [" + trade.getClass() +
                                              "] cannot be aggregated into positions");
    }

    s_logger.debug("Extracting securities for trade: [{}]", trade.getExternalSystemId().toExternalId());
    TradeSecurityExtractor<?> extractor = trade.getSecurityExtractor();
    return extractor.extractSecurities();
  }

  private <T> Iterable<T> nullCheckIterable(Iterable<T> iterable) {
    return iterable == null ? ImmutableList.<T>of() : iterable;
  }

  private PortfolioPosition createPortfolioPosition(Position position,
                                                    ManageableSecurity[] security,
                                                    String[] parentPath,
                                                    BigDecimal tradeQuantity) {
    return new PortfolioPosition(convertPosition(position, security[0], tradeQuantity), security, parentPath);
  }

  private PortfolioPosition createPortfolioPosition(Trade trade, ManageableSecurity[] security, String[] parentPath) {
    return new PortfolioPosition(convertTradeToPosition(trade, security[0]), security, parentPath);
  }

  private ManageablePosition convertTradeToPosition(Trade trade, ManageableSecurity security) {
    ManageablePosition manageablePosition = new ManageablePosition(trade.getQuantity(), security.getExternalIdBundle());
    manageablePosition.addTrade(convertTrade(trade, security));
    return manageablePosition;
  }

  private ManageablePosition convertPosition(Position position, Security security, BigDecimal tradeQuantity) {

    // If the position is supplying a quantity, then we should use that
    // rather than the total quantity obtained from the trades
    BigDecimal positionQuantity = position.getQuantity();
    ManageablePosition manageablePosition = new ManageablePosition(
        positionQuantity != null ? positionQuantity : tradeQuantity, security.getExternalIdBundle());

    IdWrapper externalSystemId = position.getExternalSystemId();
    if (externalSystemId != null) {
      manageablePosition.setProviderId(externalSystemId.toExternalId());
    }

    List<Trade> trades = position.getTrades();
    for (Trade trade : nullCheckIterable(trades)) {
      manageablePosition.addTrade(convertTrade(trade, security));
    }

    manageablePosition.setAttributes(position.getAdditionalAttributes());

    return manageablePosition;
  }

  private ManageableTrade convertTrade(Trade trade, Security security) {

    ManageableTrade manageableTrade = new ManageableTrade(trade.getQuantity(),
                                                          security.getExternalIdBundle(),
                                                          trade.getTradeDate(),
                                                          null,
                                                          trade.getCounterparty().toExternalId());

    ExternalId externalId = trade.getExternalSystemId().toExternalId();

    _xmlExternalIdValidator.validateExternalId(externalId, trade.getId());

    manageableTrade.setProviderId(externalId);

    for (AdditionalCashflow cashflow : nullCheckIterable(trade.getAdditionalCashflows())) {

      if (cashflow.getCashflowType() == AdditionalCashflow.CashflowType.PREMIUM) {
        MonetaryAmount monetaryAmount = cashflow.getMonetaryAmount();
        manageableTrade.setPremium(monetaryAmount.getAmount().doubleValue());
        manageableTrade.setPremiumCurrency(monetaryAmount.getCurrency());
        manageableTrade.setPremiumDate(cashflow.getCashflowDate());
      }
    }

    manageableTrade.setAttributes(trade.getAdditionalAttributes());

    return manageableTrade;
  }


}
TOP

Related Classes of com.opengamma.integration.tool.portfolio.xml.v1_0.conversion.PortfolioConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.