class ForexNonDeliverableOptionBlackSmileMethod {

  public MultipleCurrencyAmount currencyExposure(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(); // The strike is 1 ccy2=X ccy1; we want the price in ccy2 => we need 1 ccy1 = 1/X ccy2.
    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 sign = (optionForex.isLong() ? 1.0 : -1.0);
    final double price = priceAdjoint[0] * Math.abs(optionForex.getUnderlyingNDF().getNotionalCurrency1()) * sign;
    final double deltaSpot = priceAdjoint[1] * dfNonDelivery / dfDelivery;
    final CurrencyAmount[] currencyExposure = new CurrencyAmount[2];
    // Implementation note: foreign currency (currency 1) exposure = Delta_spot * amount1.
    currencyExposure[0] = CurrencyAmount.of(optionForex.getCurrency1(), deltaSpot * Math.abs(optionForex.getUnderlyingNDF().getNotionalCurrency1()) * sign);
    // Implementation note: domestic currency (currency 2) exposure = -Delta_spot * amount1 * spot+PV
    currencyExposure[1] = CurrencyAmount.of(optionForex.getCurrency2(), -deltaSpot * Math.abs(optionForex.getUnderlyingNDF().getNotionalCurrency1()) * spot * sign + price);
    return MultipleCurrencyAmount.of(currencyExposure);
  }

  private  ForexNonDeliverableOptionBlackSmileMethod();

}