Exemplo 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));
        }
Exemplo n.º 2
0
        //-------------------------------------------------------------------------
        public virtual void test_builder()
        {
            ResolvedFxVanillaOption test = sut();

            assertEquals(test.Expiry, EXPIRY_DATE_TIME);
            assertEquals(test.ExpiryDate, EXPIRY_DATE_TIME.toLocalDate());
            assertEquals(test.LongShort, LONG);
            assertEquals(test.CounterCurrency, USD);
            assertEquals(test.PutCall, CALL);
            assertEquals(test.Strike, STRIKE);
            assertEquals(test.Underlying, FX);
            assertEquals(test.CurrencyPair, FX.CurrencyPair);
        }
Exemplo n.º 3
0
        //-------------------------------------------------------------------------
        public virtual void test_presentValue()
        {
            CurrencyAmount computedRec = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
            CurrencyAmount computedPay = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
            SwapPaymentEventPricer <SwapPaymentEvent> paymentEventPricer = SwapPaymentEventPricer.standard();
            ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(RSWAP_REC, RATE_PROVIDER);
            LocalDate       expiryDate    = MATURITY.toLocalDate();
            int             nPayments     = cashFlowEquiv.PaymentEvents.size();

            double[] alpha = new double[nPayments];
            double[] discountedCashFlow = new double[nPayments];
            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                SwapPaymentEvent payment = cashFlowEquiv.PaymentEvents.get(loopcf);
                alpha[loopcf] = HW_PROVIDER.alpha(RATE_PROVIDER.ValuationDate, expiryDate, expiryDate, payment.PaymentDate);
                discountedCashFlow[loopcf] = paymentEventPricer.presentValue(payment, RATE_PROVIDER);
            }
            double omegaPay    = -1d;
            double kappa       = HW_PROVIDER.Model.kappa(DoubleArray.copyOf(discountedCashFlow), DoubleArray.copyOf(alpha));
            double expectedRec = 0.0;
            double expectedPay = 0.0;

            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                expectedRec += discountedCashFlow[loopcf] * NORMAL.getCDF((kappa + alpha[loopcf]));
                expectedPay += discountedCashFlow[loopcf] * NORMAL.getCDF(omegaPay * (kappa + alpha[loopcf]));
            }
            assertEquals(computedRec.Currency, EUR);
            assertEquals(computedRec.Amount, expectedRec, NOTIONAL * TOL);
            assertEquals(computedPay.Currency, EUR);
            assertEquals(computedPay.Amount, expectedPay, NOTIONAL * TOL);
        }
 //-------------------------------------------------------------------------
 public virtual void test_basics()
 {
     assertEquals(VOL_SIMPLE_MONEY_PRICE.ValuationDate, VAL_DATE_TIME.toLocalDate());
     assertEquals(VOL_SIMPLE_MONEY_PRICE.ValuationDateTime, VAL_DATE_TIME);
     assertEquals(VOL_SIMPLE_MONEY_PRICE.Index, EUR_EURIBOR_3M);
     assertEquals(VOL_SIMPLE_MONEY_PRICE.Name, IborFutureOptionVolatilitiesName.of("Price"));
 }
        //-------------------------------------------------------------------------
        public double relativeTime(ZonedDateTime dateTime)
        {
            ArgChecker.notNull(dateTime, "dateTime");
            LocalDate valuationDate = valuationDateTime.toLocalDate();
            LocalDate date          = dateTime.toLocalDate();

            return(dayCount.relativeYearFraction(valuationDate, date));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the time to expiry for the valuation date time.
        /// </summary>
        /// <param name="valuationDateTime">  the valuation date time </param>
        /// <param name="dayCount">  the day count </param>
        /// <param name="refData">  the reference data </param>
        /// <returns> the time to expiry </returns>
        public double timeToExpiry(ZonedDateTime valuationDateTime, DayCount dayCount, ReferenceData refData)
        {
            LocalDate valuationDate = valuationDateTime.toLocalDate();
            LocalDate spotDate      = spotDateOffset.adjust(valuationDate, refData);
            LocalDate deliveryDate  = businessDayAdjustment.adjust(spotDate.plus(tenor), refData);
            LocalDate expiryDate    = expiryDateOffset_Renamed.adjust(deliveryDate, refData);

            return(dayCount.relativeYearFraction(valuationDate, expiryDate));
        }
        public virtual void test_expiry()
        {
            FxOptionVolatilitiesNode test     = FxOptionVolatilitiesNode.of(EUR_GBP, SPOT_DATE_OFFSET, BDA, ValueType.BLACK_VOLATILITY, QUOTE_ID, Tenor.TENOR_3M, STRIKE);
            ZonedDateTime            dateTime = LocalDate.of(2016, 1, 23).atStartOfDay(ZoneId.of("Europe/London"));
            DaysAdjustment           expAdj   = DaysAdjustment.ofBusinessDays(-2, LO_TA);
            double computed = test.timeToExpiry(dateTime, ACT_365F, REF_DATA);
            double expected = ACT_365F.relativeYearFraction(dateTime.toLocalDate(), expAdj.adjust(BDA.adjust(SPOT_DATE_OFFSET.adjust(dateTime.toLocalDate(), REF_DATA).plus(Tenor.TENOR_3M), REF_DATA), REF_DATA));

            assertEquals(computed, expected);
        }
Exemplo n.º 8
0
        //-------------------------------------------------------------------------
        public virtual void test_builder()
        {
            ResolvedSwaption test = sut();

            assertEquals(test.ExpiryDate, EXPIRY.toLocalDate());
            assertEquals(test.Expiry, EXPIRY);
            assertEquals(test.LongShort, LONG);
            assertEquals(test.SwaptionSettlement, PHYSICAL_SETTLE);
            assertEquals(test.Underlying, SWAP);
            assertEquals(test.Currency, USD);
            assertEquals(test.Index, USD_LIBOR_3M);
        }
Exemplo n.º 9
0
        public virtual void test_builder_min()
        {
            IborCapletFloorletPeriod test = IborCapletFloorletPeriod.builder().notional(NOTIONAL).startDate(START).endDate(END).yearFraction(YEAR_FRACTION).caplet(STRIKE).iborRate(RATE_COMP).build();

            assertEquals(test.Caplet.Value, STRIKE);
            assertEquals(test.Floorlet.HasValue, false);
            assertEquals(test.Strike, STRIKE);
            assertEquals(test.StartDate, START);
            assertEquals(test.EndDate, END);
            assertEquals(test.PaymentDate, test.EndDate);
            assertEquals(test.Currency, EUR);
            assertEquals(test.Notional, NOTIONAL);
            assertEquals(test.IborRate, RATE_COMP);
            assertEquals(test.Index, EUR_EURIBOR_3M);
            assertEquals(test.FixingDate, FIXING_TIME_ZONE.toLocalDate());
            assertEquals(test.FixingDateTime, FIXING_TIME_ZONE);
            assertEquals(test.PutCall, PutCall.CALL);
            assertEquals(test.UnadjustedStartDate, START);
            assertEquals(test.UnadjustedEndDate, END);
            assertEquals(test.YearFraction, YEAR_FRACTION);
        }
Exemplo n.º 10
0
        public virtual void test_volatilities()
        {
            BlackFxOptionSmileVolatilitiesSpecification @base = BlackFxOptionSmileVolatilitiesSpecification.builder().name(VOL_NAME).currencyPair(EUR_GBP).dayCount(ACT_360).nodes(NODES).timeInterpolator(PCHIP).strikeInterpolator(PCHIP).build();
            LocalDate     date       = LocalDate.of(2017, 9, 25);
            ZonedDateTime dateTime   = date.atStartOfDay().atZone(ZoneId.of("Europe/London"));
            DoubleArray   parameters = DoubleArray.of(0.05, -0.05, 0.15, 0.25, 0.1, -0.1);
            BlackFxOptionSmileVolatilities computed = @base.volatilities(dateTime, parameters, REF_DATA);
            LocalDate               spotDate        = SPOT_OFFSET.adjust(dateTime.toLocalDate(), REF_DATA);
            DaysAdjustment          expOffset       = DaysAdjustment.ofBusinessDays(-2, TA_LO);
            DoubleArray             expiries        = DoubleArray.of(ACT_360.relativeYearFraction(date, expOffset.adjust(BUS_ADJ.adjust(spotDate.plus(Tenor.TENOR_3M), REF_DATA), REF_DATA)), ACT_360.relativeYearFraction(date, expOffset.adjust(BUS_ADJ.adjust(spotDate.plus(Tenor.TENOR_1Y), REF_DATA), REF_DATA)));
            SmileDeltaTermStructure smiles          = InterpolatedStrikeSmileDeltaTermStructure.of(expiries, DoubleArray.of(0.1), DoubleArray.of(0.25, 0.15), DoubleMatrix.ofUnsafe(new double[][]
            {
                new double[] { -0.1 },
                new double[] { -0.05 }
            }), DoubleMatrix.ofUnsafe(new double[][]
            {
                new double[] { 0.1 },
                new double[] { 0.05 }
            }), ACT_360, PCHIP, FLAT, FLAT, PCHIP, FLAT, FLAT);
            BlackFxOptionSmileVolatilities expected = BlackFxOptionSmileVolatilities.of(VOL_NAME, EUR_GBP, dateTime, smiles);

            assertEquals(computed, expected);
        }
Exemplo n.º 11
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));
        }
Exemplo n.º 12
0
        /// <summary>
        /// Computes the present value sensitivity to SABR parameters by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityModelParamsSabr(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency      ccy           = cmsPeriod.Currency;
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    return(PointSensitivityBuilder.none());
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double expiryTime            = swaptionVolatilities.relativeTime(expiryDate);
            double shift                 = swaptionVolatilities.shift(expiryTime, tenor);
            double strikeCpn             = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;
            double forward               = swapPricer.parRate(swap, provider);
            double eta                   = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor                = dfPayment / intProv.h(forward) * intProv.g(forward);
            double factor2               = factor * intProv.k(strikeCpn);

            double[] strikePartPrice          = intProv.SabrExtrapolation.priceAdjointSabr(Math.Max(0d, strikeCpn + shift), intProv.PutCall).Derivatives.multipliedBy(factor2).toArray();
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_VEGA, NUM_ITER);

            double[] totalSensi = new double[4];
            for (int loopparameter = 0; loopparameter < 4; loopparameter++)
            {
                double integralPart = 0d;
                System.Func <double, double> integrant = intProv.integrantVega(loopparameter);
                try
                {
                    if (intProv.PutCall.Call)
                    {
                        integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    }
                    else
                    {
                        integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e);
                }
                totalSensi[loopparameter] = (strikePartPrice[loopparameter] + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            }
            SwaptionVolatilitiesName name = swaptionVolatilities.Name;

            return(PointSensitivityBuilder.of(SwaptionSabrSensitivity.of(name, expiryTime, tenor, ALPHA, ccy, totalSensi[0]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, BETA, ccy, totalSensi[1]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, RHO, ccy, totalSensi[2]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, NU, ccy, totalSensi[3])));
        }
Exemplo n.º 13
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value curve sensitivity by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityRates(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsDeltaIntegrantProvider intProv    = new CmsDeltaIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            RungeKuttaIntegrator1D    integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);

            double[] bs = intProv.bsbsp(strikeCpn);
            double[] n  = intProv.Nnp;
            double   strikePartPrice   = intProv.k(strikeCpn) * n[0] * bs[0];
            double   integralPartPrice = 0d;
            double   integralPart      = 0d;

            System.Func <double, double> integrant      = intProv.integrant();
            System.Func <double, double> integrantDelta = intProv.integrantDelta();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPartPrice = integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    integralPart      = dfPayment * integrateCall(integrator, integrantDelta, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPartPrice = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn).Value;
                    integralPart      = -dfPayment *integrator.integrate(integrantDelta, -shift, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double deltaPD = strikePartPrice + integralPartPrice;

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                deltaPD -= shift;
            }
            deltaPD *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            double strikePart = dfPayment * intProv.k(strikeCpn) * (n[1] * bs[0] + n[0] * bs[1]);
            double deltaFwd   = (strikePart + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            PointSensitivityBuilder sensiFwd = swapPricer.parRateSensitivity(swap, provider).multipliedBy(deltaFwd);
            PointSensitivityBuilder sensiDf  = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(deltaPD);

            return(sensiFwd.combinedWith(sensiDf));
        }
Exemplo n.º 14
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value </returns>
        public CurrencyAmount presentValue(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(CurrencyAmount.zero(ccy));
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);

            if (expiryTime < MIN_TIME)
            {
                double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, forward);
                return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
            }
            double eta = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor     = dfPayment / intProv.h(forward) * intProv.g(forward);
            double strikePart = factor * intProv.k(strikeCpn) * intProv.bs(strikeCpn);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);
            double integralPart = 0d;

            System.Func <double, double> integrant = intProv.integrant();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double priceCMS = (strikePart + integralPart);

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                priceCMS -= dfPayment * shift;
            }
            priceCMS *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            return(CurrencyAmount.of(ccy, priceCMS));
        }
 //-------------------------------------------------------------------------
 public double relativeTime(ZonedDateTime zonedDateTime)
 {
     ArgChecker.notNull(zonedDateTime, "date");
     return(dayCount.relativeYearFraction(valuationDateTime.toLocalDate(), zonedDateTime.toLocalDate()));
 }
Exemplo n.º 16
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));
        }
Exemplo n.º 17
0
        /// <summary>
        /// Computes the present value sensitivity to strike by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public double presentValueSensitivityStrike(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            ArgChecker.isFalse(cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON), "presentValueSensitivityStrike is not relevant for CMS coupon");
            Currency  ccy   = cmsPeriod.Currency;
            SwapIndex index = cmsPeriod.Index;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(0d);
            }
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        expiryTime    = swaptionVolatilities.relativeTime(expiryDate);
            double        strike        = cmsPeriod.Strike;
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = 0d;
                    switch (cmsPeriod.CmsPeriodType)
                    {
                    case CAPLET:
                        payoff = fixedRate.Value >= strike ? -1d : 0d;
                        break;

                    case FLOORLET:
                        payoff = fixedRate.Value < strike ? 1d : 0d;
                        break;

                    default:
                        throw new System.ArgumentException("unsupported CMS type");
                    }
                    return(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction * dfPayment);
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strike, expiryTime, tenor, cutOffStrike, eta);
            double factor = dfPayment * intProv.g(forward) / intProv.h(forward);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_STRIKE, NUM_ITER);

            double[] kpkpp = intProv.kpkpp(strike);
            double   firstPart;
            double   thirdPart;

            System.Func <double, double> integrant = intProv.integrantDualDelta();
            if (intProv.PutCall.Call)
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = integrateCall(integrator, integrant, swaptionVolatilities, forward, strike, expiryTime, tenor);
            }
            else
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strike).Value;
            }
            double secondPart = intProv.k(strike) * intProv.SabrExtrapolation.priceDerivativeStrike(strike + shift, intProv.PutCall);

            return(cmsPeriod.Notional * cmsPeriod.YearFraction * factor * (firstPart + secondPart + thirdPart));
        }
        //-------------------------------------------------------------------------
        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));
        }