/**
  * Computes the present value of the Physical delivery swaption.
  *
  * @param swaption The swaption.
  * @param hwData The Hull-White parameters and the curves.
  * @return The present value.
  */
 public CurrencyAmount presentValue(
     final SwaptionPhysicalFixedIbor swaption,
     final HullWhiteOneFactorPiecewiseConstantDataBundle hwData) {
   Validate.notNull(swaption);
   Validate.notNull(hwData);
   final double expiryTime = swaption.getTimeToExpiry();
   final AnnuityPaymentFixed cfe = swaption.getUnderlyingSwap().accept(CFEC, hwData);
   final double[] alpha = new double[cfe.getNumberOfPayments()];
   final double[] df = new double[cfe.getNumberOfPayments()];
   final double[] discountedCashFlow = new double[cfe.getNumberOfPayments()];
   for (int loopcf = 0; loopcf < cfe.getNumberOfPayments(); loopcf++) {
     alpha[loopcf] =
         MODEL.alpha(
             hwData.getHullWhiteParameter(),
             0.0,
             expiryTime,
             expiryTime,
             cfe.getNthPayment(loopcf).getPaymentTime());
     df[loopcf] =
         hwData
             .getCurve(cfe.getDiscountCurve())
             .getDiscountFactor(cfe.getNthPayment(loopcf).getPaymentTime());
     discountedCashFlow[loopcf] = df[loopcf] * cfe.getNthPayment(loopcf).getAmount();
   }
   // Integration
   final SwaptionIntegrant integrant = new SwaptionIntegrant(discountedCashFlow, alpha);
   final double limit = 10.0;
   final double absoluteTolerance = 1.0E-2;
   final double relativeTolerance = 1.0E-6;
   final RungeKuttaIntegrator1D integrator =
       new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, NB_INTEGRATION);
   double pv = 0.0;
   try {
     pv =
         1.0
             / Math.sqrt(2.0 * Math.PI)
             * integrator.integrate(integrant, -limit, limit)
             * (swaption.isLong() ? 1.0 : -1.0);
   } catch (final Exception e) {
     throw new RuntimeException(e);
   }
   return CurrencyAmount.of(swaption.getCurrency(), pv);
 }
 /**
  * Computes the price of a future from the curves using an estimation of the future rate without
  * convexity adjustment.
  *
  * @param future The future.
  * @param curves The Hull-White parameters and the curves.
  * @return The price.
  */
 public double price(
     final InterestRateFutureSecurity future,
     final HullWhiteOneFactorPiecewiseConstantDataBundle curves) {
   Validate.notNull(future, "Future");
   Validate.notNull(curves, "Curves");
   final YieldAndDiscountCurve forwardCurve = curves.getCurve(future.getForwardCurveName());
   final double dfForwardStart = forwardCurve.getDiscountFactor(future.getFixingPeriodStartTime());
   final double dfForwardEnd = forwardCurve.getDiscountFactor(future.getFixingPeriodEndTime());
   final double forward =
       (dfForwardStart / dfForwardEnd - 1) / future.getFixingPeriodAccrualFactor();
   final double futureConvexityFactor =
       MODEL.futuresConvexityFactor(
           curves.getHullWhiteParameter(),
           future.getTradingLastTime(),
           future.getFixingPeriodStartTime(),
           future.getFixingPeriodEndTime());
   final double price =
       1.0
           - futureConvexityFactor * forward
           + (1 - futureConvexityFactor) / future.getFixingPeriodAccrualFactor();
   return price;
 }
 /**
  * Compute the price sensitivity to rates of a interest rate future by discounting.
  *
  * @param future The future.
  * @param curves The Hull-White parameters and the curves.
  * @return The price rate sensitivity.
  */
 public InterestRateCurveSensitivity priceCurveSensitivity(
     final InterestRateFutureSecurity future,
     final HullWhiteOneFactorPiecewiseConstantDataBundle curves) {
   ArgumentChecker.notNull(future, "Future");
   ArgumentChecker.notNull(curves, "Curves");
   final YieldAndDiscountCurve forwardCurve = curves.getCurve(future.getForwardCurveName());
   final double dfForwardStart = forwardCurve.getDiscountFactor(future.getFixingPeriodStartTime());
   final double dfForwardEnd = forwardCurve.getDiscountFactor(future.getFixingPeriodEndTime());
   final double futureConvexityFactor =
       MODEL.futuresConvexityFactor(
           curves.getHullWhiteParameter(),
           future.getTradingLastTime(),
           future.getFixingPeriodStartTime(),
           future.getFixingPeriodEndTime());
   // Backward sweep
   final double priceBar = 1.0;
   final double forwardBar = -futureConvexityFactor * priceBar;
   final double dfForwardEndBar =
       -dfForwardStart
           / (dfForwardEnd * dfForwardEnd)
           / future.getFixingPeriodAccrualFactor()
           * forwardBar;
   final double dfForwardStartBar =
       1.0 / (future.getFixingPeriodAccrualFactor() * dfForwardEnd) * forwardBar;
   final Map<String, List<DoublesPair>> resultMap = new HashMap<>();
   final List<DoublesPair> listForward = new ArrayList<>();
   listForward.add(
       DoublesPair.of(
           future.getFixingPeriodStartTime(),
           -future.getFixingPeriodStartTime() * dfForwardStart * dfForwardStartBar));
   listForward.add(
       DoublesPair.of(
           future.getFixingPeriodEndTime(),
           -future.getFixingPeriodEndTime() * dfForwardEnd * dfForwardEndBar));
   resultMap.put(future.getForwardCurveName(), listForward);
   final InterestRateCurveSensitivity result = new InterestRateCurveSensitivity(resultMap);
   return result;
 }