/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.sabrcube;
import static com.opengamma.engine.value.ValueRequirementNames.PRESENT_VALUE_SABR_ALPHA_SENSITIVITY;
import static com.opengamma.engine.value.ValueRequirementNames.PRESENT_VALUE_SABR_NU_SENSITIVITY;
import static com.opengamma.engine.value.ValueRequirementNames.PRESENT_VALUE_SABR_RHO_SENSITIVITY;
import static com.opengamma.engine.value.ValueRequirementNames.SABR_SURFACES;
import static com.opengamma.engine.value.ValueRequirementNames.VOLATILITY_CUBE_FITTED_POINTS;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.model.option.definition.SABRInterestRateDataBundle;
import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory;
import com.opengamma.analytics.math.interpolation.GridInterpolator2D;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.surface.InterpolatedDoublesSurface;
import com.opengamma.core.security.Security;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.SurfaceAndCubePropertyNames;
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.DoubleLabelledMatrix2D;
import com.opengamma.financial.analytics.DoubleLabelledMatrix3D;
import com.opengamma.financial.analytics.ircurve.calcconfig.MultiCurveCalculationConfig;
import com.opengamma.financial.analytics.model.InterpolatedDataProperties;
import com.opengamma.financial.analytics.model.SABRVegaCalculationUtils;
import com.opengamma.financial.analytics.model.VegaMatrixUtils;
import com.opengamma.financial.analytics.model.YieldCurveFunctionUtils;
import com.opengamma.financial.analytics.model.sabr.SABRDiscountingFunction;
import com.opengamma.financial.analytics.model.volatility.SmileFittingPropertyNamesAndValues;
import com.opengamma.financial.analytics.model.volatility.cube.fitted.FittedSmileDataPoints;
import com.opengamma.financial.analytics.volatility.fittedresults.SABRFittedSurfaces;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.util.money.Currency;
import com.opengamma.util.tuple.DoublesPair;
/**
* Base class for functions that calculate vega for swaptions, CMS, cap/floors and cap/floor CMS spreads using the SABR model.
*
* @deprecated Use descendants of {@link SABRDiscountingFunction}
*/
@Deprecated
public abstract class SABRVegaFunction extends SABRFunction {
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final ValueRequirement desiredValue = desiredValues.iterator().next();
final Currency currency = FinancialSecurityUtils.getCurrency(target.getSecurity());
final String curveCalculationConfigName = desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG);
final MultiCurveCalculationConfig curveCalculationConfig = getCurveCalculationConfigSource().getConfig(curveCalculationConfigName);
if (curveCalculationConfig == null) {
throw new OpenGammaRuntimeException("Could not find curve calculation configuration named " + curveCalculationConfigName);
}
final YieldCurveBundle curves = YieldCurveFunctionUtils.getYieldCurves(inputs, curveCalculationConfig);
final SABRInterestRateDataBundle data = getModelParameters(target, inputs, currency, curves, desiredValue);
final Object alphaSensitivityObject = inputs.getValue(PRESENT_VALUE_SABR_ALPHA_SENSITIVITY);
if (alphaSensitivityObject == null) {
throw new OpenGammaRuntimeException("Could not get alpha sensitivity");
}
final Object nuSensitivityObject = inputs.getValue(PRESENT_VALUE_SABR_NU_SENSITIVITY);
if (nuSensitivityObject == null) {
throw new OpenGammaRuntimeException("Could not get nu sensitivity");
}
final Object rhoSensitivityObject = inputs.getValue(PRESENT_VALUE_SABR_RHO_SENSITIVITY);
if (rhoSensitivityObject == null) {
throw new OpenGammaRuntimeException("Could not get rho sensitivity");
}
final Object sabrSurfacesObject = inputs.getValue(SABR_SURFACES);
if (sabrSurfacesObject == null) {
throw new OpenGammaRuntimeException("Could not get SABR fitted surfaces");
}
final SABRFittedSurfaces sabrFittedSurfaces = (SABRFittedSurfaces) sabrSurfacesObject;
final Object fittedDataPointsObject = inputs.getValue(VOLATILITY_CUBE_FITTED_POINTS);
if (fittedDataPointsObject == null) {
throw new OpenGammaRuntimeException("Could not get fitted points for cube");
}
final FittedSmileDataPoints fittedDataPoints = (FittedSmileDataPoints) fittedDataPointsObject;
final Map<DoublesPair, DoubleMatrix2D> inverseJacobians = sabrFittedSurfaces.getInverseJacobians();
final DoubleLabelledMatrix2D alphaSensitivity = (DoubleLabelledMatrix2D) alphaSensitivityObject;
final DoubleLabelledMatrix2D nuSensitivity = (DoubleLabelledMatrix2D) nuSensitivityObject;
final DoubleLabelledMatrix2D rhoSensitivity = (DoubleLabelledMatrix2D) rhoSensitivityObject;
final double expiry = alphaSensitivity.getXKeys()[0];
final double maturity = alphaSensitivity.getYKeys()[0];
final double alpha = alphaSensitivity.getValues()[0][0];
final double nu = nuSensitivity.getValues()[0][0];
final double rho = rhoSensitivity.getValues()[0][0];
final InterpolatedDoublesSurface alphaSurface = data.getSABRParameter().getAlphaSurface();
final Map<Double, Interpolator1DDataBundle> alphaDataBundle = (Map<Double, Interpolator1DDataBundle>) alphaSurface.getInterpolatorData();
final InterpolatedDoublesSurface nuSurface = data.getSABRParameter().getNuSurface();
final Map<Double, Interpolator1DDataBundle> nuDataBundle = (Map<Double, Interpolator1DDataBundle>) nuSurface.getInterpolatorData();
final InterpolatedDoublesSurface rhoSurface = data.getSABRParameter().getRhoSurface();
final Map<Double, Interpolator1DDataBundle> rhoDataBundle = (Map<Double, Interpolator1DDataBundle>) rhoSurface.getInterpolatorData();
final DoublesPair expiryMaturity = DoublesPair.of(expiry, maturity);
final String xInterpolatorName = desiredValue.getConstraint(InterpolatedDataProperties.X_INTERPOLATOR_NAME);
final String xLeftExtrapolatorName = desiredValue.getConstraint(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME);
final String xRightExtrapolatorName = desiredValue.getConstraint(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME);
final String yInterpolatorName = desiredValue.getConstraint(InterpolatedDataProperties.Y_INTERPOLATOR_NAME);
final String yLeftExtrapolatorName = desiredValue.getConstraint(InterpolatedDataProperties.LEFT_Y_EXTRAPOLATOR_NAME);
final String yRightExtrapolatorName = desiredValue.getConstraint(InterpolatedDataProperties.RIGHT_Y_EXTRAPOLATOR_NAME);
final Interpolator1D xInterpolator = CombinedInterpolatorExtrapolatorFactory.getInterpolator(xInterpolatorName, xLeftExtrapolatorName, xRightExtrapolatorName);
final Interpolator1D yInterpolator = CombinedInterpolatorExtrapolatorFactory.getInterpolator(yInterpolatorName, yLeftExtrapolatorName, yRightExtrapolatorName);
final GridInterpolator2D nodeSensitivityCalculator = new GridInterpolator2D(xInterpolator, yInterpolator);
final Map<Double, DoubleMatrix2D> result = SABRVegaCalculationUtils.getVegaCube(alpha, rho, nu, alphaDataBundle, rhoDataBundle, nuDataBundle, inverseJacobians, expiryMaturity,
nodeSensitivityCalculator);
final DoubleLabelledMatrix3D labelledMatrix = VegaMatrixUtils.getVegaSwaptionCubeQuoteMatrix(fittedDataPoints.getFittedPoints(), result);
final ValueProperties properties = getResultProperties(createValueProperties().get(), currency.getCode(), desiredValue);
final ValueSpecification spec = new ValueSpecification(getValueRequirement(), target.toSpecification(), properties);
return Collections.singleton(new ComputedValue(spec, labelledMatrix));
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
final Set<ValueRequirement> requirements = super.getRequirements(context, target, desiredValue);
if (requirements == null) {
return null;
}
final ValueProperties constraints = desiredValue.getConstraints();
final Set<String> xInterpolators = constraints.getValues(InterpolatedDataProperties.X_INTERPOLATOR_NAME);
if (xInterpolators == null || xInterpolators.size() != 1) {
return null;
}
final Set<String> xLeftExtrapolators = constraints.getValues(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME);
if (xLeftExtrapolators == null || xLeftExtrapolators.size() != 1) {
return null;
}
final Set<String> xRightExtrapolators = constraints.getValues(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME);
if (xRightExtrapolators == null || xRightExtrapolators.size() != 1) {
return null;
}
final Set<String> yInterpolators = constraints.getValues(InterpolatedDataProperties.Y_INTERPOLATOR_NAME);
if (yInterpolators == null || yInterpolators.size() != 1) {
return null;
}
final Set<String> yLeftExtrapolators = constraints.getValues(InterpolatedDataProperties.LEFT_Y_EXTRAPOLATOR_NAME);
if (yLeftExtrapolators == null || yLeftExtrapolators.size() != 1) {
return null;
}
final Set<String> yRightExtrapolators = constraints.getValues(InterpolatedDataProperties.RIGHT_Y_EXTRAPOLATOR_NAME);
if (yRightExtrapolators == null || yRightExtrapolators.size() != 1) {
return null;
}
final Security security = target.getSecurity();
final Currency currency = FinancialSecurityUtils.getCurrency(security);
final ValueProperties sensitivityProperties = getSensitivityProperties(target, currency.getCode(), desiredValue);
final String cubeDefinitionName = desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_CUBE_DEFINITION);
final String cubeSpecificationName = desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_CUBE_SPECIFICATION);
final String surfaceDefinitionName = desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_DEFINITION);
final String surfaceSpecificationName = desiredValue.getConstraint(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_SPECIFICATION);
final String fittingMethod = desiredValue.getConstraint(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD);
requirements.add(new ValueRequirement(ValueRequirementNames.PRESENT_VALUE_SABR_ALPHA_SENSITIVITY, target.toSpecification(), sensitivityProperties));
requirements.add(new ValueRequirement(ValueRequirementNames.PRESENT_VALUE_SABR_RHO_SENSITIVITY, target.toSpecification(), sensitivityProperties));
requirements.add(new ValueRequirement(ValueRequirementNames.PRESENT_VALUE_SABR_NU_SENSITIVITY, target.toSpecification(), sensitivityProperties));
requirements.add(new ValueRequirement(ValueRequirementNames.VOLATILITY_CUBE_FITTED_POINTS, ComputationTargetSpecification.NULL,
getFittedPointsProperties(cubeDefinitionName, cubeSpecificationName, surfaceDefinitionName, surfaceSpecificationName, fittingMethod)));
return requirements;
}
@Override
protected String getValueRequirement() {
return ValueRequirementNames.VEGA_QUOTE_CUBE;
}
/**
* Gets the value properties for the SABR parameter sensitivities.
* @param target The target
* @param currency The currency of the security
* @param desiredValue The desired value
* @return The value properties
*/
protected abstract ValueProperties getSensitivityProperties(final ComputationTarget target, final String currency, final ValueRequirement desiredValue);
/**
* Gets the value properties for the fitted points of the cube
* @param cubeDefinitionName The cube definition name
* @param cubeSpecificationName The cube specification name
* @param surfaceDefinitionName The surface definition name
* @param surfaceSpecificationName The surface specification name
* @param fittingMethod The SABR fitting method
* @return The value properties
*/
protected ValueProperties getFittedPointsProperties(final String cubeDefinitionName, final String cubeSpecificationName,
final String surfaceDefinitionName, final String surfaceSpecificationName, final String fittingMethod) {
return ValueProperties.builder()
.with(SurfaceAndCubePropertyNames.PROPERTY_CUBE_DEFINITION, cubeDefinitionName)
.with(SurfaceAndCubePropertyNames.PROPERTY_CUBE_SPECIFICATION, cubeSpecificationName)
.with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_DEFINITION, surfaceDefinitionName)
.with(SurfaceAndCubePropertyNames.PROPERTY_SURFACE_SPECIFICATION, surfaceSpecificationName)
.with(SmileFittingPropertyNamesAndValues.PROPERTY_VOLATILITY_MODEL, SmileFittingPropertyNamesAndValues.SABR)
.with(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD, fittingMethod).get();
}
@Override
protected Object getResult(final InstrumentDerivative derivative, final SABRInterestRateDataBundle data, final ValueRequirement desiredValue) {
throw new UnsupportedOperationException("Should never get here");
}
}