Esempio n. 1
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 SabrIborCapletFloorletVolatilityCalibrationDefinition, "definition should be SabrIborCapletFloorletVolatilityCalibrationDefinition");
            SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition = (SabrIborCapletFloorletVolatilityCalibrationDefinition)definition;
            // unpack cap data, create node caps
            IborIndex index           = sabrDefinition.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(sabrDefinition, calibrationDateTime, capFloorData);
            SurfaceMetadata metadata   = sabrDefinition.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(sabrDefinition, 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 initial caplet vol surface
            IList <CurveMetadata> metadataList                = sabrDefinition.createSabrParameterMetadata();
            DoubleArray           initialValues               = sabrDefinition.createFullInitialValues();
            IList <Curve>         curveList                   = sabrDefinition.createSabrParameterCurve(metadataList, initialValues);
            SabrParameters        sabrParamsInitial           = SabrParameters.of(curveList[0], curveList[1], curveList[2], curveList[3], sabrDefinition.ShiftCurve, sabrDefinition.SabrVolatilityFormula);
            SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(sabrDefinition.Name, index, calibrationDateTime, sabrParamsInitial);
            // solve least square
            UncoupledParameterTransforms transform = new UncoupledParameterTransforms(initialValues, sabrDefinition.createFullTransform(TRANSFORMS), new BitArray());

            System.Func <DoubleArray, DoubleArray>  valueFunction    = createPriceFunction(sabrDefinition, ratesProvider, vols, capList, priceList);
            System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(sabrDefinition, ratesProvider, vols, capList, priceList, index.Currency);
            NonLinearTransformFunction      transFunc    = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform);
            LeastSquareResults              res          = solver.solve(DoubleArray.filled(priceList.Count, 1d), DoubleArray.copyOf(errorList), transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(initialValues));
            LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform);

            vols = updateParameters(sabrDefinition, vols, resTransform.ModelParameters);

            return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, res.ChiSq));
        }
        //-------------------------------------------------------------------------
        // create complete lists of caps, volatilities, strikes, expiries
        protected internal virtual void reduceRawData(IborCapletFloorletVolatilityDefinition definition, RatesProvider ratesProvider, DoubleArray strikes, DoubleArray volatilityData, DoubleArray errors, LocalDate startDate, LocalDate endDate, SurfaceMetadata metadata, System.Func <Surface, IborCapletFloorletVolatilities> volatilityFunction, IList <double> timeList, IList <double> strikeList, IList <double> volList, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, IList <double> errorList)
        {
            int nStrikes = strikes.size();

            for (int i = 0; i < nStrikes; ++i)
            {
                if (Double.isFinite(volatilityData.get(i)))
                {
                    ResolvedIborCapFloorLeg capFloor = definition.createCap(startDate, endDate, strikes.get(i)).resolve(referenceData);
                    capList.Add(capFloor);
                    strikeList.Add(strikes.get(i));
                    volList.Add(volatilityData.get(i));
                    ConstantSurface constVolSurface     = ConstantSurface.of(metadata, volatilityData.get(i));
                    IborCapletFloorletVolatilities vols = volatilityFunction(constVolSurface);
                    timeList.Add(vols.relativeTime(capFloor.FinalFixingDateTime));
                    priceList.Add(pricer.presentValue(capFloor, ratesProvider, vols).Amount);
                    errorList.Add(errors.get(i));
                }
            }
        }
Esempio n. 3
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 SabrIborCapletFloorletVolatilityBootstrapDefinition, "definition should be SabrIborCapletFloorletVolatilityBootstrapDefinition");
            SabrIborCapletFloorletVolatilityBootstrapDefinition bsDefinition = (SabrIborCapletFloorletVolatilityBootstrapDefinition)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]);
            }

            IList <CurveMetadata> metadataList   = bsDefinition.createSabrParameterMetadata();
            DoubleArray           timeToExpiries = DoubleArray.of(nExpiries, i => timeList[startIndex[i]]);

            BitArray @fixed  = new BitArray();
            bool     betaFix = false;
            Curve    betaCurve;
            Curve    rhoCurve;

            if (bsDefinition.BetaCurve.Present)
            {
                betaFix = true;
                @fixed.Set(1, true);
                betaCurve = bsDefinition.BetaCurve.get();
                rhoCurve  = InterpolatedNodalCurve.of(metadataList[2], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            }
            else
            {
                @fixed.Set(2, true);
                betaCurve = InterpolatedNodalCurve.of(metadataList[1], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
                rhoCurve  = bsDefinition.RhoCurve.get();
            }
            InterpolatedNodalCurve alphaCurve = InterpolatedNodalCurve.of(metadataList[0], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            InterpolatedNodalCurve nuCurve    = InterpolatedNodalCurve.of(metadataList[3], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            Curve          shiftCurve         = bsDefinition.ShiftCurve;
            SabrParameters sabrParams         = SabrParameters.of(alphaCurve, betaCurve, rhoCurve, nuCurve, shiftCurve, bsDefinition.SabrVolatilityFormula);
            SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(bsDefinition.Name, index, calibrationDateTime, sabrParams);
            double        totalChiSq = 0d;
            ZonedDateTime prevExpiry = calibrationDateTime.minusDays(1L);     // included if calibrationDateTime == fixingDateTime

            for (int i = 0; i < nExpiries; ++i)
            {
                DoubleArray start = computeInitialValues(ratesProvider, betaCurve, shiftCurve, timeList, volList, capList, startIndex, i, betaFix, capFloorData.DataType);
                UncoupledParameterTransforms transform = new UncoupledParameterTransforms(start, TRANSFORMS, @fixed);
                int nCaplets     = startIndex[i + 1] - startIndex[i];
                int currentStart = startIndex[i];
                System.Func <DoubleArray, DoubleArray>  valueFunction    = createPriceFunction(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, nExpiries, i, nCaplets, betaFix);
                System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(ratesProvider, vols, prevExpiry, capList, priceList, index.Currency, startIndex, nExpiries, i, nCaplets, betaFix);
                NonLinearTransformFunction transFunc = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform);
                DoubleArray        adjustedPrices    = this.adjustedPrices(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, i, nCaplets);
                DoubleArray        errors            = DoubleArray.of(nCaplets, n => errorList[currentStart + n]);
                LeastSquareResults res = solver.solve(adjustedPrices, errors, transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(start));
                LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform);
                vols        = updateParameters(vols, nExpiries, i, betaFix, resTransform.ModelParameters);
                totalChiSq += res.ChiSq;
                prevExpiry  = capList[startIndex[i + 1] - 1].FinalFixingDateTime;
            }
            return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, totalChiSq));
        }
Esempio n. 4
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));
        }
 /// <summary>
 /// Calibrates caplet volatilities to cap volatilities.
 /// </summary>
 /// <param name="definition">  the caplet volatility definition </param>
 /// <param name="calibrationDateTime">  the calibration time </param>
 /// <param name="capFloorData">  the cap data </param>
 /// <param name="ratesProvider">  the rates provider </param>
 /// <returns> the calibration result </returns>
 public abstract IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider);
        // function creating volatilities object from surface
        protected internal virtual System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData)
        {
            IborIndex index = definition.Index;

            if (capFloorData.StrikeType.Equals(STRIKE))
            {
                if (capFloorData.DataType.Equals(BLACK_VOLATILITY))
                {
                    return(blackVolatilitiesFunction(index, calibrationDateTime));
                }
                else if (capFloorData.DataType.Equals(NORMAL_VOLATILITY))
                {
                    return(normalVolatilitiesFunction(index, calibrationDateTime));
                }
                throw new System.ArgumentException("Data type not supported");
            }
            throw new System.ArgumentException("strike type must be ValueType.STRIKE");
        }
        //-------------------------------------------------------------------------
        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));
        }