ForexNonDeliverableOptionBlackSmileMethod { public PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexNonDeliverableOption optionForex, final BlackForexSmileProviderInterface smileMulticurves) { Validate.notNull(optionForex, "Forex option"); Validate.notNull(smileMulticurves, "Smile"); Validate.isTrue(smileMulticurves.checkCurrencies(optionForex.getCurrency1(), optionForex.getCurrency2()), "Option currencies not compatible with smile data"); final MulticurveProviderInterface multicurves = smileMulticurves.getMulticurveProvider(); final double paymentTime = optionForex.getUnderlyingNDF().getPaymentTime(); final double expiryTime = optionForex.getExpiryTime(); final double strike = 1.0 / optionForex.getStrike(); final double dfDelivery = multicurves.getDiscountFactor(optionForex.getCurrency2(), paymentTime); final double dfNonDelivery = multicurves.getDiscountFactor(optionForex.getCurrency1(), paymentTime); final double spot = multicurves.getFxRate(optionForex.getCurrency1(), optionForex.getCurrency2()); final double forward = spot * dfNonDelivery / dfDelivery; final double volatility = smileMulticurves.getVolatility(optionForex.getCurrency1(), optionForex.getCurrency2(), expiryTime, strike, forward); final BlackFunctionData dataBlack = new BlackFunctionData(forward, dfDelivery, volatility); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, expiryTime, !optionForex.isCall()); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); final double volatilitySensitivityValue = priceAdjoint[2] * Math.abs(optionForex.getUnderlyingNDF().getNotionalCurrency1()) * (optionForex.isLong() ? 1.0 : -1.0); final DoublesPair point = DoublesPair.of(optionForex.getExpiryTime(), (optionForex.getCurrency1() == smileMulticurves.getCurrencyPair().getFirst()) ? strike : 1.0 / strike); final SurfaceValue result = SurfaceValue.from(point, volatilitySensitivityValue); final PresentValueForexBlackVolatilitySensitivity sensi = new PresentValueForexBlackVolatilitySensitivity(optionForex.getCurrency1(), optionForex.getCurrency2(), result); return sensi; } private  ForexNonDeliverableOptionBlackSmileMethod(); static ForexNonDeliverableOptionBlackSmileMethod getInstance(); MultipleCurrencyAmount presentValue(final ForexNonDeliverableOption optionForex, final BlackForexSmileProviderInterface smileMulticurves); MultipleCurrencyAmount currencyExposure(final ForexNonDeliverableOption optionForex, final BlackForexSmileProviderInterface smileMulticurves); double forwardForexRate(final ForexNonDeliverableOption ndo, final MulticurveProviderInterface multicurves); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final ForexNonDeliverableOption optionForex, final BlackForexSmileProviderInterface smileMulticurves); PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexNonDeliverableOption optionForex, final BlackForexSmileProviderInterface smileMulticurves); PresentValueForexBlackVolatilityNodeSensitivityDataBundle presentValueVolatilityNodeSensitivity(final ForexNonDeliverableOption optionForex,
      final BlackForexSmileProviderInterface smileMulticurves);  }
@Test public void presentValueVolatilitySensitivity() { final PresentValueForexBlackVolatilitySensitivity pvvsNDO = METHOD_NDO.presentValueBlackVolatilitySensitivity(NDO, SMILE_MULTICURVES); final PresentValueForexBlackVolatilitySensitivity pvvsFXO = METHOD_FXO.presentValueBlackVolatilitySensitivity(FOREX_OPT, SMILE_MULTICURVES); final DoublesPair point = DoublesPair.of(NDO.getExpiryTime(), NDO.getStrike()); assertEquals("Forex non-deliverable option: present value curve sensitivity", pvvsFXO.getVega().getMap().get(point), pvvsNDO.getVega().getMap().get(point), TOLERANCE_PV_DELTA); }