public virtual void recovery_test_normal2_shift() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC, ConstantCurve.of("Black shift", 0.02)); DoubleArray strikes = createNormalEquivStrikes(); RawOptionData data = RawOptionData.of(createNormalEquivMaturities(), strikes, ValueType.STRIKE, createFullNormalEquivDataMatrix(), ValueType.NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities resVol = (ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalEquivVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } assertEquals(res.ChiSquare, 0d); }
public virtual void recovery_test_blackSurface() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, LINEAR); DoubleArray strikes = createBlackStrikes(); RawOptionData data = RawOptionData.of(createBlackMaturities(), strikes, ValueType.STRIKE, createFullBlackDataMatrix(), ValueType.BLACK_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); BlackIborCapletFloorletExpiryStrikeVolatilities resVol = (BlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsBlackVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.blackVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); BlackIborCapletFloorletExpiryStrikeVolatilities constVol = BlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } assertEquals(res.ChiSquare, 0d); assertEquals(resVol.Index, USD_LIBOR_3M); assertEquals(resVol.Name, definition.Name); assertEquals(resVol.ValuationDateTime, CALIBRATION_TIME); InterpolatedNodalSurface surface = (InterpolatedNodalSurface)resVol.Surface; for (int i = 0; i < surface.ParameterCount; ++i) { GenericVolatilitySurfacePeriodParameterMetadata metadata = (GenericVolatilitySurfacePeriodParameterMetadata)surface.getParameterMetadata(i); assertEquals(metadata.Strike.Value, surface.YValues.get(i)); } }
public virtual void recovery_test_blackCurve() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, LINEAR); DoubleArray strikes = createBlackStrikes(); for (int i = 0; i < strikes.size(); ++i) { Pair <IList <Period>, DoubleMatrix> trimedData = trimData(createBlackMaturities(), createBlackDataMatrixForStrike(i)); RawOptionData data = RawOptionData.of(trimedData.First, DoubleArray.of(strikes.get(i)), ValueType.STRIKE, trimedData.Second, ValueType.BLACK_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); BlackIborCapletFloorletExpiryStrikeVolatilities resVol = (BlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsBlackVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.blackVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); BlackIborCapletFloorletExpiryStrikeVolatilities constVol = BlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } }
public virtual void test_invalid_data() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, LINEAR); DoubleArray strikes = createBlackStrikes(); RawOptionData data = RawOptionData.of(createBlackMaturities(), strikes, ValueType.STRIKE, createFullBlackDataMatrixInvalid(), ValueType.BLACK_VOLATILITY); assertThrowsIllegalArg(() => CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER)); }
//------------------------------------------------------------------------- public virtual void coverage() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test1 = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); coverImmutableBean(test1); SurfaceIborCapletFloorletVolatilityBootstrapDefinition test2 = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("other"), GBP_LIBOR_3M, ACT_365F, LINEAR, LINEAR, SHIFT); coverBeanEquals(test1, test2); }
public virtual void test_of_shift() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, STEP_UPPER, DOUBLE_QUADRATIC, SHIFT); assertEquals(test.DayCount, ACT_ACT_ISDA); assertEquals(test.Index, USD_LIBOR_3M); assertEquals(test.Interpolator, GridSurfaceInterpolator.of(STEP_UPPER, DOUBLE_QUADRATIC)); assertEquals(test.Name, NAME); assertEquals(test.ShiftCurve.get(), SHIFT); }
public virtual void test_of_surface() { GridSurfaceInterpolator interp = GridSurfaceInterpolator.of(LINEAR, LINEAR); SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, interp); assertEquals(test.DayCount, ACT_ACT_ISDA); assertEquals(test.Index, USD_LIBOR_3M); assertEquals(test.Interpolator, interp); assertEquals(test.Name, NAME); assertFalse(test.ShiftCurve.Present); }
public virtual void test_createMetadata_wrongValueType() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition @base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of(ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] { new double[] { 0.15, 0.12, 0.13 }, new double[] { 0.1, 0.08, 0.09 } }), ValueType.PRICE); assertThrowsIllegalArg(() => @base.createMetadata(capData)); }
public virtual void test_createCap() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition @base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, TIME_SQUARE, DOUBLE_QUADRATIC); LocalDate startDate = LocalDate.of(2012, 4, 20); LocalDate endDate = LocalDate.of(2017, 4, 20); double strike = 0.01; IborCapFloorLeg expected = IborCapFloorLeg.builder().calculation(IborRateCalculation.of(USD_LIBOR_3M)).capSchedule(ValueSchedule.of(strike)).currency(USD_LIBOR_3M.Currency).notional(ValueSchedule.ALWAYS_1).paymentDateOffset(DaysAdjustment.NONE).paymentSchedule(PeriodicSchedule.of(startDate, endDate, Frequency.of(USD_LIBOR_3M.Tenor.Period), BusinessDayAdjustment.of(BusinessDayConventions.MODIFIED_FOLLOWING, USD_LIBOR_3M.FixingCalendar), StubConvention.NONE, RollConventions.NONE)).payReceive(PayReceive.RECEIVE).build(); IborCapFloorLeg computed = @base.createCap(startDate, endDate, strike); assertEquals(computed, expected); }
//----------------------------------------------------------------------- public override bool Equals(object obj) { if (obj == this) { return(true); } if (obj != null && obj.GetType() == this.GetType()) { SurfaceIborCapletFloorletVolatilityBootstrapDefinition other = (SurfaceIborCapletFloorletVolatilityBootstrapDefinition)obj; return(JodaBeanUtils.equal(name, other.name) && JodaBeanUtils.equal(index, other.index) && JodaBeanUtils.equal(dayCount, other.dayCount) && JodaBeanUtils.equal(interpolator, other.interpolator) && JodaBeanUtils.equal(shiftCurve, other.shiftCurve)); } return(false); }
public virtual void test_createMetadata_normal() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition @base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of(ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] { new double[] { 0.15, 0.12, 0.13 }, new double[] { 0.1, Double.NaN, 0.09 } }), ValueType.NORMAL_VOLATILITY); IList <GenericVolatilitySurfacePeriodParameterMetadata> list = new List <GenericVolatilitySurfacePeriodParameterMetadata>(); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.005))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.01))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.015))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.005))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.015))); SurfaceMetadata expected = Surfaces.normalVolatilityByExpiryStrike(NAME.Name, ACT_ACT_ISDA).withParameterMetadata(list); SurfaceMetadata computed = @base.createMetadata(capData); assertEquals(computed, expected); }
public virtual void test_serialization() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); assertSerialization(test); }
//------------------------------------------------------------------------- public virtual void test_of_wrongInterpolator() { assertThrowsIllegalArg(() => SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, DOUBLE_QUADRATIC, DOUBLE_QUADRATIC)); }
//------------------------------------------------------------------------- public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider) { ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime"); ArgChecker.isTrue(definition is SurfaceIborCapletFloorletVolatilityBootstrapDefinition, "definition should be SurfaceIborCapletFloorletVolatilityBootstrapDefinition"); SurfaceIborCapletFloorletVolatilityBootstrapDefinition bsDefinition = (SurfaceIborCapletFloorletVolatilityBootstrapDefinition)definition; IborIndex index = bsDefinition.Index; LocalDate calibrationDate = calibrationDateTime.toLocalDate(); LocalDate baseDate = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData); LocalDate startDate = baseDate.plus(index.Tenor); System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(bsDefinition, calibrationDateTime, capFloorData); SurfaceMetadata metadata = bsDefinition.createMetadata(capFloorData); IList <Period> expiries = capFloorData.Expiries; int nExpiries = expiries.Count; DoubleArray strikes = capFloorData.Strikes; DoubleMatrix errorsMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d)); IList <double> timeList = new List <double>(); IList <double> strikeList = new List <double>(); IList <double> volList = new List <double>(); IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>(); IList <double> priceList = new List <double>(); IList <double> errorList = new List <double>(); int[] startIndex = new int[nExpiries + 1]; for (int i = 0; i < nExpiries; ++i) { LocalDate endDate = baseDate.plus(expiries[i]); DoubleArray volatilityData = capFloorData.Data.row(i); DoubleArray errors = errorsMatrix.row(i); reduceRawData(bsDefinition, ratesProvider, strikes, volatilityData, errors, startDate, endDate, metadata, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList); startIndex[i + 1] = volList.Count; ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]); } int nTotal = startIndex[nExpiries]; IborCapletFloorletVolatilities vols; int start; ZonedDateTime prevExpiry; DoubleArray initialVol = DoubleArray.copyOf(volList); if (bsDefinition.ShiftCurve.Present) { Curve shiftCurve = bsDefinition.ShiftCurve.get(); DoubleArray strikeShifted = DoubleArray.of(nTotal, n => strikeList[n] + shiftCurve.yValue(timeList[n])); if (capFloorData.DataType.Equals(NORMAL_VOLATILITY)) { // correct initial surface metadata = Surfaces.blackVolatilityByExpiryStrike(bsDefinition.Name.Name, bsDefinition.DayCount).withParameterMetadata(metadata.ParameterMetadata.get()); initialVol = DoubleArray.of(nTotal, n => volList[n] / (ratesProvider.iborIndexRates(index).rate(capList[n].FinalPeriod.IborRate.Observation) + shiftCurve.yValue(timeList[n]))); } InterpolatedNodalSurface surface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), strikeShifted, initialVol, bsDefinition.Interpolator); vols = ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of(index, calibrationDateTime, surface, bsDefinition.ShiftCurve.get()); start = 0; prevExpiry = calibrationDateTime.minusDays(1L); // included if calibrationDateTime == fixingDateTime } else { InterpolatedNodalSurface surface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), DoubleArray.copyOf(strikeList), initialVol, bsDefinition.Interpolator); vols = volatilitiesFunction(surface); start = 1; prevExpiry = capList[startIndex[1] - 1].FinalFixingDateTime; } for (int i = start; i < nExpiries; ++i) { for (int j = startIndex[i]; j < startIndex[i + 1]; ++j) { System.Func <double, double[]> func = getValueVegaFunction(capList[j], ratesProvider, vols, prevExpiry, j); GenericImpliedVolatiltySolver solver = new GenericImpliedVolatiltySolver(func); double priceFixed = i == 0 ? 0d : this.priceFixed(capList[j], ratesProvider, vols, prevExpiry); double capletVol = solver.impliedVolatility(priceList[j] - priceFixed, initialVol.get(j)); vols = vols.withParameter(j, capletVol); } prevExpiry = capList[startIndex[i + 1] - 1].FinalFixingDateTime; } return(IborCapletFloorletVolatilityCalibrationResult.ofRootFind(vols)); }