Package com.opengamma.financial.analytics.model.pnl

Source Code of com.opengamma.financial.analytics.model.pnl.AbstractTradeOrDailyPositionPnLFunction

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.pnl;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Clock;
import org.threeten.bp.LocalDate;

import com.google.common.collect.Sets;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeries;
import com.opengamma.core.position.PositionOrTrade;
import com.opengamma.core.position.Trade;
import com.opengamma.core.security.Security;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueProperties.Builder;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.OpenGammaCompilationContext;
import com.opengamma.financial.analytics.model.forex.FXUtils;
import com.opengamma.financial.analytics.timeseries.DateConstraint;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.financial.security.future.FutureSecurity;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolutionResult;
import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolver;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MoneyCalculationUtils;

/**
*
*/
public abstract class AbstractTradeOrDailyPositionPnLFunction extends AbstractFunction.NonCompiledInvoker {

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

  private final String _mark2MarketField;
  private final String _costOfCarryField;
  private final String _resolutionKey;

  /**
   * @param resolutionKey the resolution key, not-null
   * @param mark2MarketField the mark to market data field name, not-null
   * @param costOfCarryField the cost of carry field name, not-null
   */
  public AbstractTradeOrDailyPositionPnLFunction(final String resolutionKey, final String mark2MarketField, final String costOfCarryField) {
    super();
    ArgumentChecker.notNull(resolutionKey, "resolutionKey");
    ArgumentChecker.notNull(mark2MarketField, "mark data field");
    ArgumentChecker.notNull(costOfCarryField, "cost of carry data field");
    _resolutionKey = resolutionKey;
    _mark2MarketField = mark2MarketField;
    _costOfCarryField = costOfCarryField;
  }

  protected abstract LocalDate getPreferredTradeDate(Clock valuationClock, PositionOrTrade positionOrTrade);

  protected abstract DateConstraint getTimeSeriesStartDate(PositionOrTrade positionOrTrade);

  protected abstract DateConstraint getTimeSeriesEndDate(PositionOrTrade positionOrTrade);

  protected abstract LocalDate checkAvailableData(LocalDate originalTradeDate, HistoricalTimeSeries markToMarketSeries, Security security, String markDataField, String resolutionKey);

  protected abstract String getResultValueRequirementName();

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
    final ValueRequirement desiredValue = desiredValues.iterator().next();
    BigDecimal tradeValue = null;
    HistoricalTimeSeries htsMarkToMarket = null;
    HistoricalTimeSeries htsCostOfCarry = null;
    final PositionOrTrade trade = target.getPositionOrTrade();
    for (final ComputedValue input : inputs.getAllValues()) {
      if (ValueRequirementNames.VALUE.equals(input.getSpecification().getValueName())) {
        tradeValue = BigDecimal.valueOf((Double) input.getValue());
        if (trade instanceof Trade) {
          // Need to scale the value by the trade quantity
          tradeValue = ((Trade) trade).getQuantity().multiply(tradeValue);
        }
      } else if (ValueRequirementNames.HISTORICAL_TIME_SERIES.equals(input.getSpecification().getValueName())) {
        final String field = input.getSpecification().getProperty(HistoricalTimeSeriesFunctionUtils.DATA_FIELD_PROPERTY);
        if (_costOfCarryField.equals(field)) {
          htsCostOfCarry = (HistoricalTimeSeries) input.getValue();
        } else if (_mark2MarketField.equals(field)) {
          htsMarkToMarket = (HistoricalTimeSeries) input.getValue();
        }
      }
    }
    final Security security = trade.getSecurity();
    LocalDate tradeDate = getPreferredTradeDate(executionContext.getValuationClock(), trade);
    tradeDate = checkAvailableData(tradeDate, htsMarkToMarket, security, _mark2MarketField, _resolutionKey);
    final ValueSpecification valueSpecification = new ValueSpecification(getResultValueRequirementName(), target.toSpecification(), desiredValue.getConstraints());
    final double costOfCarry = getCostOfCarry(security, tradeDate, htsCostOfCarry);
    Double markToMarket = htsMarkToMarket.getTimeSeries().getValue(tradeDate);
    if (security instanceof FutureSecurity) {
      final FutureSecurity futureSecurity = (FutureSecurity) security;
      markToMarket = markToMarket * futureSecurity.getUnitAmount();
    }
    final BigDecimal dailyPnL = tradeValue.subtract(trade.getQuantity().multiply(BigDecimal.valueOf(markToMarket + costOfCarry)));
    s_logger.debug("{}  security: {} quantity: {} fairValue: {} markToMarket: {} costOfCarry: {} dailyPnL: {}",
          new Object[] {trade.getUniqueId(), trade.getSecurity().getExternalIdBundle(), trade.getQuantity(), tradeValue, markToMarket, costOfCarry, dailyPnL });
    final ComputedValue result = new ComputedValue(valueSpecification, MoneyCalculationUtils.rounded(dailyPnL).doubleValue());
    return Sets.newHashSet(result);
  }

  private double getCostOfCarry(final Security security, final LocalDate tradeDate, final HistoricalTimeSeries costOfCarryTS) {
    double result = 0.0d;
    if (costOfCarryTS != null) {
      final Double histCost = costOfCarryTS.getTimeSeries().getValue(tradeDate);
      if (histCost != null) {
        result = histCost;
      }
    }
    return result;
  }

  @Override
  public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
    final PositionOrTrade positionOrTrade = target.getPositionOrTrade();
    final Security security = positionOrTrade.getSecurity();
    final ValueRequirement securityOrTradeValue;
    if (positionOrTrade instanceof Trade) {
      // If a TRADE, request the SECURITY's value and scale up during the execute
      securityOrTradeValue = new ValueRequirement(ValueRequirementNames.VALUE, ComputationTargetType.SECURITY, security.getUniqueId(), getCurrencyProperty(security));
    } else {
      // If a POSITION, request the POSITION's value and DON'T scale during the execute
      securityOrTradeValue = new ValueRequirement(ValueRequirementNames.VALUE, target.toSpecification(), getCurrencyProperty(security));
    }
    final HistoricalTimeSeriesResolver resolver = OpenGammaCompilationContext.getHistoricalTimeSeriesResolver(context);
    final ExternalIdBundle bundle = security.getExternalIdBundle();
    final DateConstraint startDate = getTimeSeriesStartDate(positionOrTrade);
    final DateConstraint endDate = getTimeSeriesEndDate(positionOrTrade);
    final ValueRequirement markToMarketValue = getMarkToMarketSeriesRequirement(resolver, bundle, startDate, endDate);
    final ValueRequirement costOfCarryValue = getCostOfCarrySeriesRequirement(resolver, bundle, endDate);

    if (markToMarketValue == null && costOfCarryValue == null) {
      return null;
    }

    final Set<ValueRequirement> requirements = Sets.newHashSet(securityOrTradeValue);
    if (markToMarketValue != null) {
      requirements.add(markToMarketValue);
    }
    if (costOfCarryValue != null) {
      requirements.add(costOfCarryValue);
    }
    return requirements;
  }

  protected ValueProperties getCurrencyProperty(final Security security) {
    final Currency ccy = FinancialSecurityUtils.getCurrency(security);
    if (ccy != null) {
      return ValueProperties.with(ValuePropertyNames.CURRENCY, ccy.getCode()).get();
    } else {
      return ValueProperties.none();
    }
  }

  private ValueRequirement getMarkToMarketSeriesRequirement(final HistoricalTimeSeriesResolver resolver, final ExternalIdBundle bundle, final DateConstraint startDate, final DateConstraint endDate) {
    final HistoricalTimeSeriesResolutionResult timeSeries = resolver.resolve(bundle, null, null, null, _mark2MarketField, _resolutionKey);
    if (timeSeries == null) {
      return null;
    }
    return HistoricalTimeSeriesFunctionUtils.createHTSRequirement(timeSeries, _mark2MarketField, startDate, true, endDate, true);
  }

  private ValueRequirement getCostOfCarrySeriesRequirement(final HistoricalTimeSeriesResolver resolver, final ExternalIdBundle bundle, final DateConstraint endDate) {
    final HistoricalTimeSeriesResolutionResult timeSeries = resolver.resolve(bundle, null, null, null, _costOfCarryField, _resolutionKey);
    if (timeSeries == null) {
      return null;
    }
    return HistoricalTimeSeriesFunctionUtils.createHTSRequirement(timeSeries, _costOfCarryField, endDate, true, endDate, true);
  }

  @Override
  public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
    return !FXUtils.isFXSecurity(target.getPositionOrTrade().getSecurity());
  }

  protected ValueProperties.Builder createValueProperties(final ComputationTarget target) {
    final ValueProperties.Builder properties = createValueProperties();
    final Currency ccy = FinancialSecurityUtils.getCurrency(target.getPositionOrTrade().getSecurity());
    if (ccy != null) {
      properties.with(ValuePropertyNames.CURRENCY, ccy.getCode());
    }
    return properties;
  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
    return Collections.singleton(new ValueSpecification(getResultValueRequirementName(), target.toSpecification(), createValueProperties(target).get()));
  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
    if (inputs.isEmpty()) {
      return null;
    }
    UniqueId uidMarkToMarket = null;
    UniqueId uidCostOfCarry = null;
    for (final Map.Entry<ValueSpecification, ValueRequirement> input : inputs.entrySet()) {
      if (ValueRequirementNames.HISTORICAL_TIME_SERIES.equals(input.getValue().getValueName())) {
        if ("MarkToMarket".equals(input.getValue().getConstraint(".name"))) {
          uidMarkToMarket = input.getKey().getTargetSpecification().getUniqueId();
        } else {
          uidCostOfCarry = input.getKey().getTargetSpecification().getUniqueId();
        }
      }
    }

    final Builder propertiesBuilder = createValueProperties(target);
    if (uidMarkToMarket != null) {
      propertiesBuilder.with("MarkToMarketTimeSeries", uidMarkToMarket.toString());
    }
    if (uidCostOfCarry != null) {
      propertiesBuilder.with("CostOfCarryTimeSeries",  uidCostOfCarry.toString());
    }
    return Collections.singleton(new ValueSpecification(getResultValueRequirementName(), target.toSpecification(), propertiesBuilder.get()));
  }

}
TOP

Related Classes of com.opengamma.financial.analytics.model.pnl.AbstractTradeOrDailyPositionPnLFunction

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.