ForexOptionVanillaVannaVolgaMethod { public PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexOptionVanilla optionForex, final BlackForexVannaVolgaProviderInterface 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 dfDomestic = multicurves.getDiscountFactor(optionForex.getCurrency2(), optionForex.getUnderlyingForex().getPaymentTime()); final double dfForeign = multicurves.getDiscountFactor(optionForex.getCurrency1(), optionForex.getUnderlyingForex().getPaymentTime()); final double spot = multicurves.getFxRate(optionForex.getCurrency1(), optionForex.getCurrency2()); final double forward = spot * dfForeign / dfDomestic; final SmileDeltaParameters smileAtTime = smileMulticurves.getSmile(optionForex.getCurrency1(), optionForex.getCurrency2(), optionForex.getTimeToExpiry()); final double[] strikesVV = smileAtTime.getStrike(forward); final double[] volVV = smileAtTime.getVolatility(); final double volATM = volVV[1]; final double[] priceVVATM = new double[3]; final double[] priceVVsmile = new double[3]; final double[] vegaSmile = new double[3]; final BlackFunctionData dataBlackATM = new BlackFunctionData(forward, dfDomestic, volATM); for (int loopvv = 0; loopvv < 3; loopvv = loopvv + 2) { final BlackFunctionData dataBlackSmile = new BlackFunctionData(forward, dfDomestic, volVV[loopvv]); final EuropeanVanillaOption optionVV = new EuropeanVanillaOption(strikesVV[loopvv], optionForex.getTimeToExpiry(), true); priceVVATM[loopvv] = BLACK_FUNCTION.getPriceFunction(optionVV).evaluate(dataBlackATM); priceVVsmile[loopvv] = BLACK_FUNCTION.getPriceFunction(optionVV).evaluate(dataBlackSmile); vegaSmile[loopvv] = BLACK_FUNCTION.getVegaFunction(optionVV).evaluate(dataBlackSmile); } final double[] vega = new double[3]; final double[] x = vannaVolgaWeights(optionForex, forward, dfDomestic, strikesVV, volVV, vega); final double[] vegaReference = new double[3]; vegaReference[0] = x[0] * vegaSmile[0]; vegaReference[2] = x[2] * vegaSmile[2]; vegaReference[1] = vega[1] - x[0] * vega[0] - x[2] * vega[2]; final SurfaceValue result = new SurfaceValue(); for (int loopvv = 0; loopvv < 3; loopvv++) { final DoublesPair point = DoublesPair.of(optionForex.getTimeToExpiry(), strikesVV[loopvv]); result.add(point, vegaReference[loopvv] * Math.abs(optionForex.getUnderlyingForex().getPaymentCurrency1().getAmount()) * (optionForex.isLong() ? 1.0 : -1.0)); } final PresentValueForexBlackVolatilitySensitivity sensi = new PresentValueForexBlackVolatilitySensitivity(optionForex.getUnderlyingForex().getCurrency1(), optionForex.getUnderlyingForex() .getCurrency2(), result); return sensi; } private  ForexOptionVanillaVannaVolgaMethod(); static ForexOptionVanillaVannaVolgaMethod getInstance(); MultipleCurrencyAmount presentValue(final ForexOptionVanilla optionForex, final BlackForexVannaVolgaProviderInterface smileMulticurves); MultipleCurrencyAmount currencyExposure(final ForexOptionVanilla optionForex, final BlackForexVannaVolgaProviderInterface smileMulticurves); PresentValueForexBlackVolatilitySensitivity presentValueBlackVolatilitySensitivity(final ForexOptionVanilla optionForex, final BlackForexVannaVolgaProviderInterface smileMulticurves); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final ForexOptionVanilla optionForex, final BlackForexVannaVolgaProviderInterface smileMulticurves); double[] vannaVolgaWeights(final ForexOptionVanilla optionForex, final double forward, final double dfDomestic, final double[] strikesReference, final double[] volatilitiesReference); double[] vannaVolgaWeights(final ForexOptionVanilla optionForex, final double forward, final double dfDomestic, final double[] strikesReference, final double[] volatilitiesReference,
      final double[] vega);  }
@Test(enabled = true) public void analysisVega() { final int nbStrike = 50; final double strikeMin = 0.85; final double strikeRange = 1.00; final double[] strikes = new double[nbStrike + 1]; final boolean isCall = true; final boolean isLong = true; final double notional = 1000000; final ZonedDateTime optionExpiry = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE, Period.ofMonths(18), BUSINESS_DAY, CALENDAR); final ZonedDateTime optionPay = ScheduleCalculator.getAdjustedDate(optionExpiry, SETTLEMENT_DAYS, CALENDAR); final ForexOptionVanilla[] forexOption = new ForexOptionVanilla[nbStrike + 1]; for (int loopstrike = 0; loopstrike <= nbStrike; loopstrike++) { strikes[loopstrike] = strikeMin + loopstrike * strikeRange / nbStrike; final ForexDefinition forexUnderlyingDefinition = new ForexDefinition(EUR, USD, optionPay, notional, strikes[loopstrike]); final ForexOptionVanillaDefinition forexOptionDefinition = new ForexOptionVanillaDefinition(forexUnderlyingDefinition, optionExpiry, isCall, isLong); forexOption[loopstrike] = forexOptionDefinition.toDerivative(REFERENCE_DATE); } final double forward = METHOD_BLACK.forwardForexRate(forexOption[0], MULTICURVES); final SmileDeltaParameters smileTime = SMILE_TERM.getSmileForTime(forexOption[0].getTimeToExpiry()); final double[] strikesVV = smileTime.getStrike(forward); final PresentValueForexBlackVolatilitySensitivity[] vegaObject = new PresentValueForexBlackVolatilitySensitivity[nbStrike + 1]; final double[][] vegaVV = new double[3][nbStrike + 1]; final double[] vegaBlack = new double[nbStrike + 1]; for (int loopstrike = 0; loopstrike <= nbStrike; loopstrike++) { vegaObject[loopstrike] = METHOD_VANNA_VOLGA.presentValueBlackVolatilitySensitivity(forexOption[loopstrike], VANNAVOLGA_MULTICURVES); for (int loopvv = 0; loopvv < 3; loopvv++) { final DoublesPair point = DoublesPair.of(forexOption[loopstrike].getTimeToExpiry(), strikesVV[loopvv]); vegaVV[loopvv][loopstrike] = vegaObject[loopstrike].getVega().getMap().get(point); } vegaBlack[loopstrike] = METHOD_BLACK.presentValueBlackVolatilitySensitivity(forexOption[loopstrike], SMILE_MULTICURVES).toSingleValue().getAmount(); } }