/**
* Tests present value volatility sensitivity.
*/
public void volatilitySensitivity() {
final double shift = 1.0E-6;
final PresentValueForexBlackVolatilitySensitivity sensi = METHOD_BLACK_DIGITAL.presentValueBlackVolatilitySensitivity(FOREX_DIGITAL_CALL_DOM, SMILE_MULTICURVES);
final Pair<Currency, Currency> currencyPair = ObjectsPair.of(EUR, USD);
final DoublesPair point = new DoublesPair(FOREX_DIGITAL_CALL_DOM.getExpirationTime(), STRIKE);
assertEquals("Forex Digital option: vega", currencyPair, sensi.getCurrencyPair());
assertEquals("Forex Digital option: vega size", 1, sensi.getVega().getMap().entrySet().size());
assertTrue("Forex Digital option: vega", sensi.getVega().getMap().containsKey(point));
final double strike = FOREX_DIGITAL_CALL_DOM.getStrike();
final int omega = FOREX_DIGITAL_CALL_DOM.isCall() ? 1 : -1;
final double dfDomestic = MULTICURVES.getDiscountFactor(USD, FOREX_DIGITAL_CALL_DOM.getUnderlyingForex().getPaymentTime());
final double dfForeign = MULTICURVES.getDiscountFactor(EUR, FOREX_DIGITAL_CALL_DOM.getUnderlyingForex().getPaymentTime());
final double forward = SPOT * dfForeign / dfDomestic;
final double volatility = SMILE_TERM.getVolatility(new Triple<>(FOREX_DIGITAL_CALL_DOM.getExpirationTime(), strike, forward));
final double sigmaRootTPlus = (volatility + shift) * Math.sqrt(FOREX_DIGITAL_CALL_DOM.getExpirationTime());
final double dMPlus = Math.log(forward / strike) / sigmaRootTPlus - 0.5 * sigmaRootTPlus;
final double pvPlus = Math.abs(FOREX_DIGITAL_CALL_DOM.getUnderlyingForex().getPaymentCurrency2().getAmount()) * dfDomestic * NORMAL.getCDF(omega * dMPlus)
* (FOREX_DIGITAL_CALL_DOM.isLong() ? 1.0 : -1.0);
final double sigmaRootTMinus = (volatility - shift) * Math.sqrt(FOREX_DIGITAL_CALL_DOM.getExpirationTime());
final double dMMinus = Math.log(forward / strike) / sigmaRootTMinus - 0.5 * sigmaRootTMinus;
final double pvMinus = Math.abs(FOREX_DIGITAL_CALL_DOM.getUnderlyingForex().getPaymentCurrency2().getAmount()) * dfDomestic * NORMAL.getCDF(omega * dMMinus)
* (FOREX_DIGITAL_CALL_DOM.isLong() ? 1.0 : -1.0);
assertEquals("Forex Digital option: vega", (pvPlus - pvMinus) / (2 * shift), sensi.getVega().getMap().get(point), TOLERANCE_PV);
final ForexOptionDigitalDefinition optionShortDefinition = new ForexOptionDigitalDefinition(FOREX_DEFINITION, OPTION_EXP_DATE, IS_CALL, !IS_LONG);
final ForexOptionDigital optionShort = optionShortDefinition.toDerivative(REFERENCE_DATE);
final PresentValueForexBlackVolatilitySensitivity sensiShort = METHOD_BLACK_DIGITAL.presentValueBlackVolatilitySensitivity(optionShort, SMILE_MULTICURVES);
assertEquals("Forex Digital option: vega short", -sensi.getVega().getMap().get(point), sensiShort.getVega().getMap().get(point));
// Put/call parity
final ForexOptionDigitalDefinition optionShortPutDefinition = new ForexOptionDigitalDefinition(FOREX_DEFINITION, OPTION_EXP_DATE, !IS_CALL, IS_LONG);
final ForexOptionDigital optionShortPut = optionShortPutDefinition.toDerivative(REFERENCE_DATE);
final PresentValueForexBlackVolatilitySensitivity sensiShortPut = METHOD_BLACK_DIGITAL.presentValueBlackVolatilitySensitivity(optionShortPut, SMILE_MULTICURVES);
assertEquals("Forex Digital option: vega short", sensiShortPut.getVega().getMap().get(point) + sensi.getVega().getMap().get(point), 0.0, TOLERANCE_PV);
}