Package com.opengamma.financial.analytics.model.equity

Source Code of com.opengamma.financial.analytics.model.equity.EquityForwardCurveFunction

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

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.equity.variance.pricing.AffineDividends;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurveAffineDividends;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurveYieldImplied;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve;
import com.opengamma.analytics.math.curve.ConstantDoublesCurve;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
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.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.analytics.model.curve.forward.ForwardCurveValuePropertyNames;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdentifiable;
import com.opengamma.id.ExternalScheme;
import com.opengamma.util.money.Currency;

/**
* Function produces a FORWARD_CURVE given YIELD_CURVE and Equity MARKET_VALUE
* Simple implementation does not include any Dividend treatment
*/
public class EquityForwardCurveFunction extends AbstractFunction.NonCompiledInvoker {

  private static final Set<ExternalScheme> s_validSchemes = ImmutableSet.of(ExternalSchemes.BLOOMBERG_TICKER, ExternalSchemes.BLOOMBERG_TICKER_WEAK, ExternalSchemes.ACTIVFEED_TICKER);

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
    final ValueProperties properties = createValueProperties()
        .with(ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_CALCULATION_METHOD, ForwardCurveValuePropertyNames.PROPERTY_YIELD_CURVE_IMPLIED_METHOD)
        .withAny(ValuePropertyNames.CURVE_CURRENCY)
        .withAny(ValuePropertyNames.CURVE)
        .withAny(ValuePropertyNames.CURVE_CALCULATION_CONFIG)
        .withAny(ValuePropertyNames.DIVIDEND_TYPE)
        .get();
    return Collections.singleton(new ValueSpecification(ValueRequirementNames.FORWARD_CURVE, target.toSpecification(), properties));
  }

  // REVIEW Andrew 2012-01-17 -- Can we make the target type of this SECURITY, or even EQUITY_SECURITY ?

  @Override
  public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
    if (target.getValue() instanceof ExternalIdentifiable) {
      final ExternalId identifier = ((ExternalIdentifiable) target.getValue()).getExternalId();
      return s_validSchemes.contains(identifier.getScheme());
    }
    return false;
  }

  @Override
  public boolean canHandleMissingInputs() {
    // dividend yield may not be available
    return true;
  }

  /* Spot value of the equity index or name */
  private ValueRequirement getSpotRequirement(final ComputationTarget target) {
    return new ValueRequirement(MarketDataRequirementNames.MARKET_VALUE, ComputationTargetType.PRIMITIVE, target.getUniqueId());
  }

  /* Funding curve of the equity's currency */
  private ValueRequirement getFundingCurveRequirement(final Currency ccy, final String curveName, final String curveCalculationConfig) {
    final ValueProperties fundingProperties = ValueProperties.builder()  // Note that createValueProperties is _not_ used - otherwise engine can't find the requirement
        .with(ValuePropertyNames.CURVE, curveName)
        .with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfig)
        .get();
    return new ValueRequirement(ValueRequirementNames.YIELD_CURVE, ComputationTargetSpecification.of(ccy), fundingProperties);
  }

  @Override
  /* If a requirement is not found, return null, and go looking for a default */
  public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
    final Set<ValueRequirement> requirements = new HashSet<>();
    final ValueProperties constraints = desiredValue.getConstraints();

    // Spot Requirement
    requirements.add(getSpotRequirement(target));

    // Funding Curve Currency
    final Set<String> ccyConstraint = constraints.getValues(ValuePropertyNames.CURVE_CURRENCY);
    if (ccyConstraint == null || ccyConstraint.size() != 1) {
      return null;
    }
    final Currency currency = Currency.of(ccyConstraint.iterator().next());
    // Funding Curve Name
    final Set<String> fundingCurveNameSet = constraints.getValues(ValuePropertyNames.CURVE);
    if (fundingCurveNameSet  == null || fundingCurveNameSet.size() != 1) {
      return null;
    }
    final String fundingCurveName = fundingCurveNameSet.iterator().next();
    final Set<String> curveCalculationConfigs = constraints.getValues(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
    if (curveCalculationConfigs == null || curveCalculationConfigs.size() != 1) {
      return null;
    }
    final String curveCalculationConfig = Iterables.getOnlyElement(curveCalculationConfigs);
    // Funding Curve Requirement
    requirements.add(getFundingCurveRequirement(currency, fundingCurveName, curveCalculationConfig));

    // Dividend Requirements depend on type
    final Set<String> dividendTypeSet = constraints.getValues(ValuePropertyNames.DIVIDEND_TYPE);
    if (dividendTypeSet == null || dividendTypeSet.size() != 1) {
      return null;
    }
    final String dividendType = dividendTypeSet.iterator().next();
    if (ValuePropertyNames.DIVIDEND_TYPE_DISCRETE.equalsIgnoreCase(dividendType)) {
      requirements.add(new ValueRequirement(ValueRequirementNames.AFFINE_DIVIDENDS, ComputationTargetType.PRIMITIVE, target.getUniqueId()))
    } else if (ValuePropertyNames.DIVIDEND_TYPE_CONTINUOUS.equalsIgnoreCase(dividendType)) {
      requirements.add(new ValueRequirement(MarketDataRequirementNames.DIVIDEND_YIELD, ComputationTargetType.PRIMITIVE, target.getUniqueId()));
    }
    return requirements;
  }

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {

    // desiredValues is defined by getResults. In our case, a singleton
    final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);

    // Spot
    final Double spot = (Double) inputs.getValue(MarketDataRequirementNames.MARKET_VALUE);
    if (spot == null) {
      throw new OpenGammaRuntimeException("Failed to get spot value requirement: " + target.getName());
    }
    final String curveCalculationConfig = desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
    // Curve Currency
    final String ccyName = desiredValue.getConstraint(ValuePropertyNames.CURVE_CURRENCY);
    if (ccyName == null) {
      throw new OpenGammaRuntimeException("Failed to find " + ValuePropertyNames.CURVE_CURRENCY);
    }
    // Funding
    final String fundingCurveName = desiredValue.getConstraint(ValuePropertyNames.CURVE);
    final Object fundingCurveObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE);
    if (fundingCurveObject == null) {
      throw new OpenGammaRuntimeException("Failed to get funding curve requirement");
    }
    final YieldCurve fundingCurve = (YieldCurve) fundingCurveObject;
    // Dividend type: Discrete or Continuous
    final String dividendType = desiredValue.getConstraint(ValuePropertyNames.DIVIDEND_TYPE);
    boolean isContinuousDividends = ValuePropertyNames.DIVIDEND_TYPE_CONTINUOUS.equalsIgnoreCase(dividendType);
    // Compute ForwardCurve
    final ForwardCurve forwardCurve;
    if (isContinuousDividends) {
      // Cost of Carry - if no dividend yield available set 0 cost of carry
      final Double dividendYieldObject = (Double) inputs.getValue(MarketDataRequirementNames.DIVIDEND_YIELD);
      final double dividendYield = dividendYieldObject == null ? 0.0 : dividendYieldObject.doubleValue();
      final YieldCurve costOfCarryCurve = YieldCurve.from(ConstantDoublesCurve.from(dividendYield, "CostOfCarry"));
      forwardCurve = new ForwardCurveYieldImplied(spot, fundingCurve, costOfCarryCurve);     
    } else {
      Object discreteDividendsInput = inputs.getValue(ValueRequirementNames.AFFINE_DIVIDENDS);
      if ((discreteDividendsInput != null) && (discreteDividendsInput instanceof AffineDividends)) {
        final AffineDividends discreteDividends = (AffineDividends) discreteDividendsInput;
        forwardCurve = new ForwardCurveAffineDividends(spot, fundingCurve, discreteDividends);
      } else {
        forwardCurve = new ForwardCurveYieldImplied(spot, fundingCurve, YieldCurve.from(ConstantDoublesCurve.from(0.0, "CostOfCarry")));
      }
    }
   
    final ValueProperties properties = createValueProperties()
        .with(ForwardCurveValuePropertyNames.PROPERTY_FORWARD_CURVE_CALCULATION_METHOD, ForwardCurveValuePropertyNames.PROPERTY_YIELD_CURVE_IMPLIED_METHOD)
        .with(ValuePropertyNames.CURVE, fundingCurveName)
        .with(ValuePropertyNames.CURVE_CURRENCY, ccyName)
        .with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfig)
        .with(ValuePropertyNames.DIVIDEND_TYPE, dividendType)
        .get();

    final ValueSpecification resultSpec = new ValueSpecification(ValueRequirementNames.FORWARD_CURVE, target.toSpecification(), properties);
    return Collections.singleton(new ComputedValue(resultSpec, forwardCurve));
  }

  @Override
  public ComputationTargetType getTargetType() {
    return ComputationTargetType.PRIMITIVE;
  }
}
TOP

Related Classes of com.opengamma.financial.analytics.model.equity.EquityForwardCurveFunction

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.