CapFloorIborHullWhiteMethod { public MultipleCurrencyAmount presentValue(final CapFloorIbor cap, final HullWhiteOneFactorProviderInterface hullWhite) { ArgumentChecker.notNull(cap, "The cap/floor shoud not be null"); ArgumentChecker.notNull(hullWhite, "The Hull-White data shoud not be null"); final Currency ccy = cap.getCurrency(); final HullWhiteOneFactorPiecewiseConstantParameters parameters = hullWhite.getHullWhiteParameters(); final MulticurveProviderInterface multicurves = hullWhite.getMulticurveProvider(); final double tp = cap.getPaymentTime(); final double t0 = cap.getFixingPeriodStartTime(); final double t1 = cap.getFixingPeriodEndTime(); final double deltaF = cap.getFixingAccrualFactor(); final double deltaP = cap.getPaymentYearFraction(); final double k = cap.getStrike(); final double dfPay = multicurves.getDiscountFactor(ccy, tp); final double forward = multicurves.getSimplyCompoundForwardRate(cap.getIndex(), t0, t1, deltaF); final double alpha0 = _model.alpha(parameters, 0.0, cap.getFixingTime(), tp, t0); final double alpha1 = _model.alpha(parameters, 0.0, cap.getFixingTime(), tp, t1); final double kappa = (Math.log((1 + deltaF * k) / (1.0 + deltaF * forward)) - (alpha1 * alpha1 - alpha0 * alpha0) / 2.0) / (alpha1 - alpha0); final double omega = (cap.isCap() ? 1.0 : -1.0); double pv = deltaP / deltaF * dfPay * omega * ((1.0 + deltaF * forward) * NORMAL.getCDF(omega * (-kappa - alpha0)) - (1.0 + deltaF * k) * NORMAL.getCDF(omega * (-kappa - alpha1))); pv *= cap.getNotional(); return MultipleCurrencyAmount.of(ccy, pv); } private  CapFloorIborHullWhiteMethod(); static CapFloorIborHullWhiteMethod getInstance(); MultipleCurrencyAmount presentValue(final CapFloorIbor cap, final HullWhiteOneFactorProviderInterface hullWhite); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CapFloorIbor cap, final HullWhiteOneFactorProviderInterface hullWhite); double[] presentValueHullWhiteSensitivity(final CapFloorIbor cap, final HullWhiteOneFactorProviderInterface hullWhite);  }
@Test public void presentValueStandard() { final double tp = CAP_LONG.getPaymentTime(); final double t0 = CAP_LONG.getFixingPeriodStartTime(); final double t1 = CAP_LONG.getFixingPeriodEndTime(); final double theta = CAP_LONG.getFixingTime(); final double deltaF = CAP_LONG.getFixingAccrualFactor(); final double deltaP = CAP_LONG.getPaymentYearFraction(); final double alpha0 = MODEL.alpha(HW_PARAMETERS, 0.0, theta, tp, t0); final double alpha1 = MODEL.alpha(HW_PARAMETERS, 0.0, theta, tp, t1); final double ptp = MULTICURVES.getDiscountFactor(EUR, tp); final double forward = MULTICURVES.getSimplyCompoundForwardRate(EURIBOR3M, t0, t1, CAP_LONG.getFixingAccrualFactor()); double kappa = Math.log((1.0 + deltaF * STRIKE) / (1.0 + deltaF * forward)); kappa += -(alpha1 * alpha1 - alpha0 * alpha0) / 2.0; kappa /= alpha1 - alpha0; final ProbabilityDistribution<Double> normal = new NormalDistribution(0, 1); double priceExpected = (1.0 + deltaF * forward) * normal.getCDF(-kappa - alpha0) - (1.0 + deltaF * STRIKE) * normal.getCDF(-kappa - alpha1); priceExpected *= deltaP / deltaF * ptp; priceExpected *= NOTIONAL; final MultipleCurrencyAmount priceMethod = METHOD_HW.presentValue(CAP_LONG, HW_MULTICURVES); assertEquals("Cap/floor: Hull-White pricing", priceExpected, priceMethod.getAmount(EUR), TOLERANCE_PV); }
@Test public void presentValueLongShort() { final MultipleCurrencyAmount priceLong = METHOD_HW.presentValue(CAP_LONG, HW_MULTICURVES); final MultipleCurrencyAmount priceShort = METHOD_HW.presentValue(CAP_SHORT, HW_MULTICURVES); assertEquals("Cap/floor: Hull-White pricing", priceLong.getAmount(EUR), -priceShort.getAmount(EUR), TOLERANCE_PV); }
@Test(enabled = true) public void monteCarlo() { HullWhiteMonteCarloMethod methodMC; methodMC = new HullWhiteMonteCarloMethod(new NormalRandomNumberGenerator(0.0, 1.0, new MersenneTwister()), 10 * NB_PATH); final MultipleCurrencyAmount pvExplicit = METHOD_HW.presentValue(CAP_LONG, HW_MULTICURVES); final MultipleCurrencyAmount pvMC = methodMC.presentValue(CAP_LONG, EUR, HW_MULTICURVES); assertEquals("Cap/floor - Hull-White - Monte Carlo", pvExplicit.getAmount(EUR), pvMC.getAmount(EUR), 5.0E+2); final double pvMCPreviousRun = 136707.032; assertEquals("Swaption physical - Hull-White - Monte Carlo", pvMCPreviousRun, pvMC.getAmount(EUR), TOLERANCE_PV); methodMC = new HullWhiteMonteCarloMethod(new NormalRandomNumberGenerator(0.0, 1.0, new MersenneTwister()), 10 * NB_PATH); final MultipleCurrencyAmount pvShortMC = methodMC.presentValue(CAP_SHORT, EUR, HW_MULTICURVES); assertEquals("Swaption physical - Hull-White - Monte Carlo", -pvMC.getAmount(EUR), pvShortMC.getAmount(EUR), TOLERANCE_PV); }
@Test(enabled = false) public void performance() { long startTime, endTime; final MultipleCurrencyAmount pvExplicit = METHOD_HW.presentValue(CAP_LONG, HW_MULTICURVES); HullWhiteMonteCarloMethod methodMC; final int nbPath = 1000000; methodMC = new HullWhiteMonteCarloMethod(new NormalRandomNumberGenerator(0.0, 1.0, new MersenneTwister()), nbPath); final int nbTest = 10; final double[] pv = new double[nbTest]; final double[] pvDiff = new double[nbTest]; startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { pv[looptest] = methodMC.presentValue(CAP_LONG, EUR, HW_MULTICURVES).getAmount(EUR); pvDiff[looptest] = pv[looptest] - pvExplicit.getAmount(EUR); } endTime = System.currentTimeMillis(); System.out.println(nbTest + " pv cap/floor Hull-White MC method (" + nbPath + " paths): " + (endTime - startTime) + " ms. Error: " + pvDiff[0]); }