//------------------------------------------------------------------------- public override NodalCurve calibrate(IList <ResolvedCdsTrade> calibrationCDSs, DoubleArray premiums, DoubleArray pointsUpfront, CurveName name, LocalDate valuationDate, CreditDiscountFactors discountFactors, RecoveryRates recoveryRates, ReferenceData refData) { int n = calibrationCDSs.Count; double[] guess = new double[n]; double[] t = new double[n]; double[] lgd = new double[n]; for (int i = 0; i < n; i++) { LocalDate endDate = calibrationCDSs[i].Product.ProtectionEndDate; t[i] = discountFactors.relativeYearFraction(endDate); lgd[i] = 1d - recoveryRates.recoveryRate(endDate); guess[i] = (premiums.get(i) + pointsUpfront.get(i) / t[i]) / lgd[i]; } DoubleArray times = DoubleArray.ofUnsafe(t); CurveMetadata baseMetadata = DefaultCurveMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.ZERO_RATE).curveName(name).dayCount(discountFactors.DayCount).build(); NodalCurve creditCurve = n == 1 ? ConstantNodalCurve.of(baseMetadata, t[0], guess[0]) : InterpolatedNodalCurve.of(baseMetadata, times, DoubleArray.ofUnsafe(guess), CurveInterpolators.PRODUCT_LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.PRODUCT_LINEAR); for (int i = 0; i < n; i++) { System.Func <double, double> func = getPriceFunction(i, calibrationCDSs[i], premiums.get(i), pointsUpfront.get(i), valuationDate, creditCurve, discountFactors, recoveryRates, refData); double[] bracket = BRACKER.getBracketedPoints(func, 0.8 * guess[i], 1.25 * guess[i], 0.0, double.PositiveInfinity); double zeroRate = bracket[0] > bracket[1] ? ROOTFINDER.getRoot(func, bracket[1], bracket[0]) : ROOTFINDER.getRoot(func, bracket[0], bracket[1]); //Negative guess handled creditCurve = creditCurve.withParameter(i, zeroRate); } return(creditCurve); }
public virtual void test_bondDiscountingProvider() { LocalDate valDate = LocalDate.of(2015, 6, 30); Curve ccAUsd = ConstantNodalCurve.of(Curves.zeroRates(CC_A_USD.CurveName, ACT_365F), 0.5d, 1.5d); Curve ccBGbp = ConstantNodalCurve.of(Curves.zeroRates(CC_B_GBP.CurveName, ACT_365F), 0.5d, 2d); Curve ccAGbp = ConstantNodalCurve.of(Curves.zeroRates(CC_A_GBP.CurveName, ACT_365F), 0.5d, 3d); Curve dcGbp = ConstantNodalCurve.of(Curves.zeroRates(DC_GBP.CurveName, ACT_365F), 0.5d, 0.1d); Curve dcUsd = ConstantNodalCurve.of(Curves.zeroRates(DC_USD.CurveName, ACT_365F), 0.5d, 0.05d); Curve rcA = ConstantCurve.of(Curves.recoveryRates(RC_A.CurveName, ACT_365F), 0.5d); Curve rcB = ConstantCurve.of(Curves.recoveryRates(RC_B.CurveName, ACT_365F), 0.4234d); IDictionary <CurveId, Curve> curveMap = new Dictionary <CurveId, Curve>(); curveMap[CC_A_USD] = ccAUsd; curveMap[CC_B_GBP] = ccBGbp; curveMap[CC_A_GBP] = ccAGbp; curveMap[DC_USD] = dcUsd; curveMap[DC_GBP] = dcGbp; curveMap[RC_A] = rcA; curveMap[RC_B] = rcB; MarketData md = ImmutableMarketData.of(valDate, ImmutableMap.copyOf(curveMap)); CreditRatesProvider provider = LOOKUP_WITH_SOURCE.creditRatesProvider(md); assertEquals(provider.ValuationDate, valDate); assertEquals(provider.findData(CC_A_USD.CurveName), ccAUsd); assertEquals(provider.findData(DC_USD.CurveName), dcUsd); assertEquals(provider.findData(RC_B.CurveName), rcB); assertEquals(provider.findData(CurveName.of("Rubbish")), null); // check credit curve LegalEntitySurvivalProbabilities cc = provider.survivalProbabilities(ISSUER_A, GBP); IsdaCreditDiscountFactors ccUnder = (IsdaCreditDiscountFactors)cc.SurvivalProbabilities; assertEquals(ccUnder.Curve.Name, ccAGbp.Name); assertThrowsRuntime(() => provider.survivalProbabilities(ISSUER_B, USD)); assertThrowsRuntime(() => provider.survivalProbabilities(ISSUER_C, USD)); // check discount curve IsdaCreditDiscountFactors dc = (IsdaCreditDiscountFactors)provider.discountFactors(USD); assertEquals(dc.Curve.Name, dcUsd.Name); assertThrowsRuntime(() => provider.discountFactors(EUR)); // check recovery rate curve ConstantRecoveryRates rc = (ConstantRecoveryRates)provider.recoveryRates(ISSUER_B); assertEquals(rc.RecoveryRate, rcB.getParameter(0)); assertThrowsRuntime(() => provider.recoveryRates(ISSUER_C)); }
public virtual void test_createSabrParameterCurve() { DoubleArray nuKnots = DoubleArray.of(5.0); SabrIborCapletFloorletVolatilityCalibrationDefinition fixedBeta = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedBeta(NAME, USD_LIBOR_3M, ACT_365F, BETA_RHO, ALPHA_KNOTS, BETA_RHO_KNOTS, nuKnots, DOUBLE_QUADRATIC, FLAT, LINEAR, HAGAN); SabrIborCapletFloorletVolatilityCalibrationDefinition fixedRho = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedRho(NAME, USD_LIBOR_3M, ACT_365F, BETA_RHO, ALPHA_KNOTS, BETA_RHO_KNOTS, nuKnots, DOUBLE_QUADRATIC, FLAT, LINEAR, HAGAN); ImmutableList <CurveMetadata> metadata = fixedBeta.createSabrParameterMetadata(); DoubleArray newValues = DoubleArray.of(0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.02, 0.05); DoubleArray newValues1 = DoubleArray.of(0.01, 0.01, 0.01, 0.01, 0.01, 0.01); DoubleArray newValues2 = DoubleArray.of(0.02, 0.02, 0.02); DoubleArray newValues3 = DoubleArray.of(0.05); IList <Curve> computedFixedBeta = fixedBeta.createSabrParameterCurve(metadata, newValues); IList <Curve> computedFixedRho = fixedRho.createSabrParameterCurve(metadata, newValues); Curve curveAlpha = InterpolatedNodalCurve.of(metadata.get(0), ALPHA_KNOTS, newValues1, DOUBLE_QUADRATIC, FLAT, LINEAR); Curve curveBeta = InterpolatedNodalCurve.of(metadata.get(1), BETA_RHO_KNOTS, newValues2, DOUBLE_QUADRATIC, FLAT, LINEAR); Curve curveRho = InterpolatedNodalCurve.of(metadata.get(2), BETA_RHO_KNOTS, newValues2, DOUBLE_QUADRATIC, FLAT, LINEAR); Curve curveNu = ConstantNodalCurve.of(metadata.get(3), nuKnots.get(0), newValues3.get(0)); assertEquals(computedFixedBeta, ImmutableList.of(curveAlpha, fixedBeta.BetaCurve.get(), curveRho, curveNu)); assertEquals(computedFixedRho, ImmutableList.of(curveAlpha, curveBeta, fixedRho.RhoCurve.get(), curveNu)); }
//------------------------------------------------------------------------- // shift the curve private NodalCurve withShift(InterpolatedNodalCurve curve, IList <ParameterMetadata> parameterMetadata, DoubleMatrix sensitivity, bool computeJacobian, double shift) { int nNode = curve.ParameterCount; if (shift < curve.XValues.get(0)) { //offset less than t value of 1st knot, so no knots are not removed double eta = curve.YValues.get(0) * shift; DoubleArray time = DoubleArray.of(nNode, i => curve.XValues.get(i) - shift); DoubleArray rate = DoubleArray.of(nNode, i => (curve.YValues.get(i) * curve.XValues.get(i) - eta) / time.get(i)); CurveMetadata metadata = curve.Metadata.withParameterMetadata(parameterMetadata); if (computeJacobian) { //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] transf = new double[nNode][nNode]; double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(nNode, nNode); for (int i = 0; i < nNode; ++i) { transf[i][0] = -shift / time.get(i); transf[i][i] += curve.XValues.get(i) / time.get(i); } DoubleMatrix jacobianMatrix = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity)); JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix); return(curve.withValues(time, rate).withMetadata(metadata.withInfo(CurveInfoType.JACOBIAN, jacobian))); } return(curve.withValues(time, rate).withMetadata(metadata)); } if (shift >= curve.XValues.get(nNode - 1)) { //new base after last knot. The new 'curve' has a constant zero rate which we represent with a nominal knot at 1.0 double time = 1d; double interval = curve.XValues.get(nNode - 1) - curve.XValues.get(nNode - 2); double rate = (curve.YValues.get(nNode - 1) * curve.XValues.get(nNode - 1) - curve.YValues.get(nNode - 2) * curve.XValues.get(nNode - 2)) / interval; if (computeJacobian) { //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] transf = new double[1][nNode]; double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(1, nNode); transf[0][nNode - 2] = -curve.XValues.get(nNode - 2) / interval; transf[0][nNode - 1] = curve.XValues.get(nNode - 1) / interval; DoubleMatrix jacobianMatrix = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity)); JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix); return(ConstantNodalCurve.of(curve.Metadata.withInfo(CurveInfoType.JACOBIAN, jacobian), time, rate)); } return(ConstantNodalCurve.of(curve.Metadata, time, rate)); } //offset greater than (or equal to) t value of 1st knot, so at least one knot must be removed int index = Arrays.binarySearch(curve.XValues.toArray(), shift); if (index < 0) { index = -(index + 1); } else { index++; } double interval = curve.XValues.get(index) - curve.XValues.get(index - 1); double tt1 = curve.XValues.get(index - 1) * (curve.XValues.get(index) - shift); double tt2 = curve.XValues.get(index) * (shift - curve.XValues.get(index - 1)); double eta = (curve.YValues.get(index - 1) * tt1 + curve.YValues.get(index) * tt2) / interval; int m = nNode - index; CurveMetadata metadata = curve.Metadata.withParameterMetadata(parameterMetadata.subList(index, nNode)); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int indexFinal = index; int indexFinal = index; DoubleArray time = DoubleArray.of(m, i => curve.XValues.get(i + indexFinal) - shift); DoubleArray rate = DoubleArray.of(m, i => (curve.YValues.get(i + indexFinal) * curve.XValues.get(i + indexFinal) - eta) / time.get(i)); if (computeJacobian) { //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] transf = new double[m][nNode]; double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(m, nNode); for (int i = 0; i < m; ++i) { transf[i][index - 1] -= tt1 / (time.get(i) * interval); transf[i][index] -= tt2 / (time.get(i) * interval); transf[i][i + index] += curve.XValues.get(i + index) / time.get(i); } DoubleMatrix jacobianMatrix = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity)); JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix); return(curve.withValues(time, rate).withMetadata(metadata.withInfo(CurveInfoType.JACOBIAN, jacobian))); } return(curve.withValues(time, rate).withMetadata(metadata)); }
/// <summary> /// Creates an instance from year fraction and zero rate values. /// </summary> /// <param name="currency"> the currency </param> /// <param name="valuationDate"> the valuation date </param> /// <param name="curveName"> the curve name </param> /// <param name="yearFractions"> the year fractions </param> /// <param name="zeroRates"> the zero rates </param> /// <param name="dayCount"> the day count </param> /// <returns> the instance </returns> public static IsdaCreditDiscountFactors of(Currency currency, LocalDate valuationDate, CurveName curveName, DoubleArray yearFractions, DoubleArray zeroRates, DayCount dayCount) { ArgChecker.notNull(yearFractions, "yearFractions"); ArgChecker.notNull(zeroRates, "zeroRates"); DefaultCurveMetadata metadata = DefaultCurveMetadata.builder().xValueType(YEAR_FRACTION).yValueType(ZERO_RATE).curveName(curveName).dayCount(dayCount).build(); NodalCurve curve = (yearFractions.size() == 1 && zeroRates.size() == 1) ? ConstantNodalCurve.of(metadata, yearFractions.get(0), zeroRates.get(0)) : InterpolatedNodalCurve.of(metadata, yearFractions, zeroRates, CurveInterpolators.PRODUCT_LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.PRODUCT_LINEAR); return(new IsdaCreditDiscountFactors(currency, valuationDate, curve)); }
//------------------------------------------------------------------------- public override NodalCurve calibrate(IList <ResolvedCdsTrade> calibrationCDSs, DoubleArray flactionalSpreads, DoubleArray pointsUpfront, CurveName name, LocalDate valuationDate, CreditDiscountFactors discountFactors, RecoveryRates recoveryRates, ReferenceData refData) { int n = calibrationCDSs.Count; double[] guess = new double[n]; double[] t = new double[n]; double[] lgd = new double[n]; for (int i = 0; i < n; i++) { LocalDate endDate = calibrationCDSs[i].Product.ProtectionEndDate; t[i] = discountFactors.relativeYearFraction(endDate); lgd[i] = 1d - recoveryRates.recoveryRate(endDate); guess[i] = (flactionalSpreads.get(i) + pointsUpfront.get(i) / t[i]) / lgd[i]; } DoubleArray times = DoubleArray.ofUnsafe(t); CurveMetadata baseMetadata = DefaultCurveMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.ZERO_RATE).curveName(name).dayCount(discountFactors.DayCount).build(); NodalCurve creditCurve = n == 1 ? ConstantNodalCurve.of(baseMetadata, t[0], guess[0]) : InterpolatedNodalCurve.of(baseMetadata, times, DoubleArray.ofUnsafe(guess), CurveInterpolators.PRODUCT_LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.PRODUCT_LINEAR); for (int i = 0; i < n; i++) { ResolvedCds cds = calibrationCDSs[i].Product; LocalDate stepinDate = cds.StepinDateOffset.adjust(valuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); LocalDate settlementDate = calibrationCDSs[i].Info.SettlementDate.orElse(cds.SettlementDateOffset.adjust(valuationDate, refData)); double accrued = cds.accruedYearFraction(stepinDate); Pricer pricer = new Pricer(this, cds, discountFactors, times, flactionalSpreads.get(i), pointsUpfront.get(i), lgd[i], stepinDate, effectiveStartDate, settlementDate, accrued); System.Func <double, double> func = pricer.getPointFunction(i, creditCurve); switch (ArbitrageHandling) { case IGNORE: { try { double[] bracket = BRACKETER.getBracketedPoints(func, 0.8 * guess[i], 1.25 * guess[i], double.NegativeInfinity, double.PositiveInfinity); double zeroRate = bracket[0] > bracket[1] ? ROOTFINDER.getRoot(func, bracket[1], bracket[0]) : ROOTFINDER.getRoot(func, bracket[0], bracket[1]); //Negative guess handled creditCurve = creditCurve.withParameter(i, zeroRate); } //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: //ORIGINAL LINE: catch (final com.opengamma.strata.math.MathException e) catch (MathException e) { //handling bracketing failure due to small survival probability if (Math.Abs(func(creditCurve.YValues.get(i - 1))) < 1.e-12) { creditCurve = creditCurve.withParameter(i, creditCurve.YValues.get(i - 1)); } else { throw new MathException(e); } } break; } case FAIL: { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double minValue = i == 0 ? 0d : creditCurve.getYValues().get(i - 1) * creditCurve.getXValues().get(i - 1) / creditCurve.getXValues().get(i); double minValue = i == 0 ? 0d : creditCurve.YValues.get(i - 1) * creditCurve.XValues.get(i - 1) / creditCurve.XValues.get(i); if (i > 0 && func(minValue) > 0.0) { //can never fail on the first spread //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder(); if (pointsUpfront.get(i) == 0.0) { msg.Append("The par spread of " + flactionalSpreads.get(i) + " at index " + i); } else { msg.Append("The premium of " + flactionalSpreads.get(i) + "and points up-front of " + pointsUpfront.get(i) + " at index " + i); } msg.Append(" is an arbitrage; cannot fit a curve with positive forward hazard rate. "); throw new System.ArgumentException(msg.ToString()); } guess[i] = Math.Max(minValue, guess[i]); double[] bracket = BRACKETER.getBracketedPoints(func, guess[i], 1.2 * guess[i], minValue, double.PositiveInfinity); double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]).Value; creditCurve = creditCurve.withParameter(i, zeroRate); break; } case ZERO_HAZARD_RATE: { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double minValue = i == 0 ? 0.0 : creditCurve.getYValues().get(i - 1) * creditCurve.getXValues().get(i - 1) / creditCurve.getXValues().get(i); double minValue = i == 0 ? 0.0 : creditCurve.YValues.get(i - 1) * creditCurve.XValues.get(i - 1) / creditCurve.XValues.get(i); if (i > 0 && func(minValue) > 0.0) { //can never fail on the first spread creditCurve = creditCurve.withParameter(i, minValue); } else { guess[i] = Math.Max(minValue, guess[i]); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double[] bracket = BRACKETER.getBracketedPoints(func, guess[i], 1.2 * guess[i], minValue, Double.POSITIVE_INFINITY); double[] bracket = BRACKETER.getBracketedPoints(func, guess[i], 1.2 * guess[i], minValue, double.PositiveInfinity); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]); double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]).Value; creditCurve = creditCurve.withParameter(i, zeroRate); } break; } default: throw new System.ArgumentException("unknown case " + ArbitrageHandling); } } return(creditCurve); }