//------------------------------------------------------------------------- public virtual void test_presentValue_formula() { CurrencyAmount computedCaplet = PRICER.presentValue(CAPLET_LONG, RATES, VOLS); CurrencyAmount computedFloorlet = PRICER.presentValue(FLOORLET_SHORT, RATES, VOLS); double forward = RATES.iborIndexRates(EUR_EURIBOR_3M).rate(RATE_COMP.Observation); double expiry = VOLS.relativeTime(CAPLET_LONG.FixingDateTime); double volatility = VOLS.volatility(expiry, STRIKE, forward); double df = RATES.discountFactor(EUR, CAPLET_LONG.PaymentDate); double expectedCaplet = NOTIONAL * df * CAPLET_LONG.YearFraction * BlackFormulaRepository.price(forward + SHIFT, STRIKE + SHIFT, expiry, volatility, CALL.Call); double expectedFloorlet = -NOTIONAL *df *FLOORLET_SHORT.YearFraction *BlackFormulaRepository.price(forward + SHIFT, STRIKE + SHIFT, expiry, volatility, PUT.Call); assertEquals(computedCaplet.Currency, EUR); assertEquals(computedCaplet.Amount, expectedCaplet, NOTIONAL * TOL); assertEquals(computedFloorlet.Currency, EUR); assertEquals(computedFloorlet.Amount, expectedFloorlet, NOTIONAL * TOL); // consistency with shifted Black ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities vols = ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of(EUR_EURIBOR_3M, VALUATION, ConstantSurface.of("constVol", volatility).withMetadata(Surfaces.blackVolatilityByExpiryStrike("costVol", DayCounts.ACT_ACT_ISDA)), IborCapletFloorletSabrRateVolatilityDataSet.CURVE_CONST_SHIFT); CurrencyAmount computedCapletBlack = PRICER_BASE.presentValue(CAPLET_LONG, RATES, vols); CurrencyAmount computedFloorletBlack = PRICER_BASE.presentValue(FLOORLET_SHORT, RATES, vols); assertEquals(computedCaplet.Amount, computedCapletBlack.Amount, NOTIONAL * TOL); assertEquals(computedFloorlet.Amount, computedFloorletBlack.Amount, NOTIONAL * TOL); }
//------------------------------------------------------------------------- public virtual void test_presentValueSensitivity() { PointSensitivityBuilder pointCaplet = PRICER.presentValueSensitivityRates(CAPLET_LONG, RATES, VOLS); CurrencyParameterSensitivities computedCaplet = RATES.parameterSensitivity(pointCaplet.build()); PointSensitivityBuilder pointFloorlet = PRICER.presentValueSensitivityRates(FLOORLET_SHORT, RATES, VOLS); CurrencyParameterSensitivities computedFloorlet = RATES.parameterSensitivity(pointFloorlet.build()); CurrencyParameterSensitivities expectedCaplet = FD_CAL.sensitivity(RATES, p => PRICER_BASE.presentValue(CAPLET_LONG, p, VOLS)); CurrencyParameterSensitivities expectedFloorlet = FD_CAL.sensitivity(RATES, p => PRICER_BASE.presentValue(FLOORLET_SHORT, p, VOLS)); assertTrue(computedCaplet.equalWithTolerance(expectedCaplet, EPS_FD * NOTIONAL * 50d)); assertTrue(computedFloorlet.equalWithTolerance(expectedFloorlet, EPS_FD * NOTIONAL * 50d)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the Ibor cap/floor leg. /// <para> /// The present value of the leg is the value on the valuation date. /// The result is returned using the payment currency of the leg. /// /// </para> /// </summary> /// <param name="capFloorLeg"> the Ibor cap/floor leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value </returns> public virtual CurrencyAmount presentValue(ResolvedIborCapFloorLeg capFloorLeg, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(ratesProvider, volatilities); return(capFloorLeg.CapletFloorletPeriods.Select(period => periodPricer.presentValue(period, ratesProvider, volatilities)).Aggregate((c1, c2) => c1.plus(c2)).get()); }
// sum of caplet prices which are already fixed private double priceFixed(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry) { VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer; return(cap.CapletFloorletPeriods.Where(p => !p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, vols).Amount).Sum()); }
//------------------------------------------------------------------------- // price and vega function private System.Func <double, double[]> getValueVegaFunction(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry, int nodeIndex) { VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer; System.Func <double, double[]> priceAndVegaFunction = (double?x) => { IborCapletFloorletVolatilities newVols = vols.withParameter(nodeIndex, x.Value); double price = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, newVols).Amount).Sum(); PointSensitivities point = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValueSensitivityModelParamsVolatility(p, ratesProvider, newVols)).Aggregate((c1, c2) => c1.combinedWith(c2)).get().build(); CurrencyParameterSensitivities sensi = newVols.parameterSensitivity(point); double vega = sensi.Sensitivities.get(0).Sensitivity.get(nodeIndex); return(new double[] { price, vega }); }; return(priceAndVegaFunction); }