/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.pnl;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.math.interpolation.Interpolator1DFactory;
import com.opengamma.engine.ComputationTargetSpecification;
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.financial.analytics.model.CalculationPropertyNamesAndValues;
import com.opengamma.financial.analytics.model.InterpolatedDataProperties;
import com.opengamma.financial.analytics.model.forex.option.black.FXOptionBlackFunction;
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.bond.CorporateBondSecurity;
import com.opengamma.financial.security.bond.GovernmentBondSecurity;
import com.opengamma.financial.security.cash.CashSecurity;
import com.opengamma.financial.security.cashflow.CashFlowSecurity;
import com.opengamma.financial.security.cds.CreditDefaultSwapIndexSecurity;
import com.opengamma.financial.security.cds.LegacyVanillaCDSSecurity;
import com.opengamma.financial.security.cds.StandardVanillaCDSSecurity;
import com.opengamma.financial.security.equity.EquitySecurity;
import com.opengamma.financial.security.fra.FRASecurity;
import com.opengamma.financial.security.future.BondFutureSecurity;
import com.opengamma.financial.security.future.InterestRateFutureSecurity;
import com.opengamma.financial.security.fx.FXForwardSecurity;
import com.opengamma.financial.security.option.BondFutureOptionSecurity;
import com.opengamma.financial.security.option.CreditDefaultSwapOptionSecurity;
import com.opengamma.financial.security.option.EquityOptionSecurity;
import com.opengamma.financial.security.option.FXOptionSecurity;
import com.opengamma.financial.security.option.IRFutureOptionSecurity;
import com.opengamma.financial.security.option.SwaptionSecurity;
import com.opengamma.financial.security.swap.SwapSecurity;
import com.opengamma.util.money.Currency;
/**
* PnL requirements gatherer.
*/
public class DefaultPnLRequirementsGatherer implements PnLRequirementsGatherer {
private final Map<String, String> _curveCalculationConfigs = new HashMap<>();
private final Map<String, String> _fxCurveCalculationConfigs = new HashMap<>();
private final Map<String, String> _fxDiscountingCurveNames = new HashMap<>();
private final Map<String, String> _irFuturesCurveCalculationConfigs = new HashMap<>();
private String _fxVolSurfaceName = "DEFAULT";
private String _swaptionVolSurfaceName = "DEFAULT";
private String _irFutureOptionVolSurfaceName = "DEFAULT";
private String _bondFutureOptionVolSurfaceName = "DEFAULT";
private String _fxVolInterpolator = Interpolator1DFactory.DOUBLE_QUADRATIC;
private String _fxVolLeftExtrapolator = Interpolator1DFactory.LINEAR_EXTRAPOLATOR;
private String _fxVolRightExtrapolator = Interpolator1DFactory.LINEAR_EXTRAPOLATOR;
protected void addCurveCalculationConfig(final String currency, final String configName) {
_curveCalculationConfigs.put(currency, configName);
}
protected void addFXCurveCalculationConfig(final String currency, final String configName) {
_fxCurveCalculationConfigs.put(currency, configName);
}
protected void addFXDiscountingCurveName(final String currency, final String curveName) {
_fxDiscountingCurveNames.put(currency, curveName);
}
protected void addIRFuturesCurveCalculationConfig(final String currency, final String configName) {
_irFuturesCurveCalculationConfigs.put(currency, configName);
}
protected void setFXVolSurfaceName(final String fxVolSurfaceName) {
_fxVolSurfaceName = fxVolSurfaceName;
}
protected void setSwaptionVolSurfaceName(final String swaptionVolSurfaceName) {
_swaptionVolSurfaceName = swaptionVolSurfaceName;
}
protected void setIRFutureOptionVolSurfaceName(final String irFutureOptionVolSurfaceName) {
_irFutureOptionVolSurfaceName = irFutureOptionVolSurfaceName;
}
protected void setBondFutureOptionVolSurfaceName(final String bondFutureOptionVolSurfaceName) {
_bondFutureOptionVolSurfaceName = bondFutureOptionVolSurfaceName;
}
protected void setFXVolInterpolator(final String fxVolInterpolator) {
_fxVolInterpolator = fxVolInterpolator;
}
protected void setFXVolLeftExtrapolator(final String fxVolLeftExtrapolator) {
_fxVolLeftExtrapolator = fxVolLeftExtrapolator;
}
protected void setFXVolRightExtrapolator(final String fxVolRightExtrapolator) {
_fxVolRightExtrapolator = fxVolRightExtrapolator;
}
@Override
public Set<ValueRequirement> getFirstOrderRequirements(final FinancialSecurity security, final String samplingPeriod, final String scheduleCalculator, final String samplingFunction,
final ComputationTargetSpecification targetSpec, final String currency) {
return security.accept(getFirstOrderRequirements(samplingPeriod, scheduleCalculator, samplingFunction, targetSpec, currency));
}
//TODO another visitor that takes desiredValue and uses those properties instead of the static defaults
protected FinancialSecurityVisitor<Set<ValueRequirement>> getFirstOrderRequirements(final String samplingPeriod, final String scheduleCalculator, final String samplingFunction,
final ComputationTargetSpecification targetSpec, final String currency) {
final ValueProperties commonProperties = ValueProperties.builder()
.with(ValuePropertyNames.CURRENCY, currency)
.with(ValuePropertyNames.SAMPLING_PERIOD, samplingPeriod)
.with(ValuePropertyNames.SCHEDULE_CALCULATOR, scheduleCalculator)
.with(ValuePropertyNames.SAMPLING_FUNCTION, samplingFunction).get();
return new FinancialSecurityVisitorAdapter<Set<ValueRequirement>>() {
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitSwapSecurity(final SwapSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitFRASecurity(final FRASecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitSwaptionSecurity(final SwaptionSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.BLACK_METHOD)
.with(ValuePropertyNames.SURFACE, _swaptionVolSurfaceName)
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitGovernmentBondSecurity(final GovernmentBondSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitCorporateBondSecurity(final CorporateBondSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitFXForwardSecurity(final FXForwardSecurity security) {
final String payCurrency = security.getPayCurrency().getCode();
final String payCalculationConfig = _fxCurveCalculationConfigs.get(payCurrency);
if (payCalculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + payCurrency);
}
final String payDiscountingCurve = _fxDiscountingCurveNames.get(payCurrency);
if (payDiscountingCurve == null) {
throw new OpenGammaRuntimeException("Could not get discounting curve for " + payCurrency);
}
final String receiveCurrency = security.getReceiveCurrency().getCode();
final String receiveCalculationConfig = _fxCurveCalculationConfigs.get(receiveCurrency);
if (receiveCalculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + receiveCurrency);
}
final String receiveDiscountingCurve = _fxDiscountingCurveNames.get(receiveCurrency);
if (receiveDiscountingCurve == null) {
throw new OpenGammaRuntimeException("Could not get discounting curve for " + receiveCurrency);
}
final ValueProperties currencyExposureProperties = commonProperties.copy()
.with(ValuePropertyNames.PAY_CURVE, payDiscountingCurve)
.with(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCalculationConfig)
.with(ValuePropertyNames.RECEIVE_CURVE, receiveDiscountingCurve)
.with(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCalculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.FX_CURRENCY_EXPOSURE).get();
final ValueProperties ycnsProperties = commonProperties.copy()
.with(ValuePropertyNames.PAY_CURVE, payDiscountingCurve)
.with(ValuePropertyNames.PAY_CURVE_CALCULATION_CONFIG, payCalculationConfig)
.with(ValuePropertyNames.RECEIVE_CURVE, receiveDiscountingCurve)
.with(ValuePropertyNames.RECEIVE_CURVE_CALCULATION_CONFIG, receiveCalculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
final ValueRequirement fxCurrencyExposure = new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, currencyExposureProperties);
final ValueRequirement fxYCNSExposure = new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, ycnsProperties);
return Sets.newHashSet(fxCurrencyExposure, fxYCNSExposure);
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitFXOptionSecurity(final FXOptionSecurity security) {
final Currency putCurrency = security.getPutCurrency();
final Currency callCurrency = security.getCallCurrency();
final String putCurrencyString = putCurrency.getCode();
final String callCurrencyString = callCurrency.getCode();
final String putCalculationConfig = _fxCurveCalculationConfigs.get(putCurrencyString);
if (putCalculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + putCurrencyString);
}
final String putDiscountingCurve = _fxDiscountingCurveNames.get(putCurrencyString);
if (putDiscountingCurve == null) {
throw new OpenGammaRuntimeException("Could not get discounting curve for " + putCurrencyString);
}
final String callCalculationConfig = _fxCurveCalculationConfigs.get(callCurrencyString);
if (callCalculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + callCurrencyString);
}
final String callDiscountingCurve = _fxDiscountingCurveNames.get(callCurrencyString);
if (callDiscountingCurve == null) {
throw new OpenGammaRuntimeException("Could not get discounting curve for " + callCurrencyString);
}
final ValueProperties deltaProperties = commonProperties.copy()
.with(ValuePropertyNames.CALCULATION_METHOD, CalculationPropertyNamesAndValues.BLACK_METHOD)
.with(FXOptionBlackFunction.PUT_CURVE, putDiscountingCurve)
.with(FXOptionBlackFunction.PUT_CURVE_CALC_CONFIG, putCalculationConfig)
.with(FXOptionBlackFunction.CALL_CURVE, callDiscountingCurve)
.with(FXOptionBlackFunction.CALL_CURVE_CALC_CONFIG, callCalculationConfig)
.with(ValuePropertyNames.SURFACE, _fxVolSurfaceName)
.with(InterpolatedDataProperties.X_INTERPOLATOR_NAME, _fxVolInterpolator)
.with(InterpolatedDataProperties.LEFT_X_EXTRAPOLATOR_NAME, _fxVolLeftExtrapolator)
.with(InterpolatedDataProperties.RIGHT_X_EXTRAPOLATOR_NAME, _fxVolRightExtrapolator)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.FX_CURRENCY_EXPOSURE).get();
final ValueRequirement delta = new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, deltaProperties);
return Sets.newHashSet(delta);
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitBondFutureSecurity(final BondFutureSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitInterestRateFutureSecurity(final InterestRateFutureSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _irFuturesCurveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitIRFutureOptionSecurity(final IRFutureOptionSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.SURFACE, _irFutureOptionVolSurfaceName)
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@SuppressWarnings("synthetic-access")
@Override
public Set<ValueRequirement> visitBondFutureOptionSecurity(final BondFutureOptionSecurity security) {
final String securityCurrency = FinancialSecurityUtils.getCurrency(security).getCode();
final String calculationConfig = _curveCalculationConfigs.get(securityCurrency);
if (calculationConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation config for " + securityCurrency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.SURFACE, _bondFutureOptionVolSurfaceName)
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, calculationConfig)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitEquitySecurity(final EquitySecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, "Delta").get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitEquityOptionSecurity(final EquityOptionSecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, "Delta").get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitCashSecurity(final CashSecurity security) {
return createValueRequirementsForCashLikeSecurity(security.getCurrency());
}
@Override
public Set<ValueRequirement> visitCashFlowSecurity(final CashFlowSecurity security) {
return createValueRequirementsForCashLikeSecurity(security.getCurrency());
}
@Override
public Set<ValueRequirement> visitStandardVanillaCDSSecurity(final StandardVanillaCDSSecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.BUCKETED_CS01)
.get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitLegacyVanillaCDSSecurity(final LegacyVanillaCDSSecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.BUCKETED_CS01)
.get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitCreditDefaultSwapOptionSecurity(final CreditDefaultSwapOptionSecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.BUCKETED_CS01)
.get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
@Override
public Set<ValueRequirement> visitCreditDefaultSwapIndexSecurity(final CreditDefaultSwapIndexSecurity security) {
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.BUCKETED_CS01)
.get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
private Set<ValueRequirement> createValueRequirementsForCashLikeSecurity(final Currency currency) {
final String config = _curveCalculationConfigs.get(currency);
if (config == null) {
throw new OpenGammaRuntimeException("Could not get curve calculation configuration for " + currency);
}
final ValueProperties properties = commonProperties.copy()
.with(ValuePropertyNames.CURVE_CALCULATION_CONFIG, config)
.with(ValuePropertyNames.PROPERTY_PNL_CONTRIBUTIONS, ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES).get();
return Collections.singleton(new ValueRequirement(ValueRequirementNames.PNL_SERIES, targetSpec, properties));
}
};
}
}