/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.hullwhitediscounting;
import static com.opengamma.engine.value.ValuePropertyNames.CURRENCY;
import static com.opengamma.engine.value.ValuePropertyNames.CURVE_EXPOSURES;
import static com.opengamma.engine.value.ValueRequirementNames.CURVE_BUNDLE;
import static com.opengamma.engine.value.ValueRequirementNames.JACOBIAN_BUNDLE;
import static com.opengamma.financial.analytics.model.curve.CurveCalculationPropertyNamesAndValues.HULL_WHITE_DISCOUNTING;
import static com.opengamma.financial.analytics.model.curve.CurveCalculationPropertyNamesAndValues.PROPERTY_CURVE_TYPE;
import static com.opengamma.financial.analytics.model.curve.CurveCalculationPropertyNamesAndValues.PROPERTY_HULL_WHITE_CURRENCY;
import static com.opengamma.financial.analytics.model.curve.CurveCalculationPropertyNamesAndValues.PROPERTY_HULL_WHITE_PARAMETERS;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.instrument.InstrumentDefinition;
import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle;
import com.opengamma.analytics.financial.provider.description.interestrate.HullWhiteOneFactorProviderDiscount;
import com.opengamma.analytics.financial.provider.description.interestrate.ProviderUtils;
import com.opengamma.core.convention.ConventionSource;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.region.RegionSource;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueProperties.Builder;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.financial.OpenGammaCompilationContext;
import com.opengamma.financial.analytics.conversion.CashFlowSecurityConverter;
import com.opengamma.financial.analytics.conversion.CashSecurityConverter;
import com.opengamma.financial.analytics.conversion.DefaultTradeConverter;
import com.opengamma.financial.analytics.conversion.DeliverableSwapFutureSecurityConverter;
import com.opengamma.financial.analytics.conversion.DeliverableSwapFutureTradeConverter;
import com.opengamma.financial.analytics.conversion.FRASecurityConverter;
import com.opengamma.financial.analytics.conversion.FXForwardSecurityConverter;
import com.opengamma.financial.analytics.conversion.FederalFundsFutureTradeConverter;
import com.opengamma.financial.analytics.conversion.FixedIncomeConverterDataProvider;
import com.opengamma.financial.analytics.conversion.FutureTradeConverter;
import com.opengamma.financial.analytics.conversion.InterestRateFutureTradeConverter;
import com.opengamma.financial.analytics.conversion.InterestRateSwapSecurityConverter;
import com.opengamma.financial.analytics.conversion.NonDeliverableFXForwardSecurityConverter;
import com.opengamma.financial.analytics.conversion.SwapSecurityConverter;
import com.opengamma.financial.analytics.conversion.SwaptionSecurityConverter;
import com.opengamma.financial.analytics.fixedincome.InterestRateInstrumentType;
import com.opengamma.financial.analytics.model.forex.ForexVisitors;
import com.opengamma.financial.analytics.model.multicurve.MultiCurvePricingFunction;
import com.opengamma.financial.security.FinancialSecurity;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.financial.security.FinancialSecurityVisitor;
import com.opengamma.financial.security.FinancialSecurityVisitorAdapter;
import com.opengamma.financial.security.cash.CashSecurity;
import com.opengamma.financial.security.cashflow.CashFlowSecurity;
import com.opengamma.financial.security.fra.FRASecurity;
import com.opengamma.financial.security.future.DeliverableSwapFutureSecurity;
import com.opengamma.financial.security.future.FederalFundsFutureSecurity;
import com.opengamma.financial.security.future.InterestRateFutureSecurity;
import com.opengamma.financial.security.fx.FXForwardSecurity;
import com.opengamma.financial.security.fx.NonDeliverableFXForwardSecurity;
import com.opengamma.financial.security.option.SwaptionSecurity;
import com.opengamma.financial.security.swap.InterestRateNotional;
import com.opengamma.financial.security.swap.SwapSecurity;
/**
* Base function for all pricing and risk functions that use curves constructed using the Hull-White discounting method. Produces results for trades with following underlying securities:
* <p>
* <ul>
* <li> {@link CashSecurity}
* <li> {@link CashFlowSecurity}
* <li> {@link FRASecurity}
* <li> {@link SwapSecurity}
* <li> {@link SwaptionSecurity}
* <li> {@link InterestRateFutureSecurity}
* <li> {@link FXForwardSecurity}
* <li> {@link NonDeliverableFXForwardSecurity}
* <li> {@link DeliverableSwapFutureSecurity}
* <li> {@link FederalFundsFutureSecurity}
* </ul>
*/
public abstract class HullWhiteDiscountingFunction extends MultiCurvePricingFunction {
/**
* @param valueRequirements The value requirements, not null
*/
public HullWhiteDiscountingFunction(final String... valueRequirements) {
super(valueRequirements);
}
@Override
protected DefaultTradeConverter getTargetToDefinitionConverter(final FunctionCompilationContext context) {
final SecuritySource securitySource = OpenGammaCompilationContext.getSecuritySource(context);
final HolidaySource holidaySource = OpenGammaCompilationContext.getHolidaySource(context);
final RegionSource regionSource = OpenGammaCompilationContext.getRegionSource(context);
final ConventionSource conventionSource = OpenGammaCompilationContext.getConventionSource(context);
final CashSecurityConverter cashConverter = new CashSecurityConverter(holidaySource, regionSource);
final CashFlowSecurityConverter cashFlowConverter = new CashFlowSecurityConverter();
final FRASecurityConverter fraConverter = new FRASecurityConverter(securitySource, holidaySource, regionSource, conventionSource);
final SwapSecurityConverter swapConverter = new SwapSecurityConverter(securitySource, holidaySource, conventionSource, regionSource);
final InterestRateSwapSecurityConverter irsConverter = new InterestRateSwapSecurityConverter(holidaySource, conventionSource, securitySource);
final SwaptionSecurityConverter swaptionConverter = new SwaptionSecurityConverter(swapConverter, irsConverter);
final FXForwardSecurityConverter fxForwardSecurityConverter = new FXForwardSecurityConverter();
final NonDeliverableFXForwardSecurityConverter nonDeliverableFXForwardSecurityConverter = new NonDeliverableFXForwardSecurityConverter();
final DeliverableSwapFutureSecurityConverter dsfConverter = new DeliverableSwapFutureSecurityConverter(securitySource, swapConverter, irsConverter);
final FederalFundsFutureTradeConverter federalFundsFutureTradeConverter = new FederalFundsFutureTradeConverter(securitySource, holidaySource, conventionSource, regionSource);
final FinancialSecurityVisitor<InstrumentDefinition<?>> securityConverter = FinancialSecurityVisitorAdapter.<InstrumentDefinition<?>>builder().cashSecurityVisitor(cashConverter)
.cashFlowSecurityVisitor(cashFlowConverter).deliverableSwapFutureSecurityVisitor(dsfConverter).fraSecurityVisitor(fraConverter).swapSecurityVisitor(swapConverter)
.fxForwardVisitor(fxForwardSecurityConverter).nonDeliverableFxForwardVisitor(nonDeliverableFXForwardSecurityConverter).swaptionVisitor(swaptionConverter).create();
final FutureTradeConverter futureTradeConverter = new FutureTradeConverter();
final InterestRateFutureTradeConverter irFutureTradeConveter = new InterestRateFutureTradeConverter(securitySource, holidaySource, conventionSource, regionSource);
final DeliverableSwapFutureTradeConverter deliverableSwapFutureTradeConverter = new DeliverableSwapFutureTradeConverter(securitySource, swapConverter, irsConverter);
return new DefaultTradeConverter(futureTradeConverter, federalFundsFutureTradeConverter, irFutureTradeConveter, deliverableSwapFutureTradeConverter, securityConverter);
}
/**
* Base compiled function for all pricing and risk functions that use the Hull-White one-factor curve construction method.
*/
protected abstract class HullWhiteCompiledFunction extends MultiCurveCompiledFunction {
/** True if the result properties set the {@link ValuePropertyNames#CURRENCY} property */
private final boolean _withCurrency;
/**
* @param tradeToDefinitionConverter Converts targets to definitions, not null
* @param definitionToDerivativeConverter Converts definitions to derivatives, not null
* @param withCurrency True if the result properties set the {@link ValuePropertyNames#CURRENCY} property
*/
protected HullWhiteCompiledFunction(final DefaultTradeConverter tradeToDefinitionConverter, final FixedIncomeConverterDataProvider definitionToDerivativeConverter, final boolean withCurrency) {
super(tradeToDefinitionConverter, definitionToDerivativeConverter);
_withCurrency = withCurrency;
}
@Override
public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
boolean canApplyTo = super.canApplyTo(context, target);
final Security security = target.getTrade().getSecurity();
if (security instanceof SwapSecurity && InterestRateInstrumentType.isFixedIncomeInstrumentType((SwapSecurity) security)) {
canApplyTo &= InterestRateInstrumentType.getInstrumentTypeFromSecurity((SwapSecurity) security) != InterestRateInstrumentType.SWAP_CROSS_CURRENCY;
}
return canApplyTo || security instanceof SwaptionSecurity || security instanceof DeliverableSwapFutureSecurity || security instanceof FederalFundsFutureSecurity;
}
@SuppressWarnings("synthetic-access")
@Override
protected Collection<ValueProperties.Builder> getResultProperties(final FunctionCompilationContext compilationContext, final ComputationTarget target) {
final ValueProperties.Builder properties = createValueProperties().with(PROPERTY_CURVE_TYPE, HULL_WHITE_DISCOUNTING).withAny(CURVE_EXPOSURES).withAny(PROPERTY_HULL_WHITE_PARAMETERS);
if (_withCurrency) {
final Security security = target.getTrade().getSecurity();
if (security instanceof SwapSecurity && InterestRateInstrumentType.isFixedIncomeInstrumentType((SwapSecurity) security) &&
(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);
}
} 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 the multiple currency case (SWAP_CROSS_CURRENCY) by returning a collection with more than one element
}
return Collections.singleton(properties);
}
@Override
protected boolean requirementsSet(final ValueProperties constraints) {
final Set<String> curveExposureConfigs = constraints.getValues(CURVE_EXPOSURES);
if (curveExposureConfigs == null) {
return false;
}
final Set<String> hullWhiteParameters = constraints.getValues(PROPERTY_HULL_WHITE_PARAMETERS);
if (hullWhiteParameters == null || hullWhiteParameters.size() != 1) {
return false;
}
return true;
}
@Override
protected Builder getCurveConstraints(final ComputationTarget target, final ValueProperties constraints) {
final String currency = FinancialSecurityUtils.getCurrency(target.getTrade().getSecurity()).getCode();
final Set<String> hullWhiteParameters = constraints.getValues(PROPERTY_HULL_WHITE_PARAMETERS);
return ValueProperties.builder().with(PROPERTY_HULL_WHITE_PARAMETERS, hullWhiteParameters).with(PROPERTY_HULL_WHITE_CURRENCY, currency);
}
/**
* Merges any {@link HullWhiteOneFactorProviderDiscount} curve bundles and FX matrices that are present in the inputs and creates a curve bundle with information for pricing using the Hull-White
* one factor model.
*
* @param inputs The function inputs
* @param matrix The FX matrix
* @return A curve bundle that can be used in Hull-White one factor model pricing functions
*/
protected HullWhiteOneFactorProviderDiscount getMergedProviders(final FunctionInputs inputs, final FXMatrix matrix) {
final Collection<HullWhiteOneFactorProviderDiscount> providers = new HashSet<>();
for (final ComputedValue input : inputs.getAllValues()) {
final String valueName = input.getSpecification().getValueName();
if (CURVE_BUNDLE.equals(valueName)) {
providers.add((HullWhiteOneFactorProviderDiscount) input.getValue());
}
}
final HullWhiteOneFactorProviderDiscount result = ProviderUtils.mergeHullWhiteProviders(providers);
return ProviderUtils.mergeHullWhiteProviders(result, matrix);
}
/**
* Merges any {@link CurveBuildingBlockBundle}s in the function inputs.
*
* @param inputs The function inputs
* @return A curve building block bundle that contains all of the information used to construct the curves used in pricing
*/
protected CurveBuildingBlockBundle getMergedCurveBuildingBlocks(final FunctionInputs inputs) {
final CurveBuildingBlockBundle result = new CurveBuildingBlockBundle();
for (final ComputedValue input : inputs.getAllValues()) {
final String valueName = input.getSpecification().getValueName();
if (valueName.equals(JACOBIAN_BUNDLE)) {
result.addAll((CurveBuildingBlockBundle) input.getValue());
}
}
return result;
}
}
}