Package com.opengamma.financial.analytics.model.forex.option.vannavolga

Source Code of com.opengamma.financial.analytics.model.forex.option.vannavolga.FXOptionVannaVolgaFunction

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

import static com.opengamma.financial.analytics.model.YieldCurveFunctionUtils.getCurveRequirement;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionBlackFunction.CALL_CURVE;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionBlackFunction.CALL_CURVE_CALC_CONFIG;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionBlackFunction.PUT_CURVE;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionBlackFunction.PUT_CURVE_CALC_CONFIG;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionFunctionUtils.getCurveForCurrency;
import static com.opengamma.financial.analytics.model.forex.option.black.FXOptionFunctionUtils.getSurfaceRequirement;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.instrument.InstrumentDefinition;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve;
import com.opengamma.analytics.financial.model.option.definition.SmileDeltaParameters;
import com.opengamma.analytics.financial.model.option.definition.SmileDeltaTermStructureVannaVolgaDataBundle;
import com.opengamma.analytics.financial.model.volatility.surface.SmileDeltaTermStructureParameters;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
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.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
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.conversion.ForexSecurityConverter;
import com.opengamma.financial.analytics.model.InterpolatedDataProperties;
import com.opengamma.financial.analytics.model.forex.ConventionBasedFXRateFunction;
import com.opengamma.financial.analytics.model.forex.ForexVisitors;
import com.opengamma.financial.currency.CurrencyPair;
import com.opengamma.financial.currency.CurrencyPairs;
import com.opengamma.financial.security.FinancialSecurity;
import com.opengamma.financial.security.FinancialSecurityTypes;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.UnorderedCurrencyPair;
import com.opengamma.util.tuple.Pair;

/**
*
*/
public abstract class FXOptionVannaVolgaFunction extends AbstractFunction.NonCompiledInvoker {
  /** Property name for the delta to use */
  public static final String PROPERTY_OTM_DELTA = "DeltaOTM";
  /** The name of the calculation method */
  public static final String VANNA_VOLGA_METHOD = "VannaVolgaMethod";
  private static final Logger s_logger = LoggerFactory.getLogger(FXOptionVannaVolgaFunction.class);
  private final String _valueRequirementName;

  public FXOptionVannaVolgaFunction(final String valueRequirementName) {
    ArgumentChecker.notNull(valueRequirementName, "value requirement name");
    _valueRequirementName = valueRequirementName;
  }

  @Override
  public ComputationTargetType getTargetType() {
    return FinancialSecurityTypes.FX_OPTION_SECURITY;
  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
    final ValueProperties properties = getResultProperties(target);
    return Collections.singleton(new ValueSpecification(_valueRequirementName, target.toSpecification(), properties));
  }

  @Override
  public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
    final ValueProperties constraints = desiredValue.getConstraints();
    final Set<String> interpolatorNames = constraints.getValues(InterpolatedDataProperties.X_INTERPOLATOR_NAME);
    if (interpolatorNames == null || interpolatorNames.size() != 1) {
      return null;
    }
    final Set<String> leftExtrapolatorNames = constraints.getValues(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME);
    if (leftExtrapolatorNames == null || leftExtrapolatorNames.size() != 1) {
      return null;
    }
    final Set<String> rightExtrapolatorNames = constraints.getValues(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME);
    if (rightExtrapolatorNames == null || rightExtrapolatorNames.size() != 1) {
      return null;
    }
    final Set<String> putCurveNames = constraints.getValues(PUT_CURVE);
    if (putCurveNames == null || putCurveNames.size() != 1) {
      return null;
    }
    final Set<String> callCurveNames = constraints.getValues(CALL_CURVE);
    if (callCurveNames == null || callCurveNames.size() != 1) {
      return null;
    }
    final Set<String> putCurveCalculationConfigs = constraints.getValues(PUT_CURVE_CALC_CONFIG);
    if (putCurveCalculationConfigs == null || putCurveCalculationConfigs.size() != 1) {
      return null;
    }
    final Set<String> callCurveCalculationConfigs = constraints.getValues(CALL_CURVE_CALC_CONFIG);
    if (callCurveCalculationConfigs == null || callCurveCalculationConfigs.size() != 1) {
      return null;
    }
    final Set<String> surfaceNames = constraints.getValues(ValuePropertyNames.SURFACE);
    if (surfaceNames == null || surfaceNames.size() != 1) {
      s_logger.error("Need one surface name; have " + surfaceNames);
    }
    final Set<String> deltas = constraints.getValues(PROPERTY_OTM_DELTA);
    if (deltas == null || deltas.size() != 1) {
      return null;
    }
    final String surfaceName = Iterables.getOnlyElement(surfaceNames);
    final String interpolatorName = Iterables.getOnlyElement(interpolatorNames);
    final String leftExtrapolatorName = Iterables.getOnlyElement(leftExtrapolatorNames);
    final String rightExtrapolatorName = Iterables.getOnlyElement(rightExtrapolatorNames);
    final String putCurveName = Iterables.getOnlyElement(putCurveNames);
    final String putCurveCalculationConfig = Iterables.getOnlyElement(putCurveCalculationConfigs);
    final String callCurveName = Iterables.getOnlyElement(callCurveNames);
    final String callCurveCalculationConfig = Iterables.getOnlyElement(callCurveCalculationConfigs);
    final FinancialSecurity security = (FinancialSecurity) target.getSecurity();
    final Currency putCurrency = security.accept(ForexVisitors.getPutCurrencyVisitor());
    final Currency callCurrency = security.accept(ForexVisitors.getCallCurrencyVisitor());
    final ValueRequirement putFundingCurve = getCurveRequirement(ComputationTargetSpecification.of(putCurrency), putCurveName, putCurveCalculationConfig);
    final ValueRequirement callFundingCurve = getCurveRequirement(ComputationTargetSpecification.of(callCurrency), callCurveName, callCurveCalculationConfig);
    final ValueRequirement fxVolatilitySurface = getSurfaceRequirement(surfaceName, putCurrency, callCurrency, interpolatorName, leftExtrapolatorName, rightExtrapolatorName);
    final UnorderedCurrencyPair currencyPair = UnorderedCurrencyPair.of(putCurrency, callCurrency);
    final ValueRequirement spotRequirement = ConventionBasedFXRateFunction.getSpotRateRequirement(currencyPair);
    final ValueRequirement pairQuoteRequirement = new ValueRequirement(ValueRequirementNames.CURRENCY_PAIRS, ComputationTargetType.PRIMITIVE, currencyPair.getUniqueId());
    return Sets.newHashSet(putFundingCurve, callFundingCurve, fxVolatilitySurface, spotRequirement, pairQuoteRequirement);
  }

  protected abstract ValueProperties getResultProperties(ComputationTarget target);

  protected abstract ValueProperties getResultProperties(ComputationTarget target, ValueRequirement desiredValue, CurrencyPair baseQuotePair);

  protected ValueSpecification getSpecification(final ComputationTarget target, final ValueRequirement desiredValue, final CurrencyPair baseQuotePair) {
    final ValueProperties properties = getResultProperties(target, desiredValue, baseQuotePair);
    return new ValueSpecification(_valueRequirementName, target.toSpecification(), properties);
  }

  protected String[] getCurveNames(final Currency putCurrency, final String putCurveName, final Currency callCurrency, final String callCurveName,
      final CurrencyPairs baseQuotePairs) {
    final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(putCurrency, callCurrency);
    final String fullPutCurveName = putCurveName + "_" + putCurrency.getCode();
    final String fullCallCurveName = callCurveName + "_" + callCurrency.getCode();
    if (baseQuotePair.getBase().equals(putCurrency)) { // To get Base/quote in market standard order.
      return new String[] {fullPutCurveName, fullCallCurveName };
    }
    return new String[] {fullCallCurveName, fullPutCurveName };
  }

  protected InstrumentDerivative getDerivative(final FinancialSecurity security, final String[] allCurveNames, final CurrencyPairs baseQuotePairs, final ZonedDateTime now) {
    final InstrumentDefinition<?> definition = security.accept(new ForexSecurityConverter(baseQuotePairs));
    return definition.toDerivative(now, allCurveNames);
  }

  protected SmileDeltaTermStructureVannaVolgaDataBundle getSmiles(final Currency putCurrency, final Currency callCurrency, final String[] allCurveNames,
      final CurrencyPairs baseQuotePairs, final String deltaName, final FunctionInputs inputs) {
    final double delta = Double.parseDouble(deltaName);
    if (Double.compare(delta, 0.5) == 0) {
      throw new OpenGammaRuntimeException("Asking for OTM smile at delta = 50; this is the ATM value");
    }
    final Object volatilitySurfaceObject = inputs.getValue(ValueRequirementNames.STANDARD_VOLATILITY_SURFACE_DATA);
    if (volatilitySurfaceObject == null) {
      throw new OpenGammaRuntimeException("Could not get volatility surface data");
    }
    final SmileDeltaTermStructureParameters allSmiles = (SmileDeltaTermStructureParameters) volatilitySurfaceObject;
    final double[] uniqueDeltas = allSmiles.getDelta();
    final int putDeltaIndex = Arrays.binarySearch(uniqueDeltas, delta);
    if (putDeltaIndex < 0) {
      throw new OpenGammaRuntimeException("Could not get OTM smile for delta = " + delta);
    }
    final SmileDeltaParameters[] surface = new SmileDeltaParameters[allSmiles.getNumberExpiration()];
    final int atmIndex = (allSmiles.getNumberStrike() - 1) / 2;
    final double[] deltas = {delta };
    for (int i = 0; i < allSmiles.getNumberExpiration(); i++) {
      final SmileDeltaParameters parameters = allSmiles.getSmileForTime(i);
      final double timeToExpiration = parameters.getTimeToExpiry();
      final double[] volatilities = new double[3];
      final double[] allVolatilities = parameters.getVolatility();
      volatilities[0] = allVolatilities[putDeltaIndex];
      volatilities[1] = allVolatilities[atmIndex];
      volatilities[2] = allVolatilities[2 * atmIndex - putDeltaIndex];
      surface[i] = new SmileDeltaParameters(timeToExpiration, deltas, volatilities);
    }
    final Interpolator1D interpolator = allSmiles.getTimeInterpolator();
    final SmileDeltaTermStructureParameters resultSmiles = new SmileDeltaTermStructureParameters(surface, interpolator);
    final Currency ccy1;
    final Currency ccy2;
    final Object spotObject = inputs.getValue(ValueRequirementNames.SPOT_RATE);
    if (spotObject == null) {
      throw new OpenGammaRuntimeException("Could not get spot requirement");
    }
    final double spot = (Double) spotObject;
    final CurrencyPair baseQuotePair = baseQuotePairs.getCurrencyPair(putCurrency, callCurrency);
    if (baseQuotePair == null) {
      throw new OpenGammaRuntimeException("Could not get base/quote pair for currency pair (" + putCurrency + ", " + callCurrency + ")");
    }
    YieldAndDiscountCurve[] curves;
    final YieldAndDiscountCurve putFundingCurve = getCurveForCurrency(inputs, putCurrency);
    final YieldAndDiscountCurve callFundingCurve = getCurveForCurrency(inputs, callCurrency);
    final Map<String, Currency> curveCurrency = new HashMap<String, Currency>();
    if (baseQuotePair.getBase().equals(putCurrency)) { // To get Base/quote in market standard order.
      ccy1 = putCurrency;
      ccy2 = callCurrency;
      curves = new YieldAndDiscountCurve[] {putFundingCurve, callFundingCurve };
      curveCurrency.put(allCurveNames[0], putCurrency);
      curveCurrency.put(allCurveNames[1], callCurrency);
    } else {
      curves = new YieldAndDiscountCurve[] {callFundingCurve, putFundingCurve };
      ccy1 = callCurrency;
      ccy2 = putCurrency;
      curveCurrency.put(allCurveNames[1], putCurrency);
      curveCurrency.put(allCurveNames[0], callCurrency);
    }
    final YieldCurveBundle yieldCurves = new YieldCurveBundle(allCurveNames, curves);
    final FXMatrix fxMatrix = new FXMatrix(ccy1, ccy2, spot);
    final YieldCurveBundle curvesWithFX = new YieldCurveBundle(fxMatrix, curveCurrency, yieldCurves.getCurvesMap());
    final Pair<Currency, Currency> ccyPair = Pair.of(ccy1, ccy2);
    return new SmileDeltaTermStructureVannaVolgaDataBundle(curvesWithFX, resultSmiles, ccyPair);
  }

  protected String getValueRequirementName() {
    return _valueRequirementName;
  }
}
TOP

Related Classes of com.opengamma.financial.analytics.model.forex.option.vannavolga.FXOptionVannaVolgaFunction

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.