public virtual void recovery_test_shiftedBlack() { double lambdaT = 0.07; double lambdaK = 0.07; double error = 1.0e-5; ConstantCurve shiftCurve = ConstantCurve.of("Black shift", 0.02); DirectIborCapletFloorletVolatilityDefinition definition = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, lambdaT, lambdaK, INTERPOLATOR, shiftCurve); ImmutableList <Period> maturities = createBlackMaturities(); DoubleArray strikes = createBlackStrikes(); DoubleMatrix errorMatrix = DoubleMatrix.filled(maturities.size(), strikes.size(), error); RawOptionData data = RawOptionData.of(maturities, strikes, STRIKE, createFullBlackDataMatrix(), errorMatrix, BLACK_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities resVols = (ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < NUM_BLACK_STRIKES; ++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, resVols).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } assertTrue(res.ChiSquare > 0d); assertEquals(resVols.Index, USD_LIBOR_3M); assertEquals(resVols.Name, definition.Name); assertEquals(resVols.ValuationDateTime, CALIBRATION_TIME); assertEquals(resVols.ShiftCurve, definition.ShiftCurve.get()); }
public virtual void recovery_test_normal() { double lambdaT = 0.07; double lambdaK = 0.07; double error = 1.0e-5; DirectIborCapletFloorletVolatilityDefinition definition = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, lambdaT, lambdaK, INTERPOLATOR); ImmutableList <Period> maturities = createNormalMaturities(); DoubleArray strikes = createNormalStrikes(); DoubleMatrix errorMatrix = DoubleMatrix.filled(maturities.size(), strikes.size(), error); RawOptionData data = RawOptionData.of(maturities, strikes, STRIKE, createFullNormalDataMatrix(), errorMatrix, NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); NormalIborCapletFloorletExpiryStrikeVolatilities resVol = (NormalIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalVols(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_NORMAL.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } }
public virtual void test_createMetadata() { DirectIborCapletFloorletVolatilityDefinition @base = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR); assertEquals(@base.createMetadata(SAMPLE_BLACK), Surfaces.blackVolatilityByExpiryStrike(NAME.Name, ACT_ACT_ISDA)); assertEquals(@base.createMetadata(SAMPLE_NORMAL), Surfaces.normalVolatilityByExpiryStrike(NAME.Name, ACT_ACT_ISDA)); assertThrowsIllegalArg(() => @base.createMetadata(RawOptionData.of(EXPIRIES, STRIKES, STRIKE, DATA, ValueType.PRICE))); }
//------------------------------------------------------------------------- public virtual void coverage() { DirectIborCapletFloorletVolatilityDefinition test1 = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR, SHIFT_CURVE); coverImmutableBean(test1); DirectIborCapletFloorletVolatilityDefinition test2 = DirectIborCapletFloorletVolatilityDefinition.of(IborCapletFloorletVolatilitiesName.of("other"), GBP_LIBOR_3M, ACT_365F, 0.01, 0.02, GridSurfaceInterpolator.of(CurveInterpolators.LINEAR, CurveInterpolators.LINEAR)); coverBeanEquals(test1, test2); }
public virtual void test_builder() { DirectIborCapletFloorletVolatilityDefinition test = DirectIborCapletFloorletVolatilityDefinition.builder().name(NAME).index(USD_LIBOR_3M).dayCount(ACT_ACT_ISDA).lambdaExpiry(LAMBDA_EXPIRY).lambdaStrike(LAMBDA_STRIKE).interpolator(INTERPOLATOR).shiftCurve(SHIFT_CURVE).build(); assertEquals(test.DayCount, ACT_ACT_ISDA); assertEquals(test.Index, USD_LIBOR_3M); assertEquals(test.Interpolator, INTERPOLATOR); assertEquals(test.LambdaExpiry, LAMBDA_EXPIRY); assertEquals(test.LambdaStrike, LAMBDA_STRIKE); assertEquals(test.Name, NAME); assertEquals(test.ShiftCurve.get(), SHIFT_CURVE); }
public virtual void test_of_shift() { DirectIborCapletFloorletVolatilityDefinition test = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR, SHIFT_CURVE); assertEquals(test.DayCount, ACT_ACT_ISDA); assertEquals(test.Index, USD_LIBOR_3M); assertEquals(test.Interpolator, INTERPOLATOR); assertEquals(test.LambdaExpiry, LAMBDA_EXPIRY); assertEquals(test.LambdaStrike, LAMBDA_STRIKE); assertEquals(test.Name, NAME); assertEquals(test.ShiftCurve.get(), SHIFT_CURVE); }
public override bool Equals(object obj) { if (obj == this) { return(true); } if (obj != null && obj.GetType() == this.GetType()) { DirectIborCapletFloorletVolatilityDefinition other = (DirectIborCapletFloorletVolatilityDefinition)obj; return(JodaBeanUtils.equal(name, other.name) && JodaBeanUtils.equal(index, other.index) && JodaBeanUtils.equal(dayCount, other.dayCount) && JodaBeanUtils.equal(lambdaExpiry, other.lambdaExpiry) && JodaBeanUtils.equal(lambdaStrike, other.lambdaStrike) && JodaBeanUtils.equal(interpolator, other.interpolator) && JodaBeanUtils.equal(shiftCurve, other.shiftCurve)); } return(false); }
public virtual void test_computePenaltyMatrix() { DirectIborCapletFloorletVolatilityDefinition @base = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR); DoubleArray strikes1 = DoubleArray.of(0.1); DoubleArray expiries1 = DoubleArray.of(1d, 2d, 5d); assertThrowsIllegalArg(() => @base.computePenaltyMatrix(strikes1, expiries1)); DoubleArray strikes2 = DoubleArray.of(0.01, 0.05, 0.1); DoubleArray expiries2 = DoubleArray.of(2d); assertThrowsIllegalArg(() => @base.computePenaltyMatrix(strikes2, expiries2)); DoubleArray strikes3 = DoubleArray.of(0.05, 0.1, 0.15); DoubleArray expiries3 = DoubleArray.of(1d, 2d, 5d); DoubleMatrix computed = @base.computePenaltyMatrix(strikes3, expiries3); DoubleMatrix expected = PenaltyMatrixGenerator.getPenaltyMatrix(new double[][] { expiries3.toArray(), strikes3.toArray() }, new int[] { 2, 2 }, new double[] { LAMBDA_EXPIRY, LAMBDA_STRIKE }); assertEquals(computed, expected); }
public virtual void recovery_test_normalFlat() { double lambdaT = 0.01; double lambdaK = 0.01; double error = 1.0e-3; DirectIborCapletFloorletVolatilityDefinition definition = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, lambdaT, lambdaK, INTERPOLATOR); ImmutableList <Period> maturities = createBlackMaturities(); DoubleArray strikes = createBlackStrikes(); DoubleMatrix errorMatrix = DoubleMatrix.filled(maturities.size(), strikes.size(), error); RawOptionData data = RawOptionData.of(maturities, strikes, STRIKE, createFullFlatBlackDataMatrix(), errorMatrix, NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); NormalIborCapletFloorletExpiryStrikeVolatilities resVol = (NormalIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; Surface resSurface = resVol.Surface; int nParams = resSurface.ParameterCount; for (int i = 0; i < nParams; ++i) { assertEquals(resSurface.getParameter(i), 0.5, 1.0e-12); } }
public virtual void test_serialization() { DirectIborCapletFloorletVolatilityDefinition test = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR, SHIFT_CURVE); assertSerialization(test); }
//------------------------------------------------------------------------- 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 DirectIborCapletFloorletVolatilityDefinition, "definition should be DirectIborCapletFloorletVolatilityDefinition"); DirectIborCapletFloorletVolatilityDefinition directDefinition = (DirectIborCapletFloorletVolatilityDefinition)definition; // unpack cap data, create node caps IborIndex index = directDefinition.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(directDefinition, calibrationDateTime, capFloorData); SurfaceMetadata metadata = directDefinition.createMetadata(capFloorData); IList <Period> expiries = capFloorData.Expiries; DoubleArray strikes = capFloorData.Strikes; int nExpiries = expiries.Count; 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>(); DoubleMatrix errorMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d)); int[] startIndex = new int[nExpiries + 1]; for (int i = 0; i < nExpiries; ++i) { LocalDate endDate = baseDate.plus(expiries[i]); DoubleArray volatilityForTime = capFloorData.Data.row(i); DoubleArray errorForTime = errorMatrix.row(i); reduceRawData(directDefinition, ratesProvider, capFloorData.Strikes, volatilityForTime, errorForTime, 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]); } // create caplet nodes and initial caplet vol surface ResolvedIborCapFloorLeg cap = capList[capList.Count - 1]; int nCaplets = cap.CapletFloorletPeriods.size(); DoubleArray capletExpiries = DoubleArray.of(nCaplets, n => directDefinition.DayCount.relativeYearFraction(calibrationDate, cap.CapletFloorletPeriods.get(n).FixingDateTime.toLocalDate())); Triple <DoubleArray, DoubleArray, DoubleArray> capletNodes; DoubleArray initialVols = DoubleArray.copyOf(volList); if (directDefinition.ShiftCurve.Present) { metadata = Surfaces.blackVolatilityByExpiryStrike(directDefinition.Name.Name, directDefinition.DayCount); Curve shiftCurve = directDefinition.ShiftCurve.get(); if (capFloorData.DataType.Equals(NORMAL_VOLATILITY)) { initialVols = DoubleArray.of(capList.Count, n => volList[n] / (ratesProvider.iborIndexRates(index).rate(capList[n].FinalPeriod.IborRate.Observation) + shiftCurve.yValue(timeList[n]))); } InterpolatedNodalSurface capVolSurface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), DoubleArray.copyOf(strikeList), initialVols, INTERPOLATOR); capletNodes = createCapletNodes(capVolSurface, capletExpiries, strikes, directDefinition.ShiftCurve.get()); volatilitiesFunction = createShiftedBlackVolatilitiesFunction(index, calibrationDateTime, shiftCurve); } else { InterpolatedNodalSurface capVolSurface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), DoubleArray.copyOf(strikeList), initialVols, INTERPOLATOR); capletNodes = createCapletNodes(capVolSurface, capletExpiries, strikes); } InterpolatedNodalSurface baseSurface = InterpolatedNodalSurface.of(metadata, capletNodes.First, capletNodes.Second, capletNodes.Third, INTERPOLATOR); DoubleMatrix penaltyMatrix = directDefinition.computePenaltyMatrix(strikes, capletExpiries); // solve least square LeastSquareResults res = solver.solve(DoubleArray.copyOf(priceList), DoubleArray.copyOf(errorList), getPriceFunction(capList, ratesProvider, volatilitiesFunction, baseSurface), getJacobianFunction(capList, ratesProvider, volatilitiesFunction, baseSurface), capletNodes.Third, penaltyMatrix, POSITIVE); InterpolatedNodalSurface resSurface = InterpolatedNodalSurface.of(metadata, capletNodes.First, capletNodes.Second, res.FitParameters, directDefinition.Interpolator); return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(volatilitiesFunction(resSurface), res.ChiSq)); }