/**
  * Computes the option security price curve sensitivity. The future price is computed without
  * convexity adjustment.
  *
  * @param security The future option security.
  * @param sabrData The SABR data bundle.
  * @return The security price curve sensitivity.
  */
 public PresentValueSABRSensitivityDataBundle priceSABRSensitivity(
     final InterestRateFutureOptionMarginSecurity security,
     final SABRInterestRateDataBundle sabrData) {
   final PresentValueSABRSensitivityDataBundle sensi = new PresentValueSABRSensitivityDataBundle();
   // Forward sweep
   final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), sabrData);
   final double rateStrike = 1.0 - security.getStrike();
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall());
   final double forward = 1 - priceFuture;
   final double delay =
       security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime();
   final double[] volatilityAdjoint =
       sabrData
           .getSABRParameter()
           .getVolatilityAdjoint(security.getExpirationTime(), delay, rateStrike, forward);
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatilityAdjoint[0]);
   final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack);
   // Backward sweep
   final double priceBar = 1.0;
   final double volatilityBar = priceAdjoint[2] * priceBar;
   final DoublesPair expiryDelay = new DoublesPair(security.getExpirationTime(), delay);
   sensi.addAlpha(expiryDelay, volatilityAdjoint[3] * volatilityBar);
   sensi.addBeta(expiryDelay, volatilityAdjoint[4] * volatilityBar);
   sensi.addRho(expiryDelay, volatilityAdjoint[5] * volatilityBar);
   sensi.addNu(expiryDelay, volatilityAdjoint[6] * volatilityBar);
   return sensi;
 }
 /**
  * Computes the option security price curve sensitivity. The future price is computed without
  * convexity adjustment.
  *
  * @param security The future option security.
  * @param sabrData The SABR data bundle.
  * @return The security price curve sensitivity.
  */
 public InterestRateCurveSensitivity priceCurveSensitivity(
     final InterestRateFutureOptionMarginSecurity security,
     final SABRInterestRateDataBundle sabrData) {
   // Forward sweep
   final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), sabrData);
   final double rateStrike = 1.0 - security.getStrike();
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall());
   final double forward = 1 - priceFuture;
   final double delay =
       security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime();
   final double[] volatilityAdjoint =
       sabrData
           .getSABRParameter()
           .getVolatilityAdjoint(security.getExpirationTime(), delay, rateStrike, forward);
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatilityAdjoint[0]);
   final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack);
   // Backward sweep
   final double priceBar = 1.0;
   final double volatilityBar = priceAdjoint[2] * priceBar;
   final double forwardBar = priceAdjoint[1] * priceBar + volatilityAdjoint[1] * volatilityBar;
   final double priceFutureBar = -forwardBar;
   final InterestRateCurveSensitivity priceFutureDerivative =
       METHOD_FUTURE.priceCurveSensitivity(security.getUnderlyingFuture(), sabrData);
   return priceFutureDerivative.multipliedBy(priceFutureBar);
 }
 @Test
 /** Tests the present value. */
 public void presentValueNoNotional() {
   final MultipleCurrencyAmount pv = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION);
   final double timeToMaturity =
       ZERO_COUPON_CAP.getReferenceEndTime() - ZERO_COUPON_CAP.getLastKnownFixingTime();
   final double df =
       MARKET
           .getCurve(ZERO_COUPON_CAP.getCurrency())
           .getDiscountFactor(ZERO_COUPON_CAP.getPaymentTime());
   final double finalIndex =
       MARKET.getCurve(PRICE_INDEX_EUR).getPriceIndex(ZERO_COUPON_CAP.getReferenceEndTime());
   final double forward = finalIndex / INDEX_1MAY_2008;
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(
           Math.pow(1 + ZERO_COUPON_CAP.getStrike(), ZERO_COUPON_CAP.getMaturity()),
           timeToMaturity,
           ZERO_COUPON_CAP.isCap());
   final double volatility =
       BLACK_INFLATION
           .getBlackParameters()
           .getVolatility(ZERO_COUPON_CAP.getReferenceEndTime(), ZERO_COUPON_CAP.getStrike());
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility);
   final Function1D<BlackFunctionData, Double> func = BLACK_FUNCTION.getPriceFunction(option);
   final double pvExpected =
       df
           * func.evaluate(dataBlack)
           * ZERO_COUPON_CAP.getNotional()
           * ZERO_COUPON_CAP.getPaymentYearFraction();
   assertEquals(
       "Zero-coupon inflation DiscountingMethod: Present value",
       pvExpected,
       pv.getAmount(ZERO_COUPON_CAP.getCurrency()),
       TOLERANCE_PV);
 }
 public void delta() {
   final double priceFutures =
       METHOD_FUTURE.price(CALL_JB_147.getUnderlyingFuture(), ISSUER_SPECIFIC_MULTICURVES);
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(
           STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall());
   final double expiry = CALL_JB_147.getExpirationTime();
   final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, STRIKE_147);
   double df =
       ISSUER_SPECIFIC_MULTICURVES
           .getMulticurveProvider()
           .getDiscountFactor(JBM5_DEFINITION.getCurrency(), CALL_JB_147.getExpirationTime());
   final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, df, volatility);
   final double[] priceAD = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack);
   final double deltaCallExpected = priceAD[1];
   final double deltaCallComputed = METHOD_OPT.delta(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT);
   assertEquals(
       "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta",
       deltaCallExpected,
       deltaCallComputed,
       TOLERANCE_DELTA);
   final double deltaPutComputed = METHOD_OPT.delta(PUT_JB_147, BLACK_EXP_STRIKE_BNDFUT);
   assertEquals(
       "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: delta",
       deltaCallExpected - deltaPutComputed,
       df,
       TOLERANCE_DELTA);
 }
 @Test
 public void presentValue() {
   final MultipleCurrencyAmount pvMethod =
       METHOD_BLACK.presentValue(SWAPTION_LONG_REC, BLACK_MULTICURVES);
   final double forward = SWAPTION_LONG_REC.getUnderlyingSwap().accept(PRDC, MULTICURVES);
   final double pvbp =
       METHOD_SWAP.presentValueBasisPoint(SWAPTION_LONG_REC.getUnderlyingSwap(), MULTICURVES);
   final double volatility =
       BLACK.getVolatility(
           SWAPTION_LONG_REC.getTimeToExpiry(), SWAPTION_LONG_REC.getMaturityTime());
   final BlackPriceFunction blackFunction = new BlackPriceFunction();
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, pvbp, volatility);
   final Function1D<BlackFunctionData, Double> func =
       blackFunction.getPriceFunction(SWAPTION_LONG_REC);
   final double pvExpected = func.evaluate(dataBlack);
   assertEquals(
       "Swaption Black method: present value", pvExpected, pvMethod.getAmount(EUR), TOLERANCE_PV);
 }
 /**
  * Computes the option security price from future price.
  *
  * @param security The future option security.
  * @param sabrData The SABR data bundle.
  * @param priceFuture The price of the underlying future.
  * @return The security price.
  */
 public double optionPriceFromFuturePrice(
     final InterestRateFutureOptionMarginSecurity security,
     final SABRInterestRateDataBundle sabrData,
     final double priceFuture) {
   final double rateStrike = 1.0 - security.getStrike();
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall());
   final double forward = 1 - priceFuture;
   final double delay =
       security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime();
   final double volatility =
       sabrData
           .getSABRParameter()
           .getVolatility(new double[] {security.getExpirationTime(), delay, rateStrike, forward});
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility);
   final double priceSecurity = BLACK_FUNCTION.getPriceFunction(option).evaluate(dataBlack);
   return priceSecurity;
 }
 public void priceFromFuturesPrice() {
   final double price = 1.465;
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(
           STRIKE_147, CALL_JB_147.getExpirationTime(), CALL_JB_147.isCall());
   final double logmoney = Math.log(STRIKE_147 / price);
   final double expiry = CALL_JB_147.getExpirationTime();
   final double volatility = BLACK_SURFACE_EXP_STRIKE.getZValue(expiry, logmoney);
   double df =
       ISSUER_SPECIFIC_MULTICURVES
           .getMulticurveProvider()
           .getDiscountFactor(JBM5_DEFINITION.getCurrency(), expiry);
   final BlackFunctionData dataBlack = new BlackFunctionData(price, df, volatility);
   final double priceExpected = BLACK_FUNCTION.getPriceFunction(option).evaluate(dataBlack);
   final double priceComputed =
       METHOD_OPT.priceFromUnderlyingPrice(CALL_JB_147, BLACK_EXP_STRIKE_BNDFUT, price);
   assertEquals(
       "BondFuturesOptionPremiumSecurityBlackBondFuturesMethod: underlying futures price",
       priceExpected,
       priceComputed,
       TOLERANCE_RATE);
 }
 /**
  * Computes the present value of the Physical delivery swaption through approximation..
  *
  * @param swaption The swaption.
  * @param cfe The swaption cash flow equiovalent.
  * @param g2Data The G2++ parameters and the curves.
  * @return The present value.
  */
 public CurrencyAmount presentValue(
     final SwaptionPhysicalFixedIbor swaption,
     final AnnuityPaymentFixed cfe,
     final G2ppPiecewiseConstantDataBundle g2Data) {
   YieldAndDiscountCurve dsc =
       g2Data.getCurve(swaption.getUnderlyingSwap().getFixedLeg().getDiscountCurve());
   int nbCf = cfe.getNumberOfPayments();
   double[] cfa = new double[nbCf];
   double[] t = new double[nbCf];
   for (int loopcf = 0; loopcf < nbCf; loopcf++) {
     cfa[loopcf] =
         -Math.signum(cfe.getNthPayment(0).getAmount()) * cfe.getNthPayment(loopcf).getAmount();
     t[loopcf] = cfe.getNthPayment(loopcf).getPaymentTime();
   }
   double rhog2pp = g2Data.getG2ppParameter().getCorrelation();
   double[][] ht0 = MODEL_G2PP.volatilityMaturityPart(g2Data.getG2ppParameter(), t[0], t);
   double[] dfswap = new double[nbCf];
   double[] p0 = new double[nbCf];
   double[] cP = new double[nbCf];
   for (int loopcf = 0; loopcf < nbCf; loopcf++) {
     dfswap[loopcf] = dsc.getDiscountFactor(t[loopcf]);
     p0[loopcf] = dfswap[loopcf] / dfswap[0];
     cP[loopcf] = cfa[loopcf] * p0[loopcf];
   }
   double k = -cfa[0];
   double b0 = 0.0;
   for (int loopcf = 1; loopcf < nbCf; loopcf++) {
     b0 += cP[loopcf];
   }
   double[] alpha0 = new double[nbCf - 1];
   double[] beta0 = new double[2];
   for (int loopcf = 0; loopcf < nbCf - 1; loopcf++) {
     alpha0[loopcf] = cfa[loopcf + 1] * p0[loopcf + 1] / b0;
     beta0[0] += alpha0[loopcf] * ht0[0][loopcf + 1];
     beta0[1] += alpha0[loopcf] * ht0[1][loopcf + 1];
   }
   double[][] gamma = MODEL_G2PP.gamma(g2Data.getG2ppParameter(), 0, swaption.getTimeToExpiry());
   double[] tau = new double[nbCf];
   for (int loopcf = 0; loopcf < nbCf; loopcf++) {
     tau[loopcf] =
         gamma[0][0] * ht0[0][loopcf] * ht0[0][loopcf]
             + gamma[1][1] * ht0[1][loopcf] * ht0[1][loopcf]
             + 2 * rhog2pp * gamma[0][1] * ht0[0][loopcf] * ht0[1][loopcf];
   }
   double xbarnum = 0.0;
   double xbarde = 0.0;
   for (int loopcf = 0; loopcf < nbCf; loopcf++) {
     xbarnum += cP[loopcf] - cP[loopcf] * tau[loopcf] * tau[loopcf] / 2.0;
     xbarde += cP[loopcf] * tau[loopcf];
   }
   double xbar = xbarnum / xbarde;
   double[] pK = new double[nbCf];
   for (int loopcf = 0; loopcf < nbCf; loopcf++) {
     pK[loopcf] = p0[loopcf] * (1.0 - tau[loopcf] * xbar - tau[loopcf] * tau[loopcf] / 2.0);
   }
   double[] alphaK = new double[nbCf - 1];
   double[] betaK = new double[2];
   for (int loopcf = 0; loopcf < nbCf - 1; loopcf++) {
     alphaK[loopcf] = cfa[loopcf + 1] * pK[loopcf + 1] / k;
     betaK[0] += alphaK[loopcf] * ht0[0][loopcf + 1];
     betaK[1] += alphaK[loopcf] * ht0[1][loopcf + 1];
   }
   double[] betaBar = new double[] {(beta0[0] + betaK[0]) / 2.0, (beta0[1] + betaK[1]) / 2.0};
   double sigmaBar2 =
       gamma[0][0] * betaBar[0] * betaBar[0]
           + gamma[1][1] * betaBar[1] * betaBar[1]
           + 2 * rhog2pp * gamma[0][1] * betaBar[0] * betaBar[1];
   double sigmaBar = Math.sqrt(sigmaBar2);
   EuropeanVanillaOption option = new EuropeanVanillaOption(k, 1, !swaption.isCall());
   final BlackPriceFunction blackFunction = new BlackPriceFunction();
   final BlackFunctionData dataBlack = new BlackFunctionData(b0, dfswap[0], sigmaBar);
   final Function1D<BlackFunctionData, Double> func = blackFunction.getPriceFunction(option);
   final double price = func.evaluate(dataBlack) * (swaption.isLong() ? 1.0 : -1.0);
   return CurrencyAmount.of(swaption.getCurrency(), price);
 }