/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.model.irfutureoption; import java.util.Collections; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Iterables; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.interestrate.InstrumentSensitivityCalculator; import com.opengamma.analytics.financial.interestrate.PresentValueCurveSensitivitySABRCalculator; import com.opengamma.analytics.financial.interestrate.PresentValueNodeSensitivityCalculator; import com.opengamma.analytics.financial.model.option.definition.SABRInterestRateDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; 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.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.ircurve.InterpolatedYieldCurveSpecificationWithSecurities; import com.opengamma.financial.analytics.ircurve.calcconfig.MultiCurveCalculationConfig; import com.opengamma.financial.analytics.model.FunctionUtils; import com.opengamma.financial.analytics.model.YieldCurveNodeSensitivitiesHelper; import com.opengamma.financial.analytics.model.curve.interestrate.MultiYieldCurvePropertiesAndDefaults; import com.opengamma.financial.analytics.model.volatility.SmileFittingPropertyNamesAndValues; import com.opengamma.financial.security.FinancialSecurityUtils; import com.opengamma.util.money.Currency; /** * */ public class IRFutureOptionSABRYCNSFunction extends IRFutureOptionSABRFunction { private static final Logger s_logger = LoggerFactory.getLogger(IRFutureOptionSABRYCNSFunction.class); private static final InstrumentSensitivityCalculator CALCULATOR = InstrumentSensitivityCalculator.getInstance(); private static final PresentValueNodeSensitivityCalculator NSC = PresentValueNodeSensitivityCalculator.using(PresentValueCurveSensitivitySABRCalculator.getInstance()); /** * Default constructor */ public IRFutureOptionSABRYCNSFunction() { super(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES); } @Override protected Set<ComputedValue> getResult(final FunctionExecutionContext context, final Set<ValueRequirement> desiredValues, final FunctionInputs inputs, final ComputationTarget target, final InstrumentDerivative irFutureOption, final SABRInterestRateDataBundle data) { final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues); final String curveName = desiredValue.getConstraint(ValuePropertyNames.CURVE); 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 String curveCalculationMethod = curveCalculationConfig.getCalculationMethod(); final Object curveSpecObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE_SPEC); if (curveSpecObject == null) { throw new OpenGammaRuntimeException("Could not get curve specification"); } final InterpolatedYieldCurveSpecificationWithSecurities curveSpec = (InterpolatedYieldCurveSpecificationWithSecurities) curveSpecObject; final Object jacobianObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE_JACOBIAN); if (jacobianObject == null) { throw new OpenGammaRuntimeException("Could not get " + ValueRequirementNames.YIELD_CURVE_JACOBIAN); } final double[][] array = FunctionUtils.decodeJacobian(jacobianObject); final DoubleMatrix2D jacobian = new DoubleMatrix2D(array); DoubleMatrix1D sensitivities; if (curveCalculationMethod.equals(MultiYieldCurvePropertiesAndDefaults.PRESENT_VALUE_STRING)) { final Object couponSensitivityObject = inputs.getValue(ValueRequirementNames.PRESENT_VALUE_COUPON_SENSITIVITY); if (couponSensitivityObject == null) { throw new OpenGammaRuntimeException("Could not get " + ValueRequirementNames.PRESENT_VALUE_COUPON_SENSITIVITY); } final DoubleMatrix1D couponSensitivity = (DoubleMatrix1D) couponSensitivityObject; sensitivities = CALCULATOR.calculateFromPresentValue(irFutureOption, null, data, couponSensitivity, jacobian, NSC); } else { sensitivities = CALCULATOR.calculateFromParRate(irFutureOption, null, data, jacobian, NSC); } final ValueProperties properties = desiredValue.getConstraints().copy().withoutAny(ValuePropertyNames.FUNCTION).with(ValuePropertyNames.FUNCTION, getUniqueId()).get(); final ValueSpecification spec = new ValueSpecification(getValueRequirementNames()[0], target.toSpecification(), properties); return YieldCurveNodeSensitivitiesHelper.getInstrumentLabelledSensitivitiesForCurve(curveName, data, sensitivities, curveSpec, spec); } @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) { final ValueProperties properties = createValueProperties().withAny(ValuePropertyNames.CURVE_CALCULATION_CONFIG).withAny(ValuePropertyNames.SURFACE) .withAny(SmileFittingPropertyNamesAndValues.PROPERTY_FITTING_METHOD).with(ValuePropertyNames.CALCULATION_METHOD, SmileFittingPropertyNamesAndValues.SABR) .withAny(ValuePropertyNames.CURVE).get(); return Collections.singleton(new ValueSpecification(getValueRequirementNames()[0], target.toSpecification(), properties)); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { //TODO repeated access of database - don't use super final Set<ValueRequirement> requirements = super.getRequirements(context, target, desiredValue); if (requirements == null) { return null; } final String curveName = desiredValue.getConstraint(ValuePropertyNames.CURVE); if (curveName == null) { s_logger.error("Must specify yield curve name"); return null; } final String curveCalculationConfigName = desiredValue.getConstraint(ValuePropertyNames.CURVE_CALCULATION_CONFIG); final MultiCurveCalculationConfig curveCalculationConfig = getCurveCalculationConfigSource().getConfig(curveCalculationConfigName); if (curveCalculationConfig == null) { s_logger.error("Could not find curve calculation configuration named " + curveCalculationConfigName); return null; } final String curveCalculationMethod = curveCalculationConfig.getCalculationMethod(); final Currency currency = FinancialSecurityUtils.getCurrency(target.getTrade().getSecurity()); requirements.add(getCurveSpecRequirement(currency, curveName)); requirements.add(getJacobianRequirement(currency, curveCalculationConfigName, curveCalculationMethod)); if (curveCalculationMethod.equals(MultiYieldCurvePropertiesAndDefaults.PRESENT_VALUE_STRING)) { requirements.add(getCouponSensitivitiesRequirement(currency, curveCalculationConfigName)); } return requirements; } private ValueRequirement getCurveSpecRequirement(final Currency currency, final String curveName) { final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE, curveName).get(); return new ValueRequirement(ValueRequirementNames.YIELD_CURVE_SPEC, ComputationTargetSpecification.of(currency), properties); } private ValueRequirement getJacobianRequirement(final Currency currency, final String curveCalculationConfigName, final String curveCalculationMethod) { final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfigName) .with(ValuePropertyNames.CURVE_CALCULATION_METHOD, curveCalculationMethod).get(); return new ValueRequirement(ValueRequirementNames.YIELD_CURVE_JACOBIAN, ComputationTargetSpecification.of(currency), properties); } private ValueRequirement getCouponSensitivitiesRequirement(final Currency currency, final String curveCalculationConfigName) { final ValueProperties properties = ValueProperties.builder().with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, curveCalculationConfigName) .with(ValuePropertyNames.CURVE_CALCULATION_METHOD, MultiYieldCurvePropertiesAndDefaults.PRESENT_VALUE_STRING).get(); return new ValueRequirement(ValueRequirementNames.PRESENT_VALUE_COUPON_SENSITIVITY, ComputationTargetSpecification.of(currency), properties); } }