CapFloorIborInArrearsSmileModelCapGenericReplicationMethod { public MultipleCurrencyAmount presentValue(final CapFloorIbor cap, final MulticurveProviderInterface curves) { ArgumentChecker.notNull(cap, "The cap/floor shoud not be null"); ArgumentChecker.notNull(curves, "curves"); final Currency ccy = cap.getCurrency(); CapFloorIbor capStandard = new CapFloorIbor(cap.getCurrency(), cap.getFixingPeriodEndTime(), cap.getPaymentYearFraction(), cap.getNotional(), cap.getFixingTime(), cap.getIndex(), cap.getFixingPeriodStartTime(), cap.getFixingPeriodEndTime(), cap.getFixingAccrualFactor(), cap.getStrike(), cap.isCap()); final double forward = curves.getSimplyCompoundForwardRate(cap.getIndex(), cap.getFixingPeriodStartTime(), cap.getFixingPeriodEndTime(), cap.getFixingAccrualFactor()); final double beta = (1.0 + cap.getFixingAccrualFactor() * forward) * curves.getDiscountFactor(ccy, cap.getFixingPeriodEndTime()) / curves.getDiscountFactor(ccy, cap.getFixingPeriodStartTime()); final double df = curves.getDiscountFactor(capStandard.getCurrency(), capStandard.getPaymentTime()); final double strikePart = (1.0 + cap.getFixingAccrualFactor() * capStandard.getStrike()) * presentValueStandard(forward, capStandard.getStrike(), capStandard.getFixingTime(), capStandard.isCap(), df, capStandard.getNotional(), capStandard.getPaymentYearFraction()); final InArrearsIntegrant integrant = new InArrearsIntegrant(capStandard, curves); double integralPart; try { if (cap.isCap()) { double atmVol = _smileFunction.getVolatility(forward); double upper = forward * Math.exp(6.0 * atmVol * Math.sqrt(cap.getFixingTime())); double strike = cap.getStrike(); integralPart = INTEGRATOR.integrate(integrant, strike, upper); double reminder = integrant.evaluate(upper) * upper; double error = reminder / integralPart; int count = 0; while (Math.abs(error) > REL_ERROR && count < MAX_COUNT) { integralPart += INTEGRATOR.integrate(integrant, upper, 2.0 * upper); upper *= 2.0; reminder = integrant.evaluate(upper) * upper; error = reminder / integralPart; ++count; if (count == MAX_COUNT) { LOGGER.info("Maximum iteration count, " + MAX_COUNT + ", has been reached. Relative error is greater than " + REL_ERROR); } } } else { double strike = cap.getStrike(); integralPart = INTEGRATOR.integrate(integrant, REL_TOL * strike, strike); } } catch (final Exception e) { throw new MathException(e); } integralPart *= 2.0 * cap.getFixingAccrualFactor(); final double pv = (strikePart + integralPart) / beta; return MultipleCurrencyAmount.of(cap.getCurrency(), pv); } CapFloorIborInArrearsSmileModelCapGenericReplicationMethod(final InterpolatedSmileFunction smileFunction); MultipleCurrencyAmount presentValue(final CapFloorIbor cap, final MulticurveProviderInterface curves); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CapFloorIbor cap,
      final MulticurveProviderInterface curves);  }
@Test public void consistencyTest() { CapFloorIbor[] derivatives = new CapFloorIbor[] {CAP_LONG, CAP_SHORT, FLOOR_SHORT }; for (final CapFloorIbor derivative : derivatives) { double forward = SABR_MULTICURVES.getMulticurveProvider().getSimplyCompoundForwardRate(derivative.getIndex(), derivative.getFixingPeriodStartTime(), derivative.getFixingPeriodEndTime(), derivative.getFixingAccrualFactor()); double maturity = derivative.getFixingPeriodEndTime() - derivative.getFixingPeriodStartTime(); int nSample = 50; double[] sampleStrikes = new double[nSample]; double[] sampleVolatilities = new double[nSample]; for (int i = 0; i < nSample; ++i) { sampleStrikes[i] = forward * (i * 0.04 + 0.001); sampleVolatilities[i] = SABR_PARAMETER.getVolatility(derivative.getFixingTime(), maturity, sampleStrikes[i], forward); } CapFloorIborSABRCapExtrapolationRightMethod oldMethod = new CapFloorIborSABRCapExtrapolationRightMethod( sampleStrikes[nSample - 1], MU); CapFloorIborInArrearsSABRCapGenericReplicationMethod methodSabrExtrap = new CapFloorIborInArrearsSABRCapGenericReplicationMethod( oldMethod); MultipleCurrencyAmount res1Extrap = methodSabrExtrap.presentValue(derivative, SABR_MULTICURVES); BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( MU, MU); SmileInterpolatorSABRWithExtrapolation sabrExtrap = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap = new InterpolatedSmileFunction(sabrExtrap, forward, sampleStrikes, derivative.getFixingTime(), sampleVolatilities); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSabrGeneralExtrap = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionExtrap); MultipleCurrencyAmount res2Extrap = methodSabrGeneralExtrap.presentValue(derivative, MULTICURVES); double refExtrap = res1Extrap.getAmount(derivative.getCurrency()); assertEquals(refExtrap, res2Extrap.getAmount(derivative.getCurrency()), Math.abs(refExtrap) * 1.e-6); } double forward = SABR_MULTICURVES.getMulticurveProvider().getSimplyCompoundForwardRate(COUPON_IBOR.getIndex(), COUPON_IBOR.getFixingPeriodStartTime(), COUPON_IBOR.getFixingPeriodEndTime(), COUPON_IBOR.getFixingAccrualFactor()); double maturity = COUPON_IBOR.getFixingPeriodEndTime() - COUPON_IBOR.getFixingPeriodStartTime(); int nSample = 50; double[] sampleStrikes = new double[nSample]; double[] sampleVolatilities = new double[nSample]; for (int i = 0; i < nSample; ++i) { sampleStrikes[i] = forward * (i * 0.04 + 0.001); sampleVolatilities[i] = SABR_PARAMETER.getVolatility(COUPON_IBOR.getFixingTime(), maturity, sampleStrikes[i], forward); } CapFloorIborSABRCapExtrapolationRightMethod oldMethod = new CapFloorIborSABRCapExtrapolationRightMethod( sampleStrikes[nSample - 1], MU); CouponIborInArrearsReplicationMethod methodSabrExtrap = new CouponIborInArrearsReplicationMethod(oldMethod); MultipleCurrencyAmount res1Extrap = methodSabrExtrap.presentValue(COUPON_IBOR, SABR_MULTICURVES); BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( MU, MU); SmileInterpolatorSABRWithExtrapolation sabrExtrap = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap = new InterpolatedSmileFunction(sabrExtrap, forward, sampleStrikes, COUPON_IBOR.getFixingTime(), sampleVolatilities); CouponIborInArrearsSmileModelReplicationMethod methodSabrGeneralExtrap = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionExtrap); MultipleCurrencyAmount res2Extrap = methodSabrGeneralExtrap.presentValue(COUPON_IBOR, MULTICURVES); double refExtrap = res1Extrap.getAmount(COUPON_IBOR.getCurrency()); assertEquals(refExtrap, res2Extrap.getAmount(COUPON_IBOR.getCurrency()), Math.abs(refExtrap) * 1.e-6); }
@Test public void ComparisonTest() { CapFloorIbor[] derivatives = new CapFloorIbor[] {CAP_LONG, CAP_SHORT, FLOOR_SHORT }; for (final CapFloorIbor derivative : derivatives) { double muLow = 18.0; double muHigh = 1.217; BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( muLow, muHigh); SmileInterpolatorSABRWithExtrapolation sabrExtrap2 = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap2 = new InterpolatedSmileFunction(sabrExtrap2, FORWARD, STRIKES, derivative.getFixingTime(), VOLS); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSabrGeneralExtrap2 = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionExtrap2); MultipleCurrencyAmount res2Extrap2 = methodSabrGeneralExtrap2.presentValue(derivative, MULTICURVES); ShiftedLogNormalExtrapolationFunctionProvider providerLog = new ShiftedLogNormalExtrapolationFunctionProvider( "Quiet"); SmileInterpolatorSABRWithExtrapolation sabrExtrap2Log = new SmileInterpolatorSABRWithExtrapolation(providerLog); InterpolatedSmileFunction smileFunctionExtrap2Log = new InterpolatedSmileFunction(sabrExtrap2Log, FORWARD, STRIKES, derivative.getFixingTime(), VOLS); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSabrGeneralExtrap2Log = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionExtrap2Log); MultipleCurrencyAmount res2Extrap2Log = methodSabrGeneralExtrap2Log.presentValue(derivative, MULTICURVES); SmileInterpolatorSpline spline = new SmileInterpolatorSpline(Interpolator1DFactory.PCHIP_INSTANCE, "Quiet"); InterpolatedSmileFunction smileFunctionSpline = new InterpolatedSmileFunction(spline, FORWARD, STRIKES, derivative.getFixingTime(), VOLS); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSpline = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionSpline); MultipleCurrencyAmount resSpline = methodSpline.presentValue(derivative, MULTICURVES); double ref = res2Extrap2.getAmount(EUR); assertEquals(ref, res2Extrap2Log.getAmount(EUR), Math.abs(ref) * 1.e-3); assertEquals(ref, resSpline.getAmount(EUR), Math.abs(ref) * 1.e-3); } double muLow = 14.05; double muHigh = 1.217; BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( muLow, muHigh); SmileInterpolatorSABRWithExtrapolation sabrExtrap2 = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap2 = new InterpolatedSmileFunction(sabrExtrap2, FORWARD, STRIKES, COUPON_IBOR.getFixingTime(), VOLS); CouponIborInArrearsSmileModelReplicationMethod methodSabrGeneralExtrap2 = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionExtrap2); MultipleCurrencyAmount res2Extrap2 = methodSabrGeneralExtrap2.presentValue(COUPON_IBOR, MULTICURVES); ShiftedLogNormalExtrapolationFunctionProvider providerLog = new ShiftedLogNormalExtrapolationFunctionProvider( "Quiet"); SmileInterpolatorSABRWithExtrapolation sabrExtrap2Log = new SmileInterpolatorSABRWithExtrapolation(providerLog); InterpolatedSmileFunction smileFunctionExtrap2Log = new InterpolatedSmileFunction(sabrExtrap2Log, FORWARD, STRIKES, COUPON_IBOR.getFixingTime(), VOLS); CouponIborInArrearsSmileModelReplicationMethod methodSabrGeneralExtrap2Log = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionExtrap2Log); MultipleCurrencyAmount res2Extrap2Log = methodSabrGeneralExtrap2Log.presentValue(COUPON_IBOR, MULTICURVES); SmileInterpolatorSpline spline = new SmileInterpolatorSpline(Interpolator1DFactory.PCHIP_INSTANCE, "Quiet"); InterpolatedSmileFunction smileFunctionSpline = new InterpolatedSmileFunction(spline, FORWARD, STRIKES, COUPON_IBOR.getFixingTime(), VOLS); CouponIborInArrearsSmileModelReplicationMethod methodSpline = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionSpline); MultipleCurrencyAmount resSpline = methodSpline.presentValue(COUPON_IBOR, MULTICURVES); double ref = res2Extrap2.getAmount(EUR); assertEquals(ref, res2Extrap2Log.getAmount(EUR), Math.abs(ref) * 1.e-2); assertEquals(ref, resSpline.getAmount(EUR), Math.abs(ref) * 1.e-2); }
@Test public void persentValueSABRExtrapolationParity() { double[] musCap = muCalculator(STRIKES, VOLS, FORWARD, CAP_LONG.getFixingTime()); SmileExtrapolationFunctionSABRProvider provider1 = new BenaimDodgsonKainthExtrapolationFunctionProvider(musCap[0], musCap[1]); double[] musIbor = muCalculator(STRIKES, VOLS, FORWARD, COUPON_IBOR.getFixingTime()); SmileExtrapolationFunctionSABRProvider provider2 = new BenaimDodgsonKainthExtrapolationFunctionProvider(musIbor[0], musIbor[1]); SmileExtrapolationFunctionSABRProvider provider = new ShiftedLogNormalExtrapolationFunctionProvider("Quiet"); SmileExtrapolationFunctionSABRProvider[] providers1 = new SmileExtrapolationFunctionSABRProvider[] {provider1, provider }; SmileExtrapolationFunctionSABRProvider[] providers2 = new SmileExtrapolationFunctionSABRProvider[] {provider2, provider }; for (int i = 0; i < 2; ++i) { SmileInterpolatorSABRWithExtrapolation sabrExtrap = new SmileInterpolatorSABRWithExtrapolation(providers1[i]); InterpolatedSmileFunction smileFunctionExtrap = new InterpolatedSmileFunction(sabrExtrap, FORWARD, STRIKES, CAP_LONG.getFixingTime(), VOLS); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSabrGeneralExtrap = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionExtrap); MultipleCurrencyAmount priceCapLong = methodSabrGeneralExtrap.presentValue(CAP_LONG, MULTICURVES); MultipleCurrencyAmount priceCapShort = methodSabrGeneralExtrap.presentValue(CAP_SHORT, MULTICURVES); assertEquals(priceCapLong.getAmount(EUR), -priceCapShort.getAmount(EUR), Math.abs(priceCapLong.getAmount(EUR)) * 1.0e-10); SmileInterpolatorSABRWithExtrapolation sabrExtrap2 = new SmileInterpolatorSABRWithExtrapolation(providers2[i]); InterpolatedSmileFunction smileFunctionExtrap2 = new InterpolatedSmileFunction(sabrExtrap2, FORWARD, STRIKES, COUPON_IBOR.getFixingTime(), VOLS); CouponIborInArrearsSmileModelReplicationMethod methodSabrGeneralExtrap2 = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionExtrap2); MultipleCurrencyAmount priceIbor = methodSabrGeneralExtrap2.presentValue(COUPON_IBOR, MULTICURVES); final CapFloorIborDefinition cap0Definition = new CapFloorIborDefinition(EUR, END_ACCRUAL_DATE, START_ACCRUAL_DATE, END_ACCRUAL_DATE, ACCRUAL_FACTOR, NOTIONAL, FIXING_DATE, EURIBOR6M, 0.0, IS_CAP, CALENDAR); final CapFloorIbor cap0 = (CapFloorIbor) cap0Definition.toDerivative(REFERENCE_DATE); final MultipleCurrencyAmount priceCap0 = methodSabrGeneralExtrap.presentValue(cap0, MULTICURVES); assertEquals(priceCap0.getAmount(EUR), priceIbor.getAmount(EUR), Math.abs(priceCap0.getAmount(EUR)) * 1.0e-10); } }
@Test public void muDependenceTest() { double[] mu = new double[] {25.0, 18.0, 5.0, 1.5 }; int nMu = mu.length; CapFloorIbor[] derivatives = new CapFloorIbor[] {CAP_LONG, CAP_SHORT, FLOOR_SHORT }; for (final CapFloorIbor derivative : derivatives) { double prev = 0.0; double pres = 0.0; for (int i = 0; i < nMu; ++i) { BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( mu[i], mu[i]); SmileInterpolatorSABRWithExtrapolation sabrExtrap2 = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap2 = new InterpolatedSmileFunction(sabrExtrap2, FORWARD, STRIKES, derivative.getFixingTime(), VOLS); CapFloorIborInArrearsSmileModelCapGenericReplicationMethod methodSabrGeneralExtrap2 = new CapFloorIborInArrearsSmileModelCapGenericReplicationMethod( smileFunctionExtrap2); MultipleCurrencyAmount res2Extrap2 = methodSabrGeneralExtrap2.presentValue(derivative, MULTICURVES); pres = Math.abs(res2Extrap2.getAmount(EUR)); assertTrue(pres > prev); prev = pres; } } double prev = 0.0; double pres = 0.0; for (int i = 0; i < nMu; ++i) { BenaimDodgsonKainthExtrapolationFunctionProvider provider = new BenaimDodgsonKainthExtrapolationFunctionProvider( mu[i], mu[i]); SmileInterpolatorSABRWithExtrapolation sabrExtrap2 = new SmileInterpolatorSABRWithExtrapolation(provider); InterpolatedSmileFunction smileFunctionExtrap2 = new InterpolatedSmileFunction(sabrExtrap2, FORWARD, STRIKES, COUPON_IBOR.getFixingTime(), VOLS); CouponIborInArrearsSmileModelReplicationMethod methodSabrGeneralExtrap2 = new CouponIborInArrearsSmileModelReplicationMethod( smileFunctionExtrap2); MultipleCurrencyAmount res2Extrap2 = methodSabrGeneralExtrap2.presentValue(COUPON_IBOR, MULTICURVES); pres = Math.abs(res2Extrap2.getAmount(EUR)); assertTrue(pres > prev); prev = pres; } }