private CurrencyParameterSensitivities sensitivityCreidtCurve <T>(ImmutableCreditRatesProvider provider, System.Func <ImmutableCreditRatesProvider, CurrencyAmount> valueFn, MetaProperty <ImmutableMap <T, LegalEntitySurvivalProbabilities> > metaProperty, CurrencyAmount valueInit) { ImmutableMap <T, LegalEntitySurvivalProbabilities> baseCurves = metaProperty.get(provider); CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty(); foreach (T key in baseCurves.Keys) { LegalEntitySurvivalProbabilities credit = baseCurves.get(key); CreditDiscountFactors creditDiscountFactors = credit.SurvivalProbabilities; DiscountFactors discountFactors = creditDiscountFactors.toDiscountFactors(); Curve curve = checkDiscountFactors(discountFactors); int paramCount = curve.ParameterCount; double[] sensitivity = new double[paramCount]; for (int i = 0; i < paramCount; i++) { Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift); IDictionary <T, LegalEntitySurvivalProbabilities> mapBumped = new Dictionary <T, LegalEntitySurvivalProbabilities>(baseCurves); mapBumped[key] = LegalEntitySurvivalProbabilities.of(credit.LegalEntityId, createCreditDiscountFactors(creditDiscountFactors, dscBumped)); ImmutableCreditRatesProvider providerDscBumped = provider.toBuilder().set(metaProperty, mapBumped).build(); sensitivity[i] = (valueFn(providerDscBumped).Amount - valueInit.Amount) / shift; } result = result.combinedWith(curve.createParameterSensitivity(valueInit.Currency, DoubleArray.copyOf(sensitivity))); } return(result); }
private LegalEntitySurvivalProbabilities(StandardId legalEntityId, CreditDiscountFactors survivalProbabilities) { JodaBeanUtils.notNull(legalEntityId, "legalEntityId"); JodaBeanUtils.notNull(survivalProbabilities, "survivalProbabilities"); this.legalEntityId = legalEntityId; this.survivalProbabilities = survivalProbabilities; }
//------------------------------------------------------------------------- private static CreditRatesProvider createCreditRatesProviderSingle(LocalDate valuationDate, bool isSingle) { IsdaCreditDiscountFactors yc = IsdaCreditDiscountFactors.of(USD, valuationDate, NODAL_YC); CreditDiscountFactors cc = isSingle ? IsdaCreditDiscountFactors.of(USD, valuationDate, NODAL_CC_SINGLE) : IsdaCreditDiscountFactors.of(USD, valuationDate, NODAL_CC); ConstantRecoveryRates rr = ConstantRecoveryRates.of(INDEX_ID, valuationDate, RECOVERY_RATE); return(ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).creditCurves(ImmutableMap.of(Pair.of(INDEX_ID, USD), LegalEntitySurvivalProbabilities.of(INDEX_ID, cc))).discountCurves(ImmutableMap.of(USD, yc)).recoveryRateCurves(ImmutableMap.of(INDEX_ID, rr)).build()); }
// return correct instance of CreditDiscountFactors private CreditDiscountFactors createCreditDiscountFactors(CreditDiscountFactors originalDsc, Curve bumpedCurve) { if (originalDsc is IsdaCreditDiscountFactors && bumpedCurve is NodalCurve) { IsdaCreditDiscountFactors isdaDsc = (IsdaCreditDiscountFactors)originalDsc; return(isdaDsc.withCurve((NodalCurve)bumpedCurve)); } throw new System.ArgumentException("Not supported"); }
public CreditDiscountFactors discountFactors(Currency currency) { CreditDiscountFactors discountFactors = discountCurves.get(currency); if (discountFactors == null) { throw new System.ArgumentException("Unable to find discount curve: " + currency); } return(discountFactors); }
public CreditDiscountFactors discountFactors(Currency currency) { CurveId curveId = lookup.DiscountCurveIds.get(currency); if (curveId == null) { throw new MarketDataNotFoundException("Unable to find discount curve: " + currency); } Curve curve = marketData.getValue(curveId); return(CreditDiscountFactors.of(currency, ValuationDate, curve)); }
private Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> reduceDiscountFactors(ResolvedCds cds, CreditRatesProvider ratesProvider) { Currency currency = cds.Currency; CreditDiscountFactors discountFactors = ratesProvider.discountFactors(currency); ArgChecker.isTrue(discountFactors.IsdaCompliant, "discount factors must be IsdaCompliantZeroRateDiscountFactors"); LegalEntitySurvivalProbabilities survivalProbabilities = ratesProvider.survivalProbabilities(cds.LegalEntityId, currency); ArgChecker.isTrue(survivalProbabilities.SurvivalProbabilities.IsdaCompliant, "survival probabilities must be IsdaCompliantZeroRateDiscountFactors"); ArgChecker.isTrue(discountFactors.DayCount.Equals(survivalProbabilities.SurvivalProbabilities.DayCount), "day count conventions of discounting curve and credit curve must be the same"); return(Pair.of(discountFactors, survivalProbabilities)); }
//------------------------------------------------------------------------- public LegalEntitySurvivalProbabilities survivalProbabilities(StandardId legalEntityId, Currency currency) { CurveId curveId = lookup.CreditCurveIds.get(Pair.of(legalEntityId, currency)); if (curveId == null) { throw new MarketDataNotFoundException("Unable to find credit curve: " + legalEntityId + ", " + currency); } Curve curve = marketData.getValue(curveId); CreditDiscountFactors survivalProbabilities = CreditDiscountFactors.of(currency, ValuationDate, curve); return(LegalEntitySurvivalProbabilities.of(legalEntityId, survivalProbabilities)); }
internal virtual Triple <CreditDiscountFactors, LegalEntitySurvivalProbabilities, double> reduceDiscountFactors(ResolvedCds cds, CreditRatesProvider ratesProvider) { Currency currency = cds.Currency; CreditDiscountFactors discountFactors = ratesProvider.discountFactors(currency); ArgChecker.isTrue(discountFactors.IsdaCompliant, "discount factors must be IsdaCompliantZeroRateDiscountFactors"); LegalEntitySurvivalProbabilities survivalProbabilities = ratesProvider.survivalProbabilities(cds.LegalEntityId, currency); ArgChecker.isTrue(survivalProbabilities.SurvivalProbabilities.IsdaCompliant, "survival probabilities must be IsdaCompliantZeroRateDiscountFactors"); ArgChecker.isTrue(discountFactors.DayCount.Equals(survivalProbabilities.SurvivalProbabilities.DayCount), "day count conventions of discounting curve and credit curve must be the same"); double indexFactor = ((IsdaCreditDiscountFactors)survivalProbabilities.SurvivalProbabilities).Curve.Metadata.getInfo(CurveInfoType.CDS_INDEX_FACTOR); return(Triple.of(discountFactors, survivalProbabilities, indexFactor)); }
public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case 866287159: // legalEntityId this.legalEntityId = (StandardId)newValue; break; case -2020275979: // survivalProbabilities this.survivalProbabilities = (CreditDiscountFactors)newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
public virtual void test_of_constant_interface() { IsdaCreditDiscountFactors test = (IsdaCreditDiscountFactors)CreditDiscountFactors.of(USD, VALUATION, CONST_CURVE); assertEquals(test.Currency, USD); assertEquals(test.Curve, CONST_CURVE); assertEquals(test.DayCount, ACT_365L); assertEquals(test.ParameterCount, 1); assertEquals(test.getParameter(0), RATE_SINGLE); assertEquals(test.ParameterKeys, DoubleArray.of(TIME_SINGLE)); assertEquals(test.getParameterMetadata(0), SimpleCurveParameterMetadata.of(METADATA.XValueType, TIME_SINGLE)); assertEquals(test.ValuationDate, VALUATION); assertEquals(test.findData(CONST_CURVE.Name), CONST_CURVE); assertEquals(test.findData(CurveName.of("Rubbish")), null); assertEquals(test.toDiscountFactors(), ZeroRateDiscountFactors.of(USD, VALUATION, CONST_CURVE)); assertEquals(test.IsdaCompliant, true); }
// extract CDS index trades from credit curve private ImmutableList <ResolvedCdsIndexTrade> getBucketCdsIndex(ResolvedCdsIndex product, CreditRatesProvider ratesProvider) { CreditDiscountFactors creditCurve = ratesProvider.survivalProbabilities(product.CdsIndexId, product.Currency).SurvivalProbabilities; int nNodes = creditCurve.ParameterCount; ImmutableList.Builder <ResolvedCdsIndexTrade> builder = ImmutableList.builder(); for (int i = 0; i < nNodes; ++i) { ParameterMetadata metadata = creditCurve.getParameterMetadata(i); ArgChecker.isTrue(metadata is ResolvedTradeParameterMetadata, "ParameterMetadata of credit curve must be ResolvedTradeParameterMetadata"); ResolvedTradeParameterMetadata tradeMetadata = (ResolvedTradeParameterMetadata)metadata; ResolvedTrade trade = tradeMetadata.Trade; ArgChecker.isTrue(trade is ResolvedCdsIndexTrade, "ResolvedTrade must be ResolvedCdsIndexTrade"); builder.add((ResolvedCdsIndexTrade)trade); } return(builder.build()); }
//------------------------------------------------------------------------- public ImmutableCreditRatesProvider toImmutableCreditRatesProvider() { LocalDate valuationDate = ValuationDate; // credit curves IDictionary <Pair <StandardId, Currency>, LegalEntitySurvivalProbabilities> creditCurves = new Dictionary <Pair <StandardId, Currency>, LegalEntitySurvivalProbabilities>(); foreach (Pair <StandardId, Currency> pair in lookup.CreditCurveIds.Keys) { CurveId curveId = lookup.CreditCurveIds.get(pair); if (marketData.containsValue(curveId)) { Curve curve = marketData.getValue(curveId); CreditDiscountFactors survivalProbabilities = CreditDiscountFactors.of(pair.Second, valuationDate, curve); creditCurves[pair] = LegalEntitySurvivalProbabilities.of(pair.First, survivalProbabilities); } } // discount curves IDictionary <Currency, CreditDiscountFactors> discountCurves = new Dictionary <Currency, CreditDiscountFactors>(); foreach (Currency currency in lookup.DiscountCurveIds.Keys) { CurveId curveId = lookup.DiscountCurveIds.get(currency); if (marketData.containsValue(curveId)) { Curve curve = marketData.getValue(curveId); discountCurves[currency] = CreditDiscountFactors.of(currency, valuationDate, curve); } } // recovery rate curves IDictionary <StandardId, RecoveryRates> recoveryRateCurves = new Dictionary <StandardId, RecoveryRates>(); foreach (StandardId legalEntityId in lookup.RecoveryRateCurveIds.Keys) { CurveId curveId = lookup.RecoveryRateCurveIds.get(legalEntityId); if (marketData.containsValue(curveId)) { Curve curve = marketData.getValue(curveId); RecoveryRates recoveryRate = RecoveryRates.of(legalEntityId, valuationDate, curve); recoveryRateCurves[legalEntityId] = recoveryRate; } } // build result return(ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).creditCurves(creditCurves).discountCurves(discountCurves).recoveryRateCurves(recoveryRateCurves).build()); }
public CurrencyParameterSensitivity singleDiscountCurveParameterSensitivity(PointSensitivities pointSensitivities, Currency currency) { CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty(); foreach (PointSensitivity point in pointSensitivities.Sensitivities) { if (point is ZeroRateSensitivity) { ZeroRateSensitivity pt = (ZeroRateSensitivity)point; if (pt.Currency.Equals(currency)) { CreditDiscountFactors factors = discountFactors(pt.CurveCurrency); sens = sens.combinedWith(factors.parameterSensitivity(pt)); } } } ArgChecker.isTrue(sens.size() == 1, "sensitivity must be unique"); return(sens.Sensitivities.get(0)); }
public virtual void test_of_interface() { IsdaCreditDiscountFactors test = (IsdaCreditDiscountFactors)CreditDiscountFactors.of(USD, VALUATION, CURVE); assertEquals(test.Currency, USD); assertEquals(test.Curve, CURVE); assertEquals(test.DayCount, ACT_365F); assertEquals(test.ParameterCount, RATE.size()); assertEquals(test.getParameter(3), RATE.get(3)); assertEquals(test.getParameter(1), RATE.get(1)); assertEquals(test.ParameterKeys, TIME); assertEquals(test.getParameterMetadata(4), SimpleCurveParameterMetadata.of(METADATA.XValueType, TIME.get(4))); assertEquals(test.getParameterMetadata(6), SimpleCurveParameterMetadata.of(METADATA.XValueType, TIME.get(6))); assertEquals(test.ValuationDate, VALUATION); assertEquals(test.findData(CURVE.Name), CURVE); assertEquals(test.findData(CurveName.of("Rubbish")), null); assertEquals(test.toDiscountFactors(), ZeroRateDiscountFactors.of(USD, VALUATION, CURVE)); assertEquals(test.IsdaCompliant, true); }
//------------------------------------------------------------------------- public CurrencyParameterSensitivities parameterSensitivity(PointSensitivities pointSensitivities) { CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty(); foreach (PointSensitivity point in pointSensitivities.Sensitivities) { if (point is CreditCurveZeroRateSensitivity) { CreditCurveZeroRateSensitivity pt = (CreditCurveZeroRateSensitivity)point; LegalEntitySurvivalProbabilities factors = survivalProbabilities(pt.LegalEntityId, pt.CurveCurrency); sens = sens.combinedWith(factors.parameterSensitivity(pt)); } else if (point is ZeroRateSensitivity) { ZeroRateSensitivity pt = (ZeroRateSensitivity)point; CreditDiscountFactors factors = discountFactors(pt.CurveCurrency); sens = sens.combinedWith(factors.parameterSensitivity(pt)); } } return(sens); }
/// <summary> /// The par spread quotes are converted to points upfronts or quoted spreads. /// <para> /// The relevant discount curve and recovery rate curve must be stored in {@code ratesProvider}. /// The credit curve is internally calibrated to par spread values. /// </para> /// <para> /// {@code trades} must be sorted in ascending order in maturity and coherent to {@code quotes}. /// </para> /// <para> /// The resultant quote is specified by {@code targetConvention}. /// /// </para> /// </summary> /// <param name="trades"> the trades </param> /// <param name="quotes"> the quotes </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="targetConvention"> the target convention </param> /// <param name="refData"> the reference data </param> /// <returns> the quotes </returns> public virtual IList <CdsQuote> quotesFromParSpread(IList <ResolvedCdsTrade> trades, IList <CdsQuote> quotes, CreditRatesProvider ratesProvider, CdsQuoteConvention targetConvention, ReferenceData refData) { ArgChecker.noNulls(trades, "trades"); ArgChecker.noNulls(quotes, "quotes"); ArgChecker.notNull(ratesProvider, "ratesProvider"); ArgChecker.notNull(targetConvention, "targetConvention"); ArgChecker.notNull(refData, "refData"); int nNodes = trades.Count; ArgChecker.isTrue(quotes.Count == nNodes, "trades and quotes must be the same size"); quotes.ForEach(q => ArgChecker.isTrue(q.QuoteConvention.Equals(CdsQuoteConvention.PAR_SPREAD), "quote must be par spread")); //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: IEnumerator <StandardId> legalEntities = trades.Select(t => t.Product.LegalEntityId).collect(Collectors.toSet()).GetEnumerator(); //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: StandardId legalEntityId = legalEntities.next(); //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: ArgChecker.isFalse(legalEntities.hasNext(), "legal entity must be common to trades"); //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: IEnumerator <Currency> currencies = trades.Select(t => t.Product.Currency).collect(Collectors.toSet()).GetEnumerator(); //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: Currency currency = currencies.next(); //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: ArgChecker.isFalse(currencies.hasNext(), "currency must be common to trades"); LocalDate valuationDate = ratesProvider.ValuationDate; CreditDiscountFactors discountFactors = ratesProvider.discountFactors(currency); RecoveryRates recoveryRates = ratesProvider.recoveryRates(legalEntityId); NodalCurve creditCurve = calibrator.calibrate(trades, DoubleArray.of(nNodes, q => quotes[q].QuotedValue), DoubleArray.filled(nNodes), CurveName.of("temp"), valuationDate, discountFactors, recoveryRates, refData); CreditRatesProvider ratesProviderNew = ratesProvider.toImmutableCreditRatesProvider().toBuilder().creditCurves(ImmutableMap.of(Pair.of(legalEntityId, currency), LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurve)))).build(); System.Func <ResolvedCdsTrade, CdsQuote> quoteValueFunction = createQuoteValueFunction(ratesProviderNew, targetConvention, refData); //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: ImmutableList <CdsQuote> result = trades.Select(c => quoteValueFunction(c)).collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList.copyOf)); return(result); }
// computes protection leg pv per unit notional, without loss-given-default rate multiplied internal virtual double protectionFull(ResolvedCds cds, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities, LocalDate referenceDate, LocalDate effectiveStartDate) { DoubleArray integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(discountFactors.relativeYearFraction(effectiveStartDate), discountFactors.relativeYearFraction(cds.ProtectionEndDate), discountFactors.ParameterKeys, survivalProbabilities.ParameterKeys); double pv = 0d; double ht0 = survivalProbabilities.zeroRate(integrationSchedule.get(0)) * integrationSchedule.get(0); double rt0 = discountFactors.zeroRate(integrationSchedule.get(0)) * integrationSchedule.get(0); double b0 = Math.Exp(-ht0 - rt0); int n = integrationSchedule.size(); for (int i = 1; i < n; ++i) { double ht1 = survivalProbabilities.zeroRate(integrationSchedule.get(i)) * integrationSchedule.get(i); double rt1 = discountFactors.zeroRate(integrationSchedule.get(i)) * integrationSchedule.get(i); double b1 = Math.Exp(-ht1 - rt1); double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; // The formula has been modified from ISDA (but is equivalent) to avoid log(exp(x)) and explicitly // calculating the time step - it also handles the limit double dPV = 0d; if (Math.Abs(dhrt) < SMALL) { dPV = dht * b0 * epsilon(-dhrt); } else { dPV = (b0 - b1) * dht / dhrt; } pv += dPV; ht0 = ht1; rt0 = rt1; b0 = b1; } // roll to the cash settle date double df = discountFactors.discountFactor(referenceDate); return(pv / df); }
// computes risky annuity internal virtual double riskyAnnuity(ResolvedCds cds, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities, LocalDate referenceDate, LocalDate stepinDate, LocalDate effectiveStartDate, PriceType priceType) { double pv = 0d; foreach (CreditCouponPaymentPeriod coupon in cds.PaymentPeriods) { if (stepinDate.isBefore(coupon.EndDate)) { double q = survivalProbabilities.survivalProbability(coupon.EffectiveEndDate); double p = discountFactors.discountFactor(coupon.PaymentDate); pv += coupon.YearFraction * p * q; } } if (cds.PaymentOnDefault.AccruedInterest) { // This is needed so that the code is consistent with ISDA C when the Markit `fix' is used. LocalDate start = cds.PaymentPeriods.size() == 1 ? effectiveStartDate : cds.AccrualStartDate; DoubleArray integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(discountFactors.relativeYearFraction(start), discountFactors.relativeYearFraction(cds.ProtectionEndDate), discountFactors.ParameterKeys, survivalProbabilities.ParameterKeys); foreach (CreditCouponPaymentPeriod coupon in cds.PaymentPeriods) { pv += singlePeriodAccrualOnDefault(coupon, effectiveStartDate, integrationSchedule, discountFactors, survivalProbabilities); } } // roll to the cash settle date double df = discountFactors.discountFactor(referenceDate); pv /= df; if (priceType.CleanPrice) { pv -= cds.accruedYearFraction(stepinDate); } return(pv); }
//------------------------------------------------------------------------- /// <summary> /// Creates an instance. /// </summary> /// <param name="legalEntityId"> the legal entity ID </param> /// <param name="survivalProbabilities"> the survival probabilities </param> /// <returns> the instance </returns> public static LegalEntitySurvivalProbabilities of(StandardId legalEntityId, CreditDiscountFactors survivalProbabilities) { return(new LegalEntitySurvivalProbabilities(legalEntityId, survivalProbabilities)); }
//------------------------------------------------------------------------- // computes protection leg pv per unit notional private double protectionLeg(ResolvedCds cds, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities, LocalDate referenceDate, LocalDate effectiveStartDate, double recoveryRate) { double protectionFull = this.protectionFull(cds, discountFactors, survivalProbabilities, referenceDate, effectiveStartDate); return((1d - recoveryRate) * protectionFull); }
internal virtual PointSensitivityBuilder riskyAnnuitySensitivity(ResolvedCds cds, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities, LocalDate referenceDate, LocalDate stepinDate, LocalDate effectiveStartDate) { double pv = 0d; PointSensitivityBuilder pvSensi = PointSensitivityBuilder.none(); foreach (CreditCouponPaymentPeriod coupon in cds.PaymentPeriods) { if (stepinDate.isBefore(coupon.EndDate)) { double q = survivalProbabilities.survivalProbability(coupon.EffectiveEndDate); PointSensitivityBuilder qSensi = survivalProbabilities.zeroRatePointSensitivity(coupon.EffectiveEndDate); double p = discountFactors.discountFactor(coupon.PaymentDate); PointSensitivityBuilder pSensi = discountFactors.zeroRatePointSensitivity(coupon.PaymentDate); pv += coupon.YearFraction * p * q; pvSensi = pvSensi.combinedWith(pSensi.multipliedBy(coupon.YearFraction * q).combinedWith(qSensi.multipliedBy(coupon.YearFraction * p))); } } if (cds.PaymentOnDefault.AccruedInterest) { // This is needed so that the code is consistent with ISDA C when the Markit `fix' is used. LocalDate start = cds.PaymentPeriods.size() == 1 ? effectiveStartDate : cds.AccrualStartDate; DoubleArray integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(discountFactors.relativeYearFraction(start), discountFactors.relativeYearFraction(cds.ProtectionEndDate), discountFactors.ParameterKeys, survivalProbabilities.ParameterKeys); foreach (CreditCouponPaymentPeriod coupon in cds.PaymentPeriods) { Pair <double, PointSensitivityBuilder> pvAndSensi = singlePeriodAccrualOnDefaultSensitivity(coupon, effectiveStartDate, integrationSchedule, discountFactors, survivalProbabilities); pv += pvAndSensi.First; pvSensi = pvSensi.combinedWith(pvAndSensi.Second); } } double df = discountFactors.discountFactor(referenceDate); PointSensitivityBuilder dfSensi = discountFactors.zeroRatePointSensitivity(referenceDate).multipliedBy(-pv / (df * df)); pvSensi = pvSensi.multipliedBy(1d / df); return(dfSensi.combinedWith(pvSensi)); }
// computes accrual-on-default pv per unit notional for a single payment period private double singlePeriodAccrualOnDefault(CreditCouponPaymentPeriod coupon, LocalDate effectiveStartDate, DoubleArray integrationSchedule, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities) { LocalDate start = coupon.EffectiveStartDate.isBefore(effectiveStartDate) ? effectiveStartDate : coupon.EffectiveStartDate; if (!start.isBefore(coupon.EffectiveEndDate)) { return(0d); // this coupon has already expired } DoubleArray knots = DoublesScheduleGenerator.truncateSetInclusive(discountFactors.relativeYearFraction(start), discountFactors.relativeYearFraction(coupon.EffectiveEndDate), integrationSchedule); double t0Knot = knots.get(0); double ht0 = survivalProbabilities.zeroRate(t0Knot) * t0Knot; double rt0 = discountFactors.zeroRate(t0Knot) * t0Knot; double b0 = Math.Exp(-rt0 - ht0); double effStart = discountFactors.relativeYearFraction(coupon.EffectiveStartDate); double t0 = t0Knot - effStart + omega; double pv = 0d; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int nItems = knots.size(); int nItems = knots.size(); for (int j = 1; j < nItems; ++j) { double t = knots.get(j); double ht1 = survivalProbabilities.zeroRate(t) * t; double rt1 = discountFactors.zeroRate(t) * t; double b1 = Math.Exp(-rt1 - ht1); double dt = knots.get(j) - knots.get(j - 1); double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; double tPV; if (formula == AccrualOnDefaultFormula.MARKIT_FIX) { if (Math.Abs(dhrt) < SMALL) { tPV = dht * dt * b0 * Epsilon.epsilonP(-dhrt); } else { tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); } } else { double t1 = t - effStart + omega; if (Math.Abs(dhrt) < SMALL) { tPV = dht * b0 * (t0 * epsilon(-dhrt) + dt * Epsilon.epsilonP(-dhrt)); } else { tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1)); } t0 = t1; } pv += tPV; ht0 = ht1; rt0 = rt1; b0 = b1; } double yearFractionCurve = discountFactors.DayCount.relativeYearFraction(coupon.StartDate, coupon.EndDate); return(coupon.YearFraction * pv / yearFractionCurve); }
//------------------------------------------------------------------------- internal virtual PointSensitivityBuilder protectionLegSensitivity(ResolvedCds cds, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities, LocalDate referenceDate, LocalDate effectiveStartDate, double recoveryRate) { DoubleArray integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(discountFactors.relativeYearFraction(effectiveStartDate), discountFactors.relativeYearFraction(cds.ProtectionEndDate), discountFactors.ParameterKeys, survivalProbabilities.ParameterKeys); int n = integrationSchedule.size(); double[] dht = new double[n - 1]; double[] drt = new double[n - 1]; double[] dhrt = new double[n - 1]; double[] p = new double[n]; double[] q = new double[n]; // pv double pv = 0d; double ht0 = survivalProbabilities.zeroRate(integrationSchedule.get(0)) * integrationSchedule.get(0); double rt0 = discountFactors.zeroRate(integrationSchedule.get(0)) * integrationSchedule.get(0); p[0] = Math.Exp(-rt0); q[0] = Math.Exp(-ht0); double b0 = p[0] * q[0]; for (int i = 1; i < n; ++i) { double ht1 = survivalProbabilities.zeroRate(integrationSchedule.get(i)) * integrationSchedule.get(i); double rt1 = discountFactors.zeroRate(integrationSchedule.get(i)) * integrationSchedule.get(i); p[i] = Math.Exp(-rt1); q[i] = Math.Exp(-ht1); double b1 = p[i] * q[i]; dht[i - 1] = ht1 - ht0; drt[i - 1] = rt1 - rt0; dhrt[i - 1] = dht[i - 1] + drt[i - 1]; double dPv = 0d; if (Math.Abs(dhrt[i - 1]) < SMALL) { double eps = epsilon(-dhrt[i - 1]); dPv = dht[i - 1] * b0 * eps; } else { dPv = (b0 - b1) * dht[i - 1] / dhrt[i - 1]; } pv += dPv; ht0 = ht1; rt0 = rt1; b0 = b1; } double df = discountFactors.discountFactor(referenceDate); // pv sensitivity double factor = (1d - recoveryRate) / df; double eps0 = computeExtendedEpsilon(-dhrt[0], p[1], q[1], p[0], q[0]); PointSensitivityBuilder pvSensi = discountFactors.zeroRatePointSensitivity(integrationSchedule.get(0)).multipliedBy(-dht[0] * q[0] * eps0 * factor); pvSensi = pvSensi.combinedWith(survivalProbabilities.zeroRatePointSensitivity(integrationSchedule.get(0)).multipliedBy(factor * (drt[0] * p[0] * eps0 + p[0]))); for (int i = 1; i < n - 1; ++i) { double epsp = computeExtendedEpsilon(-dhrt[i], p[i + 1], q[i + 1], p[i], q[i]); double epsm = computeExtendedEpsilon(dhrt[i - 1], p[i - 1], q[i - 1], p[i], q[i]); PointSensitivityBuilder pSensi = discountFactors.zeroRatePointSensitivity(integrationSchedule.get(i)).multipliedBy(factor * (-dht[i] * q[i] * epsp - dht[i - 1] * q[i] * epsm)); PointSensitivityBuilder qSensi = survivalProbabilities.zeroRatePointSensitivity(integrationSchedule.get(i)).multipliedBy(factor * (drt[i - 1] * p[i] * epsm + drt[i] * p[i] * epsp)); pvSensi = pvSensi.combinedWith(pSensi).combinedWith(qSensi); } if (n > 1) { double epsLast = computeExtendedEpsilon(dhrt[n - 2], p[n - 2], q[n - 2], p[n - 1], q[n - 1]); pvSensi = pvSensi.combinedWith(discountFactors.zeroRatePointSensitivity(integrationSchedule.get(n - 1)).multipliedBy(-dht[n - 2] * q[n - 1] * epsLast * factor)); pvSensi = pvSensi.combinedWith(survivalProbabilities.zeroRatePointSensitivity(integrationSchedule.get(n - 1)).multipliedBy(factor * (drt[n - 2] * p[n - 1] * epsLast - p[n - 1]))); } PointSensitivityBuilder dfSensi = discountFactors.zeroRatePointSensitivity(referenceDate).multipliedBy(-pv * factor / df); return(dfSensi.combinedWith(pvSensi)); }
private System.Func <double, double> getPriceFunction(int index, ResolvedCdsTrade cds, double flactionalSpread, double pointsUpfront, LocalDate valuationDate, NodalCurve creditCurve, CreditDiscountFactors discountFactors, RecoveryRates recoveryRates, ReferenceData refData) { ResolvedCds cdsProduct = cds.Product; Currency currency = cdsProduct.Currency; StandardId legalEntityId = cdsProduct.LegalEntityId; Pair <StandardId, Currency> pair = Pair.of(legalEntityId, currency); ImmutableCreditRatesProvider ratesbase = ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).discountCurves(ImmutableMap.of(currency, discountFactors)).recoveryRateCurves(ImmutableMap.of(legalEntityId, recoveryRates)).build(); System.Func <double, double> func = (double?x) => { NodalCurve tempCreditCurve = creditCurve.withParameter(index, x.Value); ImmutableCreditRatesProvider rates = ratesbase.toBuilder().creditCurves(ImmutableMap.of(pair, LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, tempCreditCurve)))).build(); double price = TradePricer.price(cds, rates, flactionalSpread, PriceType.CLEAN, refData); return(price - pointsUpfront); }; return(func); }
//------------------------------------------------------------------------- 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); }
public Pricer(FastCreditCurveCalibrator outerInstance, ResolvedCds nodeCds, CreditDiscountFactors yieldCurve, DoubleArray creditCurveKnots, double fractionalSpread, double pointsUpfront, double lgd, LocalDate stepinDate, LocalDate effectiveStartDate, LocalDate settlementDate, double accruedYearFraction) { this.outerInstance = outerInstance; accYearFraction = accruedYearFraction; cds = nodeCds; fracSpread = fractionalSpread; puf = pointsUpfront; productEffectiveStart = yieldCurve.relativeYearFraction(effectiveStartDate); double protectionEnd = yieldCurve.relativeYearFraction(cds.ProtectionEndDate); // protection leg proLegIntPoints = DoublesScheduleGenerator.getIntegrationsPoints(productEffectiveStart, protectionEnd, yieldCurve.ParameterKeys, creditCurveKnots).toArray(); nProPoints = proLegIntPoints.Length; valuationDF = yieldCurve.discountFactor(settlementDate); lgdDF = lgd / valuationDF; proYieldCurveRT = new double[nProPoints]; proDF = new double[nProPoints]; for (int i = 0; i < nProPoints; i++) { proYieldCurveRT[i] = yieldCurve.zeroRate(proLegIntPoints[i]) * proLegIntPoints[i]; proDF[i] = Math.Exp(-proYieldCurveRT[i]); } // premium leg nPayments = cds.PaymentPeriods.size(); paymentDF = new double[nPayments]; int indexTmp = -1; for (int i = 0; i < nPayments; i++) { if (stepinDate.isBefore(cds.PaymentPeriods.get(i).EndDate)) { paymentDF[i] = yieldCurve.discountFactor(cds.PaymentPeriods.get(i).PaymentDate); } else { indexTmp = i; } } startPeriodIndex = indexTmp + 1; // accrual on default if (cds.PaymentOnDefault.AccruedInterest) { LocalDate tmp = nPayments == 1 ? effectiveStartDate : cds.AccrualStartDate; DoubleArray integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(yieldCurve.relativeYearFraction(tmp), protectionEnd, yieldCurve.ParameterKeys, creditCurveKnots); accRate = new double[nPayments]; offsetAccStart = new double[nPayments]; offsetAccEnd = new double[nPayments]; premLegIntPoints = new double[nPayments][]; premDF = new double[nPayments][]; rt = new double[nPayments][]; premDt = new double[nPayments][]; for (int i = startPeriodIndex; i < nPayments; i++) { CreditCouponPaymentPeriod coupon = cds.PaymentPeriods.get(i); offsetAccStart[i] = yieldCurve.relativeYearFraction(coupon.EffectiveStartDate); offsetAccEnd[i] = yieldCurve.relativeYearFraction(coupon.EffectiveEndDate); accRate[i] = coupon.YearFraction / yieldCurve.DayCount.relativeYearFraction(coupon.StartDate, coupon.EndDate); double start = Math.Max(productEffectiveStart, offsetAccStart[i]); if (start >= offsetAccEnd[i]) { continue; } premLegIntPoints[i] = DoublesScheduleGenerator.truncateSetInclusive(start, offsetAccEnd[i], integrationSchedule).toArray(); int n = premLegIntPoints[i].Length; rt[i] = new double[n]; premDF[i] = new double[n]; for (int k = 0; k < n; k++) { rt[i][k] = yieldCurve.zeroRate(premLegIntPoints[i][k]) * premLegIntPoints[i][k]; premDF[i][k] = Math.Exp(-rt[i][k]); } premDt[i] = new double[n - 1]; for (int k = 1; k < n; k++) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double dt = premLegIntPoints[i][k] - premLegIntPoints[i][k - 1]; double dt = premLegIntPoints[i][k] - premLegIntPoints[i][k - 1]; premDt[i][k - 1] = dt; } } } else { accRate = null; offsetAccStart = null; offsetAccEnd = null; premDF = null; premDt = null; rt = null; premLegIntPoints = null; } }
private Pair <double, PointSensitivityBuilder> singlePeriodAccrualOnDefaultSensitivity(CreditCouponPaymentPeriod coupon, LocalDate effectiveStartDate, DoubleArray integrationSchedule, CreditDiscountFactors discountFactors, LegalEntitySurvivalProbabilities survivalProbabilities) { LocalDate start = coupon.EffectiveStartDate.isBefore(effectiveStartDate) ? effectiveStartDate : coupon.EffectiveStartDate; if (!start.isBefore(coupon.EffectiveEndDate)) { return(Pair.of(0d, PointSensitivityBuilder.none())); //this coupon has already expired } DoubleArray knots = DoublesScheduleGenerator.truncateSetInclusive(discountFactors.relativeYearFraction(start), discountFactors.relativeYearFraction(coupon.EffectiveEndDate), integrationSchedule); // pv double pv = 0d; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int nItems = knots.size(); int nItems = knots.size(); double[] dhrtBar = new double[nItems - 1]; double[] dhtBar = new double[nItems - 1]; double[] bBar = new double[nItems]; double[] p = new double[nItems]; double[] q = new double[nItems]; double t = knots.get(0); double ht0 = survivalProbabilities.zeroRate(t) * t; double rt0 = discountFactors.zeroRate(t) * t; q[0] = Math.Exp(-ht0); p[0] = Math.Exp(-rt0); double b0 = q[0] * p[0]; double effStart = discountFactors.relativeYearFraction(coupon.EffectiveStartDate); double t0 = t - effStart + omega; for (int i = 1; i < nItems; ++i) { t = knots.get(i); double ht1 = survivalProbabilities.zeroRate(t) * t; double rt1 = discountFactors.zeroRate(t) * t; q[i] = Math.Exp(-ht1); p[i] = Math.Exp(-rt1); double b1 = q[i] * p[i]; double dt = knots.get(i) - knots.get(i - 1); double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; double tPv; if (formula == AccrualOnDefaultFormula.MARKIT_FIX) { if (Math.Abs(dhrt) < SMALL) { double eps = epsilonP(-dhrt); tPv = dht * dt * b0 * eps; dhtBar[i - 1] = dt * b0 * eps; dhrtBar[i - 1] = -dht *dt *b0 *epsilonPP(-dhrt); bBar[i - 1] += dht * eps; } else { tPv = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); dhtBar[i - 1] = dt / dhrt * ((b0 - b1) / dhrt - b1); dhrtBar[i - 1] = dht * dt / (dhrt * dhrt) * (b1 - 2d * (b0 - b1) / dhrt); bBar[i - 1] += dht * dt / (dhrt * dhrt); bBar[i] += -dht * dt / dhrt * (1d + 1d / dhrt); } } else { double t1 = t - effStart + omega; if (Math.Abs(dhrt) < SMALL) { double eps = epsilon(-dhrt); double epsp = epsilonP(-dhrt); tPv = dht * b0 * (t0 * eps + dt * epsp); dhtBar[i - 1] = b0 * (t0 * eps + dt * epsp); dhrtBar[i - 1] = -dht * b0 * (t0 * epsp + dt * epsilonPP(-dhrt)); bBar[i - 1] += dht * (t0 * eps + dt * epsp); } else { tPv = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1)); dhtBar[i - 1] = (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1)) / dhrt; dhrtBar[i - 1] = dht / (dhrt * dhrt) * (-2d * dt / dhrt * (b0 - b1) - t0 * b0 + t1 * b1); bBar[i - 1] += dht / dhrt * (t0 + dt / dhrt); bBar[i] += dht / dhrt * (-t1 - dt / dhrt); } t0 = t1; } pv += tPv; ht0 = ht1; rt0 = rt1; b0 = b1; } double yfRatio = coupon.YearFraction / discountFactors.DayCount.relativeYearFraction(coupon.StartDate, coupon.EndDate); // pv sensitivity PointSensitivityBuilder qSensiFirst = survivalProbabilities.zeroRatePointSensitivity(knots.get(0)).multipliedBy(yfRatio * ((dhrtBar[0] + dhtBar[0]) / q[0] + bBar[0] * p[0])); PointSensitivityBuilder pSensiFirst = discountFactors.zeroRatePointSensitivity(knots.get(0)).multipliedBy(yfRatio * (dhrtBar[0] / p[0] + bBar[0] * q[0])); PointSensitivityBuilder pvSensi = pSensiFirst.combinedWith(qSensiFirst); for (int i = 1; i < nItems - 1; ++i) { PointSensitivityBuilder qSensi = survivalProbabilities.zeroRatePointSensitivity(knots.get(i)).multipliedBy(yfRatio * (-(dhrtBar[i - 1] + dhtBar[i - 1]) / q[i] + (dhrtBar[i] + dhtBar[i]) / q[i] + bBar[i] * p[i])); PointSensitivityBuilder pSensi = discountFactors.zeroRatePointSensitivity(knots.get(i)).multipliedBy(yfRatio * (-dhrtBar[i - 1] / p[i] + dhrtBar[i] / p[i] + bBar[i] * q[i])); pvSensi = pvSensi.combinedWith(pSensi).combinedWith(qSensi); } if (nItems > 1) { PointSensitivityBuilder qSensiLast = survivalProbabilities.zeroRatePointSensitivity(knots.get(nItems - 1)).multipliedBy(yfRatio * (-(dhrtBar[nItems - 2] + dhtBar[nItems - 2]) / q[nItems - 1] + bBar[nItems - 1] * p[nItems - 1])); PointSensitivityBuilder pSensiLast = discountFactors.zeroRatePointSensitivity(knots.get(nItems - 1)).multipliedBy(yfRatio * (-dhrtBar[nItems - 2] / p[nItems - 1] + bBar[nItems - 1] * q[nItems - 1])); pvSensi = pvSensi.combinedWith(pSensiLast).combinedWith(qSensiLast); } return(Pair.of(yfRatio * pv, pvSensi)); }
//------------------------------------------------------------------------- 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); }
private double[] getStandardQuoteForm(ResolvedCdsTrade calibrationCds, CdsQuote marketQuote, LocalDate valuationDate, CreditDiscountFactors discountFactors, RecoveryRates recoveryRates, bool computeJacobian, ReferenceData refData) { double[] res = new double[3]; res[2] = 1d; if (marketQuote.QuoteConvention.Equals(CdsQuoteConvention.PAR_SPREAD)) { res[0] = marketQuote.QuotedValue; } else if (marketQuote.QuoteConvention.Equals(CdsQuoteConvention.QUOTED_SPREAD)) { double qSpread = marketQuote.QuotedValue; CurveName curveName = CurveName.of("quoteConvertCurve"); NodalCurve tempCreditCurve = calibrate(ImmutableList.of(calibrationCds), DoubleArray.of(qSpread), DoubleArray.of(0d), curveName, valuationDate, discountFactors, recoveryRates, refData); Currency currency = calibrationCds.Product.Currency; StandardId legalEntityId = calibrationCds.Product.LegalEntityId; ImmutableCreditRatesProvider rates = ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).discountCurves(ImmutableMap.of(currency, discountFactors)).recoveryRateCurves(ImmutableMap.of(legalEntityId, recoveryRates)).creditCurves(ImmutableMap.of(Pair.of(legalEntityId, currency), LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, tempCreditCurve)))).build(); res[0] = calibrationCds.Product.FixedRate; res[1] = tradePricer.price(calibrationCds, rates, PriceType.CLEAN, refData); if (computeJacobian) { CurrencyParameterSensitivities pufSensi = rates.parameterSensitivity(tradePricer.priceSensitivity(calibrationCds, rates, refData)); CurrencyParameterSensitivities spSensi = rates.parameterSensitivity(tradePricer.parSpreadSensitivity(calibrationCds, rates, refData)); res[2] = spSensi.getSensitivity(curveName, currency).Sensitivity.get(0) / pufSensi.getSensitivity(curveName, currency).Sensitivity.get(0); } } else if (marketQuote.QuoteConvention.Equals(CdsQuoteConvention.POINTS_UPFRONT)) { res[0] = calibrationCds.Product.FixedRate; res[1] = marketQuote.QuotedValue; } else { throw new System.ArgumentException("Unknown CDSQuoteConvention type " + marketQuote.GetType()); } return(res); }