/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.riskfactors; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableSet; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.core.id.ExternalSchemes; import com.opengamma.core.position.Portfolio; import com.opengamma.core.position.PortfolioNode; import com.opengamma.core.position.Position; import com.opengamma.core.position.impl.AbstractPortfolioNodeTraversalCallback; import com.opengamma.core.position.impl.PortfolioNodeTraverser; import com.opengamma.core.security.SecuritySource; 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.engine.view.ViewCalculationConfiguration; import com.opengamma.financial.analytics.MissingInputsFunction; import com.opengamma.financial.analytics.conversion.SwapSecurityUtils; import com.opengamma.financial.analytics.fixedincome.InterestRateInstrumentType; import com.opengamma.financial.analytics.ircurve.YieldCurveFunction; import com.opengamma.financial.analytics.model.InstrumentTypeProperties; import com.opengamma.financial.analytics.model.volatility.surface.black.BlackVolatilitySurfacePropertyNamesAndValues; import com.opengamma.financial.security.FinancialSecurity; 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.bond.MunicipalBondSecurity; import com.opengamma.financial.security.capfloor.CapFloorCMSSpreadSecurity; import com.opengamma.financial.security.capfloor.CapFloorSecurity; import com.opengamma.financial.security.cash.CashSecurity; import com.opengamma.financial.security.deposit.ContinuousZeroDepositSecurity; import com.opengamma.financial.security.deposit.PeriodicZeroDepositSecurity; import com.opengamma.financial.security.deposit.SimpleZeroDepositSecurity; import com.opengamma.financial.security.equity.EquitySecurity; import com.opengamma.financial.security.equity.EquityVarianceSwapSecurity; import com.opengamma.financial.security.fra.FRASecurity; import com.opengamma.financial.security.future.AgricultureFutureSecurity; import com.opengamma.financial.security.future.BondFutureSecurity; import com.opengamma.financial.security.future.EnergyFutureSecurity; import com.opengamma.financial.security.future.EquityFutureSecurity; import com.opengamma.financial.security.future.EquityIndexDividendFutureSecurity; import com.opengamma.financial.security.future.FXFutureSecurity; import com.opengamma.financial.security.future.IndexFutureSecurity; import com.opengamma.financial.security.future.InterestRateFutureSecurity; import com.opengamma.financial.security.future.MetalFutureSecurity; import com.opengamma.financial.security.future.StockFutureSecurity; import com.opengamma.financial.security.fx.FXForwardSecurity; import com.opengamma.financial.security.fx.NonDeliverableFXForwardSecurity; import com.opengamma.financial.security.option.CommodityFutureOptionSecurity; import com.opengamma.financial.security.option.EquityBarrierOptionSecurity; import com.opengamma.financial.security.option.EquityIndexDividendFutureOptionSecurity; import com.opengamma.financial.security.option.EquityIndexOptionSecurity; import com.opengamma.financial.security.option.EquityOptionSecurity; import com.opengamma.financial.security.option.FXBarrierOptionSecurity; import com.opengamma.financial.security.option.FXDigitalOptionSecurity; import com.opengamma.financial.security.option.FXOptionSecurity; import com.opengamma.financial.security.option.FxFutureOptionSecurity; import com.opengamma.financial.security.option.IRFutureOptionSecurity; import com.opengamma.financial.security.option.NonDeliverableFXDigitalOptionSecurity; import com.opengamma.financial.security.option.NonDeliverableFXOptionSecurity; import com.opengamma.financial.security.option.SwaptionSecurity; import com.opengamma.financial.security.swap.InterestRateNotional; import com.opengamma.financial.security.swap.Notional; import com.opengamma.financial.security.swap.SwapSecurity; import com.opengamma.id.ExternalId; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Default implementation of {@link RiskFactorsGatherer}. */ public class DefaultRiskFactorsGatherer extends FinancialSecurityVisitorAdapter<Set<Pair<String, ValueProperties>>> implements RiskFactorsGatherer { private static final Logger s_logger = LoggerFactory.getLogger(DefaultRiskFactorsGatherer.class); private final SecuritySource _securities; private final RiskFactorsConfigurationProvider _configProvider; public DefaultRiskFactorsGatherer(final SecuritySource securities, final RiskFactorsConfigurationProvider configProvider) { ArgumentChecker.notNull(securities, "securities"); ArgumentChecker.notNull(configProvider, "configProvider"); _securities = securities; _configProvider = configProvider; } @Override public Set<ValueRequirement> getPositionRiskFactors(final Position position) { ArgumentChecker.notNull(position, "position"); final Set<Pair<String, ValueProperties>> securityRiskFactors = ((FinancialSecurity) position.getSecurity()).accept(this); if (securityRiskFactors.isEmpty()) { return ImmutableSet.of(); } final Set<ValueRequirement> results = new HashSet<ValueRequirement>(securityRiskFactors.size()); for (final Pair<String, ValueProperties> securityRiskFactor : securityRiskFactors) { results.add(getValueRequirement(position, securityRiskFactor.getFirst(), securityRiskFactor.getSecond())); } return results; } @Override public Set<ValueRequirement> getPositionRiskFactors(final Portfolio portfolio) { ArgumentChecker.notNull(portfolio, "portfolio"); final RiskFactorPortfolioTraverser callback = new RiskFactorPortfolioTraverser(); callback.traverse(portfolio.getRootNode()); return callback.getRiskFactors(); } @Override public void addPortfolioRiskFactors(final Portfolio portfolio, final ViewCalculationConfiguration calcConfig) { ArgumentChecker.notNull(portfolio, "portfolio"); ArgumentChecker.notNull(calcConfig, "calcConfig"); final RiskFactorPortfolioTraverser callback = new RiskFactorPortfolioTraverser(calcConfig); callback.traverse(portfolio.getRootNode()); } //------------------------------------------------------------------------- private class RiskFactorPortfolioTraverser extends AbstractPortfolioNodeTraversalCallback { private final ViewCalculationConfiguration _calcConfig; private final Set<ValueRequirement> _valueRequirements = new HashSet<ValueRequirement>(); public RiskFactorPortfolioTraverser() { this(null); } public RiskFactorPortfolioTraverser(final ViewCalculationConfiguration calcConfig) { _calcConfig = calcConfig; } public void traverse(final PortfolioNode rootNode) { PortfolioNodeTraverser.depthFirst(this).traverse(rootNode); } public Set<ValueRequirement> getRiskFactors() { return new HashSet<ValueRequirement>(_valueRequirements); } @Override public void preOrderOperation(final PortfolioNode portfolioNode) { } @Override public void preOrderOperation(final PortfolioNode parentNode, final Position position) { // REVIEW 2012-09-17 Andrew -- [PLAT-2286] Should we check whether the position has already been visited? final Set<ValueRequirement> riskFactorRequirements = DefaultRiskFactorsGatherer.this.getPositionRiskFactors(position); _valueRequirements.addAll(riskFactorRequirements); if (_calcConfig != null) { for (final ValueRequirement riskFactorRequirement : riskFactorRequirements) { _calcConfig.addPortfolioRequirement(position.getSecurity().getSecurityType(), riskFactorRequirement.getValueName(), riskFactorRequirement.getConstraints()); } } } @Override public void postOrderOperation(final PortfolioNode parentNode, final Position position) { } @Override public void postOrderOperation(final PortfolioNode portfolioNode) { } } //------------------------------------------------------------------------- // Securities @Override public Set<Pair<String, ValueProperties>> visitCorporateBondSecurity(final CorporateBondSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve())); } @Override public Set<Pair<String, ValueProperties>> visitGovernmentBondSecurity(final GovernmentBondSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve())); } @Override public Set<Pair<String, ValueProperties>> visitMunicipalBondSecurity(final MunicipalBondSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve())); } @Override public Set<Pair<String, ValueProperties>> visitCashSecurity(final CashSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve()), getPV01(getForwardCurve(security.getCurrency()))); } @Override public Set<Pair<String, ValueProperties>> visitEquitySecurity(final EquitySecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitFRASecurity(final FRASecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve()), getPV01(getForwardCurve(security.getCurrency()))); } @Override public Set<Pair<String, ValueProperties>> visitSwapSecurity(final SwapSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder(); // At the moment pay and receive must be the same currency, so any one of them is sufficient final Notional payNotional = security.getPayLeg().getNotional(); final Notional receiveNotional = security.getReceiveLeg().getNotional(); if (payNotional instanceof InterestRateNotional && receiveNotional instanceof InterestRateNotional) { final Currency ccy = ((InterestRateNotional) payNotional).getCurrency(); builder.add(getYieldCurveNodeSensitivities(getFundingCurve(), ccy)); builder.add(getYieldCurveNodeSensitivities(getForwardCurve(ccy), ccy)); final InterestRateInstrumentType type = SwapSecurityUtils.getSwapType(security); if (type == InterestRateInstrumentType.SWAP_CMS_CMS || type == InterestRateInstrumentType.SWAP_FIXED_CMS || type == InterestRateInstrumentType.SWAP_IBOR_CMS) { builder.add(getVegaQuoteCubeMatrix(ValueProperties.with(ValuePropertyNames.CUBE, "BLOOMBERG"))); } else if (type == InterestRateInstrumentType.SWAP_FIXED_IBOR || type == InterestRateInstrumentType.SWAP_FIXED_IBOR_WITH_SPREAD || type == InterestRateInstrumentType.SWAP_IBOR_IBOR) { builder.add(getPV01(getFundingCurve())); builder.add(getPV01(getForwardCurve(ccy))); } } builder.add(getPresentValue(ValueProperties.builder())); return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitEquityIndexOptionSecurity(final EquityIndexOptionSecurity security) { final ExternalId underlyingId = security.getUnderlyingId(); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getEquityValue(ValueRequirementNames.PRESENT_VALUE, underlyingId)) .add(getEquityValue(ValueRequirementNames.VEGA_QUOTE_MATRIX, underlyingId)) .add(getEquityValue(ValueRequirementNames.VEGA_MATRIX, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VEGA, underlyingId)) .add(getEquityValue(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_DELTA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_GAMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VOMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VANNA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_RHO, underlyingId)) .build(); } @Override public Set<Pair<String, ValueProperties>> visitEquityOptionSecurity(final EquityOptionSecurity security) { final ExternalId underlyingId = security.getUnderlyingId(); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getEquityValue(ValueRequirementNames.PRESENT_VALUE, underlyingId)) .add(getEquityValue(ValueRequirementNames.VEGA_QUOTE_MATRIX, underlyingId)) .add(getEquityValue(ValueRequirementNames.VEGA_MATRIX, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VEGA, underlyingId)) .add(getEquityValue(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_DELTA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_GAMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VOMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VANNA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_RHO, underlyingId)) .build(); } @Override public Set<Pair<String, ValueProperties>> visitEquityBarrierOptionSecurity(final EquityBarrierOptionSecurity security) { final ExternalId underlyingId = security.getUnderlyingId(); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getEquityValue(ValueRequirementNames.PRESENT_VALUE, underlyingId)) .add(getEquityValue(ValueRequirementNames.VEGA_QUOTE_MATRIX, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VEGA, underlyingId)) .add(getEquityValue(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_DELTA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_GAMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VOMMA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_VANNA, underlyingId)) .add(getEquityValue(ValueRequirementNames.VALUE_RHO, underlyingId)) .build(); } @Override public Set<Pair<String, ValueProperties>> visitFXOptionSecurity(final FXOptionSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getFXPresentValueWithCalculationMethod()) .add(getFXCurrencyExposureWithCalculationMethod()) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getCallCurrency()), security.getCallCurrency())) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPutCurrency()), security.getPutCurrency())); final String surfaceName = _configProvider.getFXVanillaOptionSurfaceName(security.getCallCurrency(), security.getPutCurrency()); if (surfaceName != null) { builder.add(getFXVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.FOREX))); builder.add(getFXVegaMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName))); } else { s_logger.warn("Could not build surface name for {}", security); } return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitNonDeliverableFXDigitalOptionSecurity(final NonDeliverableFXDigitalOptionSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getFXPresentValueWithCalculationMethod()) .add(getFXCurrencyExposureWithCalculationMethod()) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getCallCurrency()), security.getCallCurrency())) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPutCurrency()), security.getPutCurrency())); final String surfaceName = _configProvider.getFXVanillaOptionSurfaceName(security.getCallCurrency(), security.getPutCurrency()); if (surfaceName != null) { builder.add(getFXVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.FOREX))); builder.add(getFXVegaMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName))); } else { s_logger.warn("Could not build surface name for {}", security); } return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitNonDeliverableFXOptionSecurity(final NonDeliverableFXOptionSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getFXPresentValueWithCalculationMethod()) .add(getFXCurrencyExposureWithCalculationMethod()) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getCallCurrency()), security.getCallCurrency())) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPutCurrency()), security.getPutCurrency())); final String surfaceName = _configProvider.getFXVanillaOptionSurfaceName(security.getCallCurrency(), security.getPutCurrency()); if (surfaceName != null) { builder.add(getFXVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.FOREX))); builder.add(getFXVegaMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName))); } else { s_logger.warn("Could not build surface name for {}", security); } return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitSwaptionSecurity(final SwaptionSecurity security) { return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency())) .add(getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency())) .addAll(getSabrSensitivities()) .add(getPresentValue(ValueProperties.with(ValuePropertyNames.CUBE, _configProvider.getSwaptionVolatilityCubeName(security.getCurrency())))) .add(getVegaQuoteCubeMatrix(ValueProperties.with(ValuePropertyNames.CUBE, "BLOOMBERG"))).build(); } @Override public Set<Pair<String, ValueProperties>> visitIRFutureOptionSecurity(final IRFutureOptionSecurity security) { final Currency ccy = security.getCurrency(); final String tickerStr = security.getExternalIdBundle().getValue(ExternalSchemes.BLOOMBERG_TICKER); final String futurePrefix = tickerStr.substring(0, 2); final String surfaceName = _configProvider.getIRFutureOptionVolatilitySurfaceName(futurePrefix); return ImmutableSet.<Pair<String, ValueProperties>>builder() .addAll(getSabrSensitivities()) .add(getYieldCurveNodeSensitivities(getFundingCurve(), ccy)) .add(getYieldCurveNodeSensitivities(getForwardCurve(ccy), ccy)) .add(getPresentValue(ValueProperties.with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.IR_FUTURE_OPTION))) .add(getVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.IR_FUTURE_OPTION))).build(); } @Override public Set<Pair<String, ValueProperties>> visitCommodityFutureOptionSecurity(final CommodityFutureOptionSecurity commodityFutureOptionSecurity) { s_logger.warn("Commodity Future Option risk factors not implemented"); return Collections.emptySet(); } @Override public Set<Pair<String, ValueProperties>> visitFxFutureOptionSecurity(final FxFutureOptionSecurity security) { s_logger.warn("FX Future Option risk factors not implemented"); return Collections.emptySet(); } @Override public Set<Pair<String, ValueProperties>> visitEquityIndexDividendFutureOptionSecurity(final EquityIndexDividendFutureOptionSecurity equityIndexDividendFutureOptionSecurity) { s_logger.warn("Equity index dividend future option risk factors not implemented"); return Collections.emptySet(); } @Override public Set<Pair<String, ValueProperties>> visitFXBarrierOptionSecurity(final FXBarrierOptionSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getFXPresentValueWithCalculationMethod()) .add(getFXCurrencyExposureWithCalculationMethod()) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getCallCurrency()), security.getCallCurrency())) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPutCurrency()), security.getPutCurrency())); final String surfaceName = _configProvider.getFXVanillaOptionSurfaceName(security.getCallCurrency(), security.getPutCurrency()); if (surfaceName != null) { builder.add(getFXVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.FOREX))); builder.add(getFXVegaMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName))); } else { s_logger.warn("Could not build surface name for {}", security); } return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitFXDigitalOptionSecurity(final FXDigitalOptionSecurity security) { final ImmutableSet.Builder<Pair<String, ValueProperties>> builder = ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getFXPresentValueWithCalculationMethod()) .add(getFXCurrencyExposureWithCalculationMethod()) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getCallCurrency()), security.getCallCurrency())) .add(getFXYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPutCurrency()), security.getPutCurrency())); final String surfaceName = _configProvider.getFXVanillaOptionSurfaceName(security.getCallCurrency(), security.getPutCurrency()); if (surfaceName != null) { builder.add(getFXVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName) .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, InstrumentTypeProperties.FOREX))); builder.add(getFXVegaMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, surfaceName))); } else { s_logger.warn("Could not build surface name for {}", security); } return builder.build(); } @Override public Set<Pair<String, ValueProperties>> visitFXForwardSecurity(final FXForwardSecurity security) { return ImmutableSet.of( getFXPresentValue(), getFXCurrencyExposure(), getYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPayCurrency()), security.getPayCurrency()), getYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getReceiveCurrency()), security.getReceiveCurrency())); } // REVIEW jim 23-Jan-2012 -- bit of a leap to copy fx forwards, but there you go. @Override public Set<Pair<String, ValueProperties>> visitNonDeliverableFXForwardSecurity( final NonDeliverableFXForwardSecurity security) { return ImmutableSet.of( getFXPresentValue(), getFXCurrencyExposure(), getYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getPayCurrency()), security.getPayCurrency()), getYieldCurveNodeSensitivities(_configProvider.getFXCurve(security.getReceiveCurrency()), security.getReceiveCurrency())); } @Override public Set<Pair<String, ValueProperties>> visitCapFloorSecurity(final CapFloorSecurity security) { final String cubeName = _configProvider.getSwaptionVolatilityCubeName(security.getCurrency()); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency())) .add(getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency())) .addAll(getSabrSensitivities()) .add(getVegaQuoteCubeMatrix(ValueProperties.with(ValuePropertyNames.CUBE, cubeName))) .add(getPresentValue(ValueProperties.with(ValuePropertyNames.CUBE, cubeName))).build(); } @Override public Set<Pair<String, ValueProperties>> visitCapFloorCMSSpreadSecurity(final CapFloorCMSSpreadSecurity security) { final String cubeName = _configProvider.getSwaptionVolatilityCubeName(security.getCurrency()); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency())) .add(getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency())) .addAll(getSabrSensitivities()) .add(getVegaQuoteCubeMatrix(ValueProperties.with(ValuePropertyNames.CUBE, cubeName))) .add(getPresentValue(ValueProperties.with(ValuePropertyNames.CUBE, cubeName))).build(); } @Override public Set<Pair<String, ValueProperties>> visitEquityVarianceSwapSecurity(final EquityVarianceSwapSecurity security) { final String ticker = security.getSpotUnderlyingId().getValue(); if (ticker != null) { return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getPresentValue(ValueProperties.builder())) .add(getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency())) .add(getVegaQuoteMatrix(ValueProperties .with(ValuePropertyNames.SURFACE, "DEFAULT") .with(InstrumentTypeProperties.PROPERTY_SURFACE_INSTRUMENT_TYPE, "EQUITY_OPTION"))).build(); } s_logger.warn("Could not get underlying ticker for equity variance swap security, so excluding surface"); return ImmutableSet.<Pair<String, ValueProperties>>builder() .add(getPresentValue(ValueProperties.builder())) .add(getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency())).build(); } //------------------------------------------------------------------------- // Futures @Override public Set<Pair<String, ValueProperties>> visitAgricultureFutureSecurity(final AgricultureFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitBondFutureSecurity(final BondFutureSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve())); } @Override public Set<Pair<String, ValueProperties>> visitEnergyFutureSecurity(final EnergyFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitFXFutureSecurity(final FXFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitIndexFutureSecurity(final IndexFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitInterestRateFutureSecurity(final InterestRateFutureSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getYieldCurveNodeSensitivities(getForwardCurve(security.getCurrency()), security.getCurrency()), getPresentValue(ValueProperties.builder()), getPV01(getFundingCurve()), getPV01(getForwardCurve(security.getCurrency()))); } @Override public Set<Pair<String, ValueProperties>> visitMetalFutureSecurity(final MetalFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitStockFutureSecurity(final StockFutureSecurity security) { return ImmutableSet.of(); } @Override public Set<Pair<String, ValueProperties>> visitEquityFutureSecurity(final EquityFutureSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder())); } @Override public Set<Pair<String, ValueProperties>> visitEquityIndexDividendFutureSecurity(final EquityIndexDividendFutureSecurity security) { return ImmutableSet.of( getYieldCurveNodeSensitivities(getFundingCurve(), security.getCurrency()), getPresentValue(ValueProperties.builder())); } @Override public Set<Pair<String, ValueProperties>> visitSimpleZeroDepositSecurity(final SimpleZeroDepositSecurity security) { throw new OpenGammaRuntimeException("Simple zero deposit security not supported"); } @Override public Set<Pair<String, ValueProperties>> visitPeriodicZeroDepositSecurity(final PeriodicZeroDepositSecurity security) { throw new OpenGammaRuntimeException("Periodic zero deposit security not supported"); } @Override public Set<Pair<String, ValueProperties>> visitContinuousZeroDepositSecurity(final ContinuousZeroDepositSecurity security) { throw new OpenGammaRuntimeException("Continuous zero deposit security not supported"); } //------------------------------------------------------------------------- private Pair<String, ValueProperties> getYieldCurveNodeSensitivities(final String curve, final Currency currency) { final ValueProperties.Builder constraints = ValueProperties .with(ValuePropertyNames.CURVE_CURRENCY, currency.getCode()) .with(ValuePropertyNames.CURVE, curve); return getRiskFactor(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, constraints); } private Pair<String, ValueProperties> getFXYieldCurveNodeSensitivities(final String curve, final Currency currency) { final ValueProperties.Builder constraints = ValueProperties .with(ValuePropertyNames.CURVE_CURRENCY, currency.getCode()) .with(ValuePropertyNames.CURVE, curve) .with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod()); return getRiskFactor(ValueRequirementNames.YIELD_CURVE_NODE_SENSITIVITIES, constraints); } //FIXME properties aren't correct private Pair<String, ValueProperties> getEquityValue(final String requirementName, final ExternalId underlying) { final com.opengamma.engine.value.ValueProperties.Builder builder = ValueProperties.builder().with(YieldCurveFunction.PROPERTY_FUNDING_CURVE, _configProvider.getEquityFundingCurve()) .with(ValuePropertyNames.SURFACE, _configProvider.getEquityIndexOptionVolatilitySurfaceName(underlying.getValue())) .with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getEquityCalculationMethod()) .with(BlackVolatilitySurfacePropertyNamesAndValues.PROPERTY_SMILE_INTERPOLATOR, _configProvider.getEquitySmileInterpolator()); return getRiskFactor(requirementName, builder); } private Pair<String, ValueProperties> getPresentValue(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.PRESENT_VALUE, constraints); } private Pair<String, ValueProperties> getFXPresentValue() { return getFXPresentValue(ValueProperties.builder()); } private Pair<String, ValueProperties> getFXPresentValueWithCalculationMethod() { return getFXPresentValue(ValueProperties.with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod())); } private Pair<String, ValueProperties> getFXPresentValue(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.FX_PRESENT_VALUE, constraints); } private Pair<String, ValueProperties> getFXCurrencyExposure() { return getFXCurrencyExposure(ValueProperties.builder()); } private Pair<String, ValueProperties> getFXCurrencyExposureWithCalculationMethod() { return getFXCurrencyExposure(ValueProperties.with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod())); } private Pair<String, ValueProperties> getFXCurrencyExposure(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.FX_CURRENCY_EXPOSURE, constraints, false); } private Pair<String, ValueProperties> getVegaMatrix(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.VEGA_MATRIX, constraints, false); } private Pair<String, ValueProperties> getFXVegaMatrix(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.VEGA_MATRIX, constraints.with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod()), false); } private Pair<String, ValueProperties> getVegaQuoteMatrix(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.VEGA_QUOTE_MATRIX, constraints, false); } private Pair<String, ValueProperties> getFXVegaQuoteMatrix(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.VEGA_QUOTE_MATRIX, constraints.with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod()), false); } private Pair<String, ValueProperties> getVegaQuoteCubeMatrix(final ValueProperties.Builder constraints) { return getRiskFactor(ValueRequirementNames.VEGA_QUOTE_CUBE, constraints, false); } private Pair<String, ValueProperties> getValueDelta() { return getRiskFactor(ValueRequirementNames.VALUE_DELTA, ValueProperties.builder()); } private Pair<String, ValueProperties> getPV01(final String curveName) { final ValueProperties.Builder constraints = ValueProperties .with(ValuePropertyNames.CURVE, curveName); return getRiskFactor(ValueRequirementNames.PV01, constraints, true); } private Pair<String, ValueProperties> getFXPV01(final String curveName) { final ValueProperties.Builder constraints = ValueProperties .with(ValuePropertyNames.CURVE, curveName); return getRiskFactor(ValueRequirementNames.PV01, constraints.with(ValuePropertyNames.CALCULATION_METHOD, _configProvider.getFXCalculationMethod()), true); } private Set<Pair<String, ValueProperties>> getSabrSensitivities() { return ImmutableSet.of( getPresentValueSabrAlphaSensitivity(), getPresentValueSabrRhoSensitivity(), getPresentValueSabrNuSensitivity()); } private Pair<String, ValueProperties> getPresentValueSabrAlphaSensitivity() { return getRiskFactor(ValueRequirementNames.PRESENT_VALUE_SABR_ALPHA_SENSITIVITY); } private Pair<String, ValueProperties> getPresentValueSabrRhoSensitivity() { return getRiskFactor(ValueRequirementNames.PRESENT_VALUE_SABR_RHO_SENSITIVITY); } private Pair<String, ValueProperties> getPresentValueSabrNuSensitivity() { return getRiskFactor(ValueRequirementNames.PRESENT_VALUE_SABR_NU_SENSITIVITY); } //------------------------------------------------------------------------- private Pair<String, ValueProperties> getRiskFactor(final String valueName) { return getRiskFactor(valueName, ValueProperties.builder(), true); } private Pair<String, ValueProperties> getRiskFactor(final String valueName, final ValueProperties.Builder constraints) { return getRiskFactor(valueName, constraints, true); } private Pair<String, ValueProperties> getRiskFactor(final String valueName, final ValueProperties.Builder constraints, final boolean allowCurrencyOverride) { ArgumentChecker.notNull(valueName, "valueName"); ArgumentChecker.notNull(constraints, "constraints"); if (allowCurrencyOverride && getConfigProvider().getCurrencyOverride() != null) { constraints.with(ValuePropertyNames.CURRENCY, getConfigProvider().getCurrencyOverride().getCode()); } constraints.with(ValuePropertyNames.AGGREGATION, MissingInputsFunction.AGGREGATION_STYLE_MISSING).withOptional(ValuePropertyNames.AGGREGATION); return Pairs.of(valueName, constraints.get()); } private ValueRequirement getValueRequirement(final Position position, final String valueName, final ValueProperties constraints) { return new ValueRequirement(valueName, ComputationTargetSpecification.of(position), constraints); } //------------------------------------------------------------------------- private String getFundingCurve() { return getConfigProvider().getFundingCurve(); } private String getForwardCurve(final Currency currency) { return getConfigProvider().getForwardCurve(currency); } //------------------------------------------------------------------------- @SuppressWarnings("unused") private SecuritySource getSecuritySource() { return _securities; } private RiskFactorsConfigurationProvider getConfigProvider() { return _configProvider; } }