/**
  * Computes the price curve sensitivity in the Hull-White one factor model.
  *
  * @param security The option security.
  * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters.
  * @return The curve sensitivity.
  */
 @Override
 public MulticurveSensitivity priceCurveSensitivity(
     final InterestRateFutureOptionMarginSecurity security,
     final HullWhiteOneFactorProviderInterface hwMulticurves) {
   ArgumentChecker.notNull(security, "Option security");
   ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data");
   ArgumentChecker.isTrue(
       security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()),
       "Model currency incompatible with security currency");
   final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider();
   final HullWhiteOneFactorPiecewiseConstantParameters parameters =
       hwMulticurves.getHullWhiteParameters();
   final double k = security.getStrike();
   final double ktilde = 1.0 - k;
   final double theta = security.getExpirationTime();
   final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor();
   final double t0 = security.getUnderlyingFuture().getTradingLastTime();
   final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime();
   final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime();
   // forward sweep
   final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2);
   final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2);
   final double forward =
       multicurves.getSimplyCompoundForwardRate(
           security.getUnderlyingFuture().getIborIndex(), t1, t2, delta);
   final double kappa =
       -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha;
   // Bakcward sweep
   final double priceBar = 1.0;
   double forwardBar;
   if (security.isCall()) {
     final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha);
     forwardBar = -gamma * normalAlphaKappa * priceBar;
   } else {
     final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha);
     forwardBar = gamma * normalAlphaKappa * priceBar;
   }
   final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>();
   final List<ForwardSensitivity> listForward = new ArrayList<>();
   listForward.add(new SimplyCompoundedForwardSensitivity(t1, t2, delta, forwardBar));
   mapFwd.put(
       hwMulticurves
           .getMulticurveProvider()
           .getName(security.getUnderlyingFuture().getIborIndex()),
       listForward);
   return MulticurveSensitivity.ofForward(mapFwd);
 }
 /**
  * Returns the convexity adjustment, i.e. the difference between the adjusted price and the
  * present value of the underlying swap.
  *
  * @param futures The swap futures.
  * @param hwMulticurves The multi-curve and parameters provider.
  * @return The adjustment.
  */
 public double convexityAdjustment(
     final SwapFuturesPriceDeliverableSecurity futures,
     final HullWhiteOneFactorProviderInterface hwMulticurves) {
   ArgChecker.notNull(futures, "swap futures");
   ArgChecker.notNull(hwMulticurves, "parameter provider");
   MultiCurrencyAmount pv =
       futures.getUnderlyingSwap().accept(PVDC, hwMulticurves.getMulticurveProvider());
   double price = price(futures, hwMulticurves);
   return price - (1.0d + pv.getAmount(futures.getCurrency()).getAmount());
 }
 /**
  * Computes the price in the Hull-White one factor model.
  *
  * @param security The option security.
  * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters.
  * @return The price.
  */
 @Override
 public double price(
     final InterestRateFutureOptionMarginSecurity security,
     final HullWhiteOneFactorProviderInterface hwMulticurves) {
   ArgumentChecker.notNull(security, "Option security");
   ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data");
   ArgumentChecker.isTrue(
       security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()),
       "Model currency incompatible with security currency");
   final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider();
   final HullWhiteOneFactorPiecewiseConstantParameters parameters =
       hwMulticurves.getHullWhiteParameters();
   final double k = security.getStrike();
   final double ktilde = 1.0 - k;
   final double theta = security.getExpirationTime();
   final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor();
   final double t0 = security.getUnderlyingFuture().getTradingLastTime();
   final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime();
   final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime();
   final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2);
   final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2);
   final double forward =
       multicurves.getSimplyCompoundForwardRate(
           security.getUnderlyingFuture().getIborIndex(), t1, t2, delta);
   final double kappa =
       -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha;
   if (security.isCall()) {
     final double normalKappa = NORMAL.getCDF(-kappa);
     final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha);
     return (1 - k + 1.0 / delta) * normalKappa
         - (1.0 / delta + forward) * gamma * normalAlphaKappa;
   }
   final double normalKappa = NORMAL.getCDF(kappa);
   final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha);
   return (1.0 / delta + forward) * gamma * normalAlphaKappa - (1 - k + 1.0 / delta) * normalKappa;
 }