public virtual void test_volatility_sensitivity()
        {
            double eps   = 1.0e-6;
            int    nData = TIME.size();

            for (int i = 0; i < NB_TEST; i++)
            {
                for (int k = 0; k < NB_TEST; k++)
                {
                    double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]);
                    IborCapletFloorletSensitivity point = IborCapletFloorletSensitivity.of(VOLS.Name, expiryTime, TEST_STRIKE[k], TEST_FORWARD, GBP, TEST_SENSITIVITY[i]);
                    double[] sensFd = new double[nData];
                    for (int j = 0; j < nData; j++)
                    {
                        DoubleArray volDataUp            = VOL.subArray(0, nData).with(j, VOL.get(j) + eps);
                        DoubleArray volDataDw            = VOL.subArray(0, nData).with(j, VOL.get(j) - eps);
                        InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataUp, INTERPOLATOR_2D);
                        InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataDw, INTERPOLATOR_2D);
                        ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities provUp = ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramUp, CURVE);
                        ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities provDw = ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramDw, CURVE);
                        double volUp = provUp.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD);
                        double volDw = provDw.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD);
                        double fd    = 0.5 * (volUp - volDw) / eps;
                        sensFd[j] = fd * TEST_SENSITIVITY[i];
                    }
                    CurrencyParameterSensitivity sensActual = VOLS.parameterSensitivity(point).Sensitivities.get(0);
                    double[] computed = sensActual.Sensitivity.toArray();
                    assertTrue(DoubleArrayMath.fuzzyEquals(computed, sensFd, eps));
                }
            }
        }
예제 #2
0
        public virtual void test_volatility_sensitivity()
        {
            double eps   = 1.0e-6;
            int    nData = TIME.size();

            for (int i = 0; i < NB_TEST; i++)
            {
                for (int k = 0; k < NB_TEST; k++)
                {
                    double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]);
                    IborCapletFloorletSensitivity point      = IborCapletFloorletSensitivity.of(IborCapletFloorletVolatilitiesName.of(NAME), expiryTime, TEST_STRIKE[k], TEST_FORWARD, GBP, TEST_SENSITIVITY[i]);
                    CurrencyParameterSensitivity  sensActual = VOLS.parameterSensitivity(point).Sensitivities.get(0);
                    DoubleArray computed = sensActual.Sensitivity;
                    for (int j = 0; j < nData; ++j)
                    {
                        DoubleArray volDataUp            = VOL.subArray(0, nData).with(j, VOL.get(j) + eps);
                        DoubleArray volDataDw            = VOL.subArray(0, nData).with(j, VOL.get(j) - eps);
                        InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataUp, INTERPOLATOR_2D);
                        InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataDw, INTERPOLATOR_2D);
                        NormalIborCapletFloorletExpiryStrikeVolatilities provUp = NormalIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramUp);
                        NormalIborCapletFloorletExpiryStrikeVolatilities provDw = NormalIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramDw);
                        double volUp = provUp.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD);
                        double volDw = provDw.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD);
                        double fd    = 0.5 * (volUp - volDw) / eps;
                        assertEquals(computed.get(j), fd * TEST_SENSITIVITY[i], eps);
                    }
                }
            }
        }
예제 #3
0
        private void testPriceSensitivityBlackVolatility(CurrencyParameterSensitivities computed, System.Func <BlackBondFutureVolatilities, double> valueFn)
        {
            IList <ParameterMetadata> list = computed.Sensitivities.get(0).ParameterMetadata;
            int nVol = VOL.size();

            assertEquals(list.Count, nVol);
            for (int i = 0; i < nVol; ++i)
            {
                double[] volUp = Arrays.copyOf(VOL.toArray(), nVol);
                double[] volDw = Arrays.copyOf(VOL.toArray(), nVol);
                volUp[i] += EPS;
                volDw[i] -= EPS;
                InterpolatedNodalSurface sfUp = InterpolatedNodalSurface.of(METADATA, TIME, MONEYNESS, DoubleArray.copyOf(volUp), INTERPOLATOR_2D);
                InterpolatedNodalSurface sfDw = InterpolatedNodalSurface.of(METADATA, TIME, MONEYNESS, DoubleArray.copyOf(volDw), INTERPOLATOR_2D);
                BlackBondFutureExpiryLogMoneynessVolatilities provUp = BlackBondFutureExpiryLogMoneynessVolatilities.of(VAL_DATE_TIME, sfUp);
                BlackBondFutureExpiryLogMoneynessVolatilities provDw = BlackBondFutureExpiryLogMoneynessVolatilities.of(VAL_DATE_TIME, sfDw);
                double expected = 0.5 * (valueFn(provUp) - valueFn(provDw)) / EPS;
                int    index    = -1;
                for (int j = 0; j < nVol; ++j)
                {
                    GenericVolatilitySurfaceYearFractionParameterMetadata meta = (GenericVolatilitySurfaceYearFractionParameterMetadata)list[j];
                    if (meta.YearFraction == TIME.get(i) && meta.Strike.Value == MONEYNESS.get(i))
                    {
                        index = j;
                        continue;
                    }
                }
                assertEquals(computed.Sensitivities.get(0).Sensitivity.get(index), expected, EPS);
            }
        }
예제 #4
0
	  public virtual void test_volatility_sensitivity()
	  {
		double eps = 1.0e-6;
		int nData = TIME.size();
		for (int i = 0; i < NB_TEST; i++)
		{
		  double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]);
		  SwaptionSensitivity point = SwaptionSensitivity.of(VOLS.Name, expiryTime, TEST_TENOR[i], TEST_STRIKE, TEST_FORWARD, GBP, TEST_SENSITIVITY[i]);
		  CurrencyParameterSensitivities sensActual = VOLS.parameterSensitivity(point);
		  DoubleArray computed = sensActual.getSensitivity(SURFACE.Name, GBP).Sensitivity;
		  for (int j = 0; j < nData; j++)
		  {
			DoubleArray volDataUp = VOL.with(j, VOL.get(j) + eps);
			DoubleArray volDataDw = VOL.with(j, VOL.get(j) - eps);
			InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, TENOR, volDataUp, INTERPOLATOR_2D);
			InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, TENOR, volDataDw, INTERPOLATOR_2D);
			BlackSwaptionExpiryTenorVolatilities provUp = BlackSwaptionExpiryTenorVolatilities.of(CONVENTION, VAL_DATE_TIME, paramUp);
			BlackSwaptionExpiryTenorVolatilities provDw = BlackSwaptionExpiryTenorVolatilities.of(CONVENTION, VAL_DATE_TIME, paramDw);
			double volUp = provUp.volatility(TEST_OPTION_EXPIRY[i], TEST_TENOR[i], TEST_STRIKE, TEST_FORWARD);
			double volDw = provDw.volatility(TEST_OPTION_EXPIRY[i], TEST_TENOR[i], TEST_STRIKE, TEST_FORWARD);
			double fd = 0.5 * (volUp - volDw) / eps;
			assertEquals(computed.get(j), fd * TEST_SENSITIVITY[i], eps);
		  }
		}
	  }
예제 #5
0
        public virtual void test_volatility_sensitivity()
        {
            double eps   = 1.0e-6;
            int    nData = TIME.size();

            for (int i = 0; i < NB_TEST; i++)
            {
                double expiry = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]);
                BondFutureOptionSensitivity  point      = BondFutureOptionSensitivity.of(VOLS.Name, expiry, TEST_FUTURE_EXPIRY[i], TEST_STRIKE_PRICE[i], TEST_FUTURE_PRICE[i], USD, TEST_SENSITIVITY[i]);
                CurrencyParameterSensitivity sensActual = VOLS.parameterSensitivity(point).Sensitivities.get(0);
                double[] computed = sensActual.Sensitivity.toArray();
                for (int j = 0; j < nData; j++)
                {
                    DoubleArray volDataUp            = VOL.with(j, VOL.get(j) + eps);
                    DoubleArray volDataDw            = VOL.with(j, VOL.get(j) - eps);
                    InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, MONEYNESS, volDataUp, INTERPOLATOR_2D);
                    InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, MONEYNESS, volDataDw, INTERPOLATOR_2D);
                    BlackBondFutureExpiryLogMoneynessVolatilities provUp = BlackBondFutureExpiryLogMoneynessVolatilities.of(VAL_DATE_TIME, paramUp);
                    BlackBondFutureExpiryLogMoneynessVolatilities provDw = BlackBondFutureExpiryLogMoneynessVolatilities.of(VAL_DATE_TIME, paramDw);
                    double volUp = provUp.volatility(expiry, TEST_FUTURE_EXPIRY[i], TEST_STRIKE_PRICE[i], TEST_FUTURE_PRICE[i]);
                    double volDw = provDw.volatility(expiry, TEST_FUTURE_EXPIRY[i], TEST_STRIKE_PRICE[i], TEST_FUTURE_PRICE[i]);
                    double fd    = 0.5 * (volUp - volDw) / eps;
                    assertEquals(computed[j], fd, eps);
                }
            }
        }
        public virtual void test_volatility_sensitivity()
        {
            double eps   = 1.0e-6;
            int    nData = TIME.size();

            for (int i = 0; i < NB_TEST; i++)
            {
                double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]);
                SwaptionSensitivity            point      = SwaptionSensitivity.of(VOLS.Name, expiryTime, TEST_TENOR, TEST_STRIKE[i], TEST_FORWARD, GBP, TEST_SENSITIVITY[i]);
                CurrencyParameterSensitivities sensActual = VOLS.parameterSensitivity(point);
                CurrencyParameterSensitivity   sensi      = sensActual.getSensitivity(SURFACE.Name, GBP);
                DoubleArray computed = sensi.Sensitivity;

                IDictionary <DoublesPair, double> map = new Dictionary <DoublesPair, double>();
                for (int j = 0; j < nData; ++j)
                {
                    DoubleArray volDataUp            = VOL.subArray(0, nData).with(j, VOL.get(j) + eps);
                    DoubleArray volDataDw            = VOL.subArray(0, nData).with(j, VOL.get(j) - eps);
                    InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataUp, INTERPOLATOR_2D);
                    InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataDw, INTERPOLATOR_2D);
                    NormalSwaptionExpiryStrikeVolatilities provUp = NormalSwaptionExpiryStrikeVolatilities.of(CONVENTION, VAL_DATE_TIME, paramUp);
                    NormalSwaptionExpiryStrikeVolatilities provDw = NormalSwaptionExpiryStrikeVolatilities.of(CONVENTION, VAL_DATE_TIME, paramDw);
                    double volUp = provUp.volatility(TEST_OPTION_EXPIRY[i], TEST_TENOR, TEST_STRIKE[i], TEST_FORWARD);
                    double volDw = provDw.volatility(TEST_OPTION_EXPIRY[i], TEST_TENOR, TEST_STRIKE[i], TEST_FORWARD);
                    double fd    = 0.5 * (volUp - volDw) / eps;
                    map[DoublesPair.of(TIME.get(j), STRIKE.get(j))] = fd;
                }
                IList <ParameterMetadata> list = sensi.ParameterMetadata;
                assertEquals(computed.size(), nData);
                for (int j = 0; j < list.Count; ++j)
                {
                    SwaptionSurfaceExpiryStrikeParameterMetadata metadata = (SwaptionSurfaceExpiryStrikeParameterMetadata)list[i];
                    double expected = map[DoublesPair.of(metadata.YearFraction, metadata.Strike)];
                    assertEquals(computed.get(i), expected, eps);
                }
            }
        }
        //-------------------------------------------------------------------------
        public virtual void coverage()
        {
            coverImmutableBean(VOLS);
            ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities vols = ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, VAL_DATE_TIME.plusMonths(1), InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, VOL, GridSurfaceInterpolator.of(TIME_SQUARE, LINEAR)), ConstantCurve.of("shift", 0.05));

            coverBeanEquals(VOLS, vols);
        }
예제 #8
0
        //-------------------------------------------------------------------------
        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));
        }
        //-------------------------------------------------------------------------
        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));
        }