/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.model.discounting; import static com.opengamma.engine.value.ValuePropertyNames.CURRENCY; import static com.opengamma.engine.value.ValuePropertyNames.CURVE; import static com.opengamma.engine.value.ValuePropertyNames.CURVE_EXPOSURES; import static com.opengamma.engine.value.ValueRequirementNames.ALL_PV01S; import static com.opengamma.engine.value.ValueRequirementNames.PV01; import static com.opengamma.financial.analytics.model.curve.CurveCalculationPropertyNamesAndValues.PROPERTY_CURVE_TYPE; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.threeten.bp.Instant; import com.google.common.collect.Iterables; import com.opengamma.analytics.financial.forex.method.FXMatrix; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.core.security.Security; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.function.CompiledFunctionDefinition; 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.ValueRequirement; import com.opengamma.engine.value.ValueRequirementNames; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.financial.analytics.fixedincome.InterestRateInstrumentType; import com.opengamma.financial.analytics.model.InterpolatedDataProperties; import com.opengamma.financial.analytics.model.forex.ForexVisitors; import com.opengamma.financial.security.FinancialSecurity; import com.opengamma.financial.security.FinancialSecurityUtils; import com.opengamma.financial.security.fx.FXForwardSecurity; import com.opengamma.financial.security.fx.NonDeliverableFXForwardSecurity; import com.opengamma.financial.security.swap.InterestRateNotional; import com.opengamma.financial.security.swap.SwapSecurity; import com.opengamma.util.async.AsynchronousExecution; import com.opengamma.util.money.Currency; import com.opengamma.util.tuple.Pair; /** * Gets the PV01 of an instrument to a named curve using curves constructed with the interpolated construction method. */ public class DiscountingInterpolatedPV01Function extends DiscountingInterpolatedFunction { /** * Sets the value requirements to {@link ValueRequirementNames#PV01} */ public DiscountingInterpolatedPV01Function() { super(PV01); } @Override public CompiledFunctionDefinition compile(final FunctionCompilationContext context, final Instant atInstant) { return new DiscountingInterpolatedCompiledFunction(getTargetToDefinitionConverter(context), getDefinitionToDerivativeConverter(context), true) { @SuppressWarnings("synthetic-access") @Override protected Set<ComputedValue> getValues(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues, final InstrumentDerivative derivative, final FXMatrix fxMatrix) { final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues); final String desiredCurveName = desiredValue.getConstraint(CURVE); final ValueProperties properties = desiredValue.getConstraints(); final Map<Pair<String, Currency>, Double> pv01s = (Map<Pair<String, Currency>, Double>) inputs.getValue(ALL_PV01S); final Set<ComputedValue> results = new HashSet<>(); for (final Map.Entry<Pair<String, Currency>, Double> entry : pv01s.entrySet()) { final String curveName = entry.getKey().getFirst(); if (desiredCurveName.equals(curveName)) { final ValueProperties curveSpecificProperties = properties.copy().withoutAny(CURVE).with(CURVE, curveName).get(); final ValueSpecification spec = new ValueSpecification(PV01, target.toSpecification(), curveSpecificProperties); results.add(new ComputedValue(spec, entry.getValue())); return results; } } final ValueProperties curveSpecificProperties = properties.copy().withoutAny(CURVE).with(CURVE, desiredCurveName).get(); final ValueSpecification spec = new ValueSpecification(PV01, target.toSpecification(), curveSpecificProperties); results.add(new ComputedValue(spec, 0.)); return results; } @Override public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) throws AsynchronousExecution { return getValues(executionContext, inputs, target, desiredValues, null, null); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext compilationContext, final ComputationTarget target, final ValueRequirement desiredValue) { final ValueProperties constraints = desiredValue.getConstraints(); final Set<String> curveNames = constraints.getValues(CURVE); if (curveNames == null || curveNames.size() != 1) { return null; } final Set<String> curveExposureConfigs = constraints.getValues(CURVE_EXPOSURES); if (curveExposureConfigs == null) { return null; } final ValueProperties properties = ValueProperties.with(PROPERTY_CURVE_TYPE, InterpolatedDataProperties.CALCULATION_METHOD_NAME).with(CURVE_EXPOSURES, curveExposureConfigs).get(); return Collections.singleton(new ValueRequirement(ALL_PV01S, target.toSpecification(), properties)); } @SuppressWarnings("synthetic-access") @Override protected Collection<ValueProperties.Builder> getResultProperties(final FunctionCompilationContext compilationContext, final ComputationTarget target) { final ValueProperties.Builder properties = createValueProperties().with(PROPERTY_CURVE_TYPE, InterpolatedDataProperties.CALCULATION_METHOD_NAME).withAny(CURVE_EXPOSURES) .withAny(CURVE); final Security security = target.getTrade().getSecurity(); if (security instanceof SwapSecurity && InterestRateInstrumentType.isFixedIncomeInstrumentType((SwapSecurity) security)) { if ((InterestRateInstrumentType.getInstrumentTypeFromSecurity((SwapSecurity) security) != InterestRateInstrumentType.SWAP_CROSS_CURRENCY)) { final SwapSecurity swapSecurity = (SwapSecurity) security; if (swapSecurity.getPayLeg().getNotional() instanceof InterestRateNotional) { final String currency = ((InterestRateNotional) swapSecurity.getPayLeg().getNotional()).getCurrency().getCode(); properties.with(CURRENCY, currency); return Collections.singleton(properties); } } properties.withAny(CURRENCY); return Collections.singleton(properties); } else if (security instanceof FXForwardSecurity || security instanceof NonDeliverableFXForwardSecurity) { properties.with(CURRENCY, ((FinancialSecurity) security).accept(ForexVisitors.getPayCurrencyVisitor()).getCode()); } else { properties.with(CURRENCY, FinancialSecurityUtils.getCurrency(target.getTrade().getSecurity()).getCode()); } // TODO: Handle instruments with multiple currencies correctly return Collections.singleton(properties); } }; } }