ForexOptionSingleBarrierBlackMethod { public PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves) { ArgumentChecker.notNull(optionForex, "Forex option"); ArgumentChecker.notNull(smileMulticurves, "Smile"); ArgumentChecker.isTrue(smileMulticurves.checkCurrencies(optionForex.getCurrency1(), optionForex.getCurrency2()), "Option currencies not compatible with smile data"); final MulticurveProviderInterface multicurves = smileMulticurves.getMulticurveProvider(); final double payTime = optionForex.getUnderlyingOption().getUnderlyingForex().getPaymentTime(); final double dfDomestic = multicurves.getDiscountFactor(optionForex.getCurrency2(), payTime); final double dfForeign = multicurves.getDiscountFactor(optionForex.getCurrency1(), payTime); final double rateDomestic = -Math.log(dfDomestic) / payTime; final double rateForeign = -Math.log(dfForeign) / payTime; final double spot = multicurves.getFxRate(optionForex.getCurrency1(), optionForex.getCurrency2()); final double forward = spot * Math.exp(-rateForeign * payTime) / Math.exp(-rateDomestic * payTime); final double foreignAmount = optionForex.getUnderlyingOption().getUnderlyingForex().getPaymentCurrency1().getAmount(); final double rebateByForeignUnit = optionForex.getRebate() / Math.abs(foreignAmount); final double sign = (optionForex.getUnderlyingOption().isLong() ? 1.0 : -1.0); final double volatility = smileMulticurves.getVolatility(optionForex.getCurrency1(), optionForex.getCurrency2(), optionForex.getUnderlyingOption().getTimeToExpiry(), optionForex .getUnderlyingOption().getStrike(), forward); final double[] priceDerivatives = new double[5]; BARRIER_FUNCTION.getPriceAdjoint(optionForex.getUnderlyingOption(), optionForex.getBarrier(), rebateByForeignUnit, spot, rateDomestic - rateForeign, rateDomestic, volatility, priceDerivatives); final double volatilitySensitivityValue = priceDerivatives[4] * Math.abs(foreignAmount) * sign; final DoublesPair point = DoublesPair.of(optionForex.getUnderlyingOption().getTimeToExpiry(), optionForex.getUnderlyingOption().getStrike()); final SurfaceValue result = SurfaceValue.from(point, volatilitySensitivityValue); final PresentValueForexBlackVolatilitySensitivity sensi = new PresentValueForexBlackVolatilitySensitivity(optionForex.getUnderlyingOption().getUnderlyingForex().getCurrency1(), optionForex .getUnderlyingOption().getUnderlyingForex().getCurrency2(), result); return sensi; } private  ForexOptionSingleBarrierBlackMethod(); static ForexOptionSingleBarrierBlackMethod getInstance(); MultipleCurrencyAmount presentValue(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); MultipleCurrencyAmount currencyExposure(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); PresentValueForexBlackVolatilityNodeSensitivityDataBundle presentValueBlackVolatilityNodeSensitivity(final ForexOptionSingleBarrier optionForex,
      final BlackForexSmileProviderInterface smileMulticurves); CurrencyAmount gammaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount gammaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); CurrencyAmount vommaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount vommaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); CurrencyAmount vannaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount vannaFd(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves); CurrencyAmount dVegaDSpotFD(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount dDeltaDVolFD(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount d2PriceDSpotDVolFD(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift); CurrencyAmount d2PriceDSpotDVolFdAlt(final ForexOptionSingleBarrier optionForex, final BlackForexSmileProviderInterface smileMulticurves, final double relShift);  }
@Test public void volatilitySensitivity() { final PresentValueForexBlackVolatilitySensitivity sensi = METHOD_BARRIER.presentValueBlackVolatilitySensitivity(OPTION_BARRIER, SMILE_MULTICURVES); final Pair<Currency, Currency> currencyPair = Pairs.of(EUR, USD); final DoublesPair point = DoublesPair.of(OPTION_BARRIER.getUnderlyingOption().getTimeToExpiry(), STRIKE); assertEquals("Forex vanilla option: vega", currencyPair, sensi.getCurrencyPair()); assertEquals("Forex vanilla option: vega size", 1, sensi.getVega().getMap().entrySet().size()); assertTrue("Forex vanilla option: vega", sensi.getVega().getMap().containsKey(point)); final double timeToExpiry = TimeCalculator.getTimeBetween(REFERENCE_DATE, OPTION_EXPIRY_DATE); final double payTime = TimeCalculator.getTimeBetween(REFERENCE_DATE, OPTION_PAY_DATE); final double dfDomestic = MULTICURVES.getDiscountFactor(USD, payTime); final double dfForeign = MULTICURVES.getDiscountFactor(EUR, payTime); final double forward = SPOT * dfForeign / dfDomestic; final double rateDomestic = -Math.log(dfDomestic) / payTime; final double rateForeign = -Math.log(dfForeign) / payTime; final double volatility = SMILE_TERM.getVolatility(Triple.of(timeToExpiry, STRIKE, forward)); final double[] derivatives = new double[5]; BLACK_BARRIER_FUNCTION.getPriceAdjoint(VANILLA_LONG, BARRIER_KI, REBATE / NOTIONAL, SPOT, rateDomestic - rateForeign, rateDomestic, volatility, derivatives); assertEquals("Forex vanilla option: vega", derivatives[4] * NOTIONAL, sensi.getVega().getMap().get(point)); final PresentValueForexBlackVolatilitySensitivity sensiShort = METHOD_BARRIER.presentValueBlackVolatilitySensitivity(BARRIER_SHORT, SMILE_MULTICURVES); assertEquals("Forex vanilla option: vega short", -sensi.getVega().getMap().get(point), sensiShort.getVega().getMap().get(point)); }
@Test public void volatilitySensitivityMethodVsCalculator() { final PresentValueForexBlackVolatilitySensitivity pvvsMethod = METHOD_BARRIER.presentValueBlackVolatilitySensitivity(OPTION_BARRIER, SMILE_MULTICURVES); final PresentValueForexBlackVolatilitySensitivity pvvsCalculator = OPTION_BARRIER.accept(PVFVFBC, SMILE_MULTICURVES); assertEquals("Forex present value curve sensitivity: Method vs Calculator", pvvsMethod, pvvsCalculator); }