public PresentValueForexBlackVolatilityNodeSensitivityDataBundle presentValueBlackVolatilityNodeSensitivity(final ForexOptionDigital optionForex, final SmileDeltaTermStructureDataBundle smile) {
ArgumentChecker.notNull(optionForex, "Forex option");
ArgumentChecker.notNull(smile, "Smile");
ArgumentChecker.isTrue(smile.checkCurrencies(optionForex.getCurrency1(), optionForex.getCurrency2()), "Option currencies not compatible with smile data");
final PresentValueForexBlackVolatilitySensitivity pointSensitivity = presentValueBlackVolatilitySensitivity(optionForex, smile); // In dom ccy
final SmileDeltaTermStructureParametersStrikeInterpolation volatilityModel = smile.getVolatilityModel();
final double payTime = optionForex.getUnderlyingForex().getPaymentTime();
final double expiry = optionForex.getExpirationTime();
// Forward sweep
final Currency domesticCcy;
final Currency foreignCcy;
final double strike;
final String foreignCurveName;
final String domesticCurveName;
if (optionForex.payDomestic()) {
foreignCurveName = optionForex.getUnderlyingForex().getPaymentCurrency1().getFundingCurveName();
domesticCurveName = optionForex.getUnderlyingForex().getPaymentCurrency2().getFundingCurveName();
domesticCcy = optionForex.getUnderlyingForex().getCurrency2();
foreignCcy = optionForex.getUnderlyingForex().getCurrency1();
strike = optionForex.getStrike();
} else {
foreignCurveName = optionForex.getUnderlyingForex().getPaymentCurrency2().getFundingCurveName();
domesticCurveName = optionForex.getUnderlyingForex().getPaymentCurrency1().getFundingCurveName();
strike = 1.0 / optionForex.getStrike();
domesticCcy = optionForex.getUnderlyingForex().getCurrency1();
foreignCcy = optionForex.getUnderlyingForex().getCurrency2();
}
final double dfDomestic = smile.getCurve(domesticCurveName).getDiscountFactor(payTime);
final double dfForeign = smile.getCurve(foreignCurveName).getDiscountFactor(payTime);
final double spot = smile.getFxRates().getFxRate(foreignCcy, domesticCcy);
final double forward = spot * dfForeign / dfDomestic;
final VolatilityAndBucketedSensitivities volAndSensitivities = FXVolatilityUtils.getVolatilityAndSensitivities(smile, foreignCcy, domesticCcy, expiry, forward, forward);
final double[][] nodeWeight = volAndSensitivities.getBucketedSensitivities();
final DoublesPair point = DoublesPair.of(optionForex.getExpirationTime(), (foreignCcy == smile.getCurrencyPair().getFirst()) ? strike : 1.0 / strike);
final double[][] vega = new double[volatilityModel.getNumberExpiration()][volatilityModel.getNumberStrike()];
for (int loopexp = 0; loopexp < volatilityModel.getNumberExpiration(); loopexp++) {
for (int loopstrike = 0; loopstrike < volatilityModel.getNumberStrike(); loopstrike++) {
vega[loopexp][loopstrike] = nodeWeight[loopexp][loopstrike] * pointSensitivity.getVega().getMap().get(point);
}
}
return new PresentValueForexBlackVolatilityNodeSensitivityDataBundle(optionForex.getUnderlyingForex().getCurrency1(), optionForex.getUnderlyingForex().getCurrency2(),
new DoubleMatrix1D(volatilityModel.getTimeToExpiration()), new DoubleMatrix1D(volatilityModel.getDeltaFull()), new DoubleMatrix2D(vega));
}