public virtual void coverage() { SabrParametersIborCapletFloorletVolatilities test1 = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); coverImmutableBean(test1); SabrParametersIborCapletFloorletVolatilities test2 = SabrParametersIborCapletFloorletVolatilities.of(NAME2, IborIndices.EUR_LIBOR_3M, DATE_TIME.plusDays(1), IborCapletFloorletSabrRateVolatilityDataSet.SABR_PARAM_FLAT); coverBeanEquals(test1, test2); }
public virtual void test_calc() { SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); assertEquals(test.alpha(1.56), PARAM.alpha(1.56)); assertEquals(test.beta(1.56), PARAM.beta(1.56)); assertEquals(test.rho(1.56), PARAM.rho(1.56)); assertEquals(test.nu(1.56), PARAM.nu(1.56)); assertEquals(test.shift(1.56), PARAM.shift(1.56)); }
public virtual void test_findData() { SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); assertEquals(test.findData(PARAM.AlphaCurve.Name), PARAM.AlphaCurve); assertEquals(test.findData(PARAM.BetaCurve.Name), PARAM.BetaCurve); assertEquals(test.findData(PARAM.RhoCurve.Name), PARAM.RhoCurve); assertEquals(test.findData(PARAM.NuCurve.Name), PARAM.NuCurve); assertEquals(test.findData(PARAM.ShiftCurve.Name), PARAM.ShiftCurve); assertEquals(test.findData(SurfaceName.of("Rubbish")), null); }
public virtual void test_relativeTime() { SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); double test1 = prov.relativeTime(DATE_TIME); assertEquals(test1, 0d); double test2 = prov.relativeTime(DATE_TIME.plusYears(2)); double test3 = prov.relativeTime(DATE_TIME.minusYears(2)); assertEquals(test2, -test3, 1e-2); }
//------------------------------------------------------------------------- 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)); }
public virtual void test_parameterSensitivity() { double alphaSensi = 2.24, betaSensi = 3.45, rhoSensi = -2.12, nuSensi = -0.56, shiftSensi = 2.5; SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); for (int i = 0; i < NB_TEST; i++) { double expiryTime = prov.relativeTime(TEST_OPTION_EXPIRY[i]); PointSensitivities point = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, ALPHA, EUR, alphaSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, BETA, EUR, betaSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, RHO, EUR, rhoSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, NU, EUR, nuSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, SHIFT, EUR, shiftSensi)); CurrencyParameterSensitivities sensiComputed = prov.parameterSensitivity(point); UnitParameterSensitivity alphaSensitivities = prov.Parameters.AlphaCurve.yValueParameterSensitivity(expiryTime); UnitParameterSensitivity betaSensitivities = prov.Parameters.BetaCurve.yValueParameterSensitivity(expiryTime); UnitParameterSensitivity rhoSensitivities = prov.Parameters.RhoCurve.yValueParameterSensitivity(expiryTime); UnitParameterSensitivity nuSensitivities = prov.Parameters.NuCurve.yValueParameterSensitivity(expiryTime); UnitParameterSensitivity shiftSensitivities = prov.Parameters.ShiftCurve.yValueParameterSensitivity(expiryTime); CurrencyParameterSensitivity alphaSensiObj = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_ALPHA.CurveName, EUR); CurrencyParameterSensitivity betaSensiObj = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_BETA.CurveName, EUR); CurrencyParameterSensitivity rhoSensiObj = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_RHO.CurveName, EUR); CurrencyParameterSensitivity nuSensiObj = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_NU.CurveName, EUR); CurrencyParameterSensitivity shiftSensiObj = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_SHIFT.CurveName, EUR); DoubleArray alphaNodeSensiComputed = alphaSensiObj.Sensitivity; DoubleArray betaNodeSensiComputed = betaSensiObj.Sensitivity; DoubleArray rhoNodeSensiComputed = rhoSensiObj.Sensitivity; DoubleArray nuNodeSensiComputed = nuSensiObj.Sensitivity; DoubleArray shiftNodeSensiComputed = shiftSensiObj.Sensitivity; assertEquals(alphaSensitivities.Sensitivity.size(), alphaNodeSensiComputed.size()); assertEquals(betaSensitivities.Sensitivity.size(), betaNodeSensiComputed.size()); assertEquals(rhoSensitivities.Sensitivity.size(), rhoNodeSensiComputed.size()); assertEquals(nuSensitivities.Sensitivity.size(), nuNodeSensiComputed.size()); assertEquals(shiftSensitivities.Sensitivity.size(), shiftNodeSensiComputed.size()); for (int k = 0; k < alphaNodeSensiComputed.size(); ++k) { assertEquals(alphaNodeSensiComputed.get(k), alphaSensitivities.Sensitivity.get(k) * alphaSensi, TOLERANCE_VOL); } for (int k = 0; k < betaNodeSensiComputed.size(); ++k) { assertEquals(betaNodeSensiComputed.get(k), betaSensitivities.Sensitivity.get(k) * betaSensi, TOLERANCE_VOL); } for (int k = 0; k < rhoNodeSensiComputed.size(); ++k) { assertEquals(rhoNodeSensiComputed.get(k), rhoSensitivities.Sensitivity.get(k) * rhoSensi, TOLERANCE_VOL); } for (int k = 0; k < nuNodeSensiComputed.size(); ++k) { assertEquals(nuNodeSensiComputed.get(k), nuSensitivities.Sensitivity.get(k) * nuSensi, TOLERANCE_VOL); } for (int k = 0; k < shiftNodeSensiComputed.size(); ++k) { assertEquals(shiftNodeSensiComputed.get(k), shiftSensitivities.Sensitivity.get(k) * shiftSensi, TOLERANCE_VOL); } } }
// update vols private SabrParametersIborCapletFloorletVolatilities updateParameters(SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition, SabrParametersIborCapletFloorletVolatilities volatilities, DoubleArray newValues) { SabrParameters sabrParams = volatilities.Parameters; CurveMetadata alphaMetadata = sabrParams.AlphaCurve.Metadata; CurveMetadata betaMetadata = sabrParams.BetaCurve.Metadata; CurveMetadata rhoMetadata = sabrParams.RhoCurve.Metadata; CurveMetadata nuMetadata = sabrParams.NuCurve.Metadata; IList <Curve> newCurveList = sabrDefinition.createSabrParameterCurve(ImmutableList.of(alphaMetadata, betaMetadata, rhoMetadata, nuMetadata), newValues); SabrParameters newSabrParams = SabrParameters.of(newCurveList[0], newCurveList[1], newCurveList[2], newCurveList[3], sabrDefinition.ShiftCurve, sabrDefinition.SabrVolatilityFormula); SabrParametersIborCapletFloorletVolatilities newVols = SabrParametersIborCapletFloorletVolatilities.of(volatilities.Name, volatilities.Index, volatilities.ValuationDateTime, newSabrParams); return(newVols); }
public virtual void test_volatility() { SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); for (int i = 0; i < NB_TEST; i++) { for (int j = 0; j < NB_STRIKE; ++j) { double expiryTime = prov.relativeTime(TEST_OPTION_EXPIRY[i]); double volExpected = PARAM.volatility(expiryTime, TEST_STRIKE[j], TEST_FORWARD); double volComputed = prov.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[j], TEST_FORWARD); assertEquals(volComputed, volExpected, TOLERANCE_VOL); ValueDerivatives volAdjExpected = PARAM.volatilityAdjoint(expiryTime, TEST_STRIKE[j], TEST_FORWARD); ValueDerivatives volAdjComputed = prov.volatilityAdjoint(expiryTime, TEST_STRIKE[j], TEST_FORWARD); assertEquals(volAdjComputed.Value, volExpected, TOLERANCE_VOL); assertTrue(DoubleArrayMath.fuzzyEquals(volAdjComputed.Derivatives.toArray(), volAdjExpected.Derivatives.toArray(), TOLERANCE_VOL)); } } }
public virtual void test_of() { SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); assertEquals(test.Index, EUR_EURIBOR_3M); assertEquals(test.DayCount, ACT_ACT_ISDA); assertEquals(test.Parameters, PARAM); assertEquals(test.ValuationDateTime, DATE_TIME); assertEquals(test.ParameterCount, PARAM.ParameterCount); int nParams = PARAM.ParameterCount; double newValue = 152d; for (int i = 0; i < nParams; ++i) { assertEquals(test.getParameter(i), PARAM.getParameter(i)); assertEquals(test.getParameterMetadata(i), PARAM.getParameterMetadata(i)); assertEquals(test.withParameter(i, newValue), SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM.withParameter(i, newValue))); assertEquals(test.withPerturbation((n, v, m) => 2d * v), SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM.withPerturbation((n, v, m) => 2d * v))); } }
public virtual void test_parameterSensitivity_multi() { double[] points1 = new double[] { 2.24, 3.45, -2.12, -0.56 }; double[] points2 = new double[] { -0.145, 1.01, -5.0, -11.0 }; double[] points3 = new double[] { 1.3, -4.32, 2.1, -7.18 }; SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM); double expiryTime0 = prov.relativeTime(TEST_OPTION_EXPIRY[0]); double expiryTime3 = prov.relativeTime(TEST_OPTION_EXPIRY[3]); for (int i = 0; i < NB_TEST; i++) { PointSensitivities sensi1 = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, ALPHA, EUR, points1[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, BETA, EUR, points1[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, RHO, EUR, points1[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, NU, EUR, points1[3])); PointSensitivities sensi2 = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, ALPHA, EUR, points2[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, BETA, EUR, points2[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, RHO, EUR, points2[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, NU, EUR, points2[3])); PointSensitivities sensi3 = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, ALPHA, EUR, points3[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, BETA, EUR, points3[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, RHO, EUR, points3[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, NU, EUR, points3[3])); PointSensitivities sensis = sensi1.combinedWith(sensi2).combinedWith(sensi3).normalized(); CurrencyParameterSensitivities computed = prov.parameterSensitivity(sensis); CurrencyParameterSensitivities expected = prov.parameterSensitivity(sensi1).combinedWith(prov.parameterSensitivity(sensi2)).combinedWith(prov.parameterSensitivity(sensi3)); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.AlphaCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.AlphaCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.BetaCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.BetaCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.RhoCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.RhoCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.NuCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.NuCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL); } }
/// <summary> /// Obtains {@code SabrParametersIborCapletFloorletVolatilities} with constant shift for specified valuation date. /// </summary> /// <param name="dateTime"> the valuation date time </param> /// <param name="index"> the index </param> /// <returns> the volatility provider </returns> public static SabrParametersIborCapletFloorletVolatilities getVolatilities(ZonedDateTime dateTime, IborIndex index) { return(SabrParametersIborCapletFloorletVolatilities.of(NAME, index, dateTime, SABR_PARAM_CONST_SHIFT)); }
/// <summary> /// Obtains {@code SabrParametersIborCapletFloorletVolatilities} with constant SABR parameters for specified valuation date. /// </summary> /// <param name="valuationDate"> the valuation date </param> /// <param name="index"> the index </param> /// <returns> the volatility provider </returns> public static SabrParametersIborCapletFloorletVolatilities getVolatilitiesFlatParameters(LocalDate valuationDate, IborIndex index) { ZonedDateTime dateTime = valuationDate.atStartOfDay(ZoneOffset.UTC); return(SabrParametersIborCapletFloorletVolatilities.of(NAME, index, dateTime, SABR_PARAM_FLAT)); }
//------------------------------------------------------------------------- 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)); }