public virtual void endedTest() { LocalDate valuationDate = PRODUCT.ProtectionEndDate.plusDays(1); CreditRatesProvider provider = createCreditRatesProviderSingle(valuationDate, false); double price = PRICER.price(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA); assertEquals(price, 0d); CurrencyAmount pv = PRICER.presentValue(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA); assertEquals(pv, CurrencyAmount.zero(USD)); assertThrowsIllegalArg(() => PRICER.parSpread(PRODUCT, provider, SETTLEMENT_STD, REF_DATA)); CurrencyAmount rpv01 = PRICER.rpv01(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA); assertEquals(rpv01, CurrencyAmount.zero(USD)); CurrencyAmount recovery01 = PRICER.recovery01(PRODUCT, provider, SETTLEMENT_STD, REF_DATA); assertEquals(recovery01, CurrencyAmount.zero(USD)); PointSensitivityBuilder sensi = PRICER.presentValueSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA); assertEquals(sensi, PointSensitivityBuilder.none()); PointSensitivityBuilder sensiPrice = PRICER.priceSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA); assertEquals(sensiPrice, PointSensitivityBuilder.none()); assertThrowsIllegalArg(() => PRICER.parSpreadSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA)); JumpToDefault jumpToDefault = PRICER.jumpToDefault(PRODUCT, provider, SETTLEMENT_STD, REF_DATA); assertEquals(jumpToDefault, JumpToDefault.of(USD, ImmutableMap.of(INDEX_ID, 0d))); CurrencyAmount expectedLoss = PRICER.expectedLoss(PRODUCT, provider); assertEquals(expectedLoss, CurrencyAmount.zero(USD)); }
internal override DoubleArray computedBucketedCs01(ResolvedCdsTrade trade, IList <ResolvedCdsTrade> bucketCds, CreditRatesProvider ratesProvider, ReferenceData refData) { checkCdsBucket(trade, bucketCds); ResolvedCds product = trade.Product; Currency currency = product.Currency; StandardId legalEntityId = product.LegalEntityId; LocalDate valuationDate = ratesProvider.ValuationDate; int nBucket = bucketCds.Count; DoubleArray impSp = impliedSpread(bucketCds, ratesProvider, refData); NodalCurve creditCurveBase = Calibrator.calibrate(bucketCds, impSp, DoubleArray.filled(nBucket), CurveName.of("baseImpliedCreditCurve"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); IsdaCreditDiscountFactors df = IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurveBase); CreditRatesProvider ratesProviderBase = ratesProvider.toImmutableCreditRatesProvider().toBuilder().creditCurves(ImmutableMap.of(Pair.of(legalEntityId, currency), LegalEntitySurvivalProbabilities.of(legalEntityId, df))).build(); double[][] res = new double[nBucket][]; PointSensitivities pointPv = Pricer.presentValueOnSettleSensitivity(trade, ratesProviderBase, refData); DoubleArray vLambda = ratesProviderBase.singleCreditCurveParameterSensitivity(pointPv, legalEntityId, currency).Sensitivity; for (int i = 0; i < nBucket; i++) { PointSensitivities pointSp = Pricer.parSpreadSensitivity(bucketCds[i], ratesProviderBase, refData); res[i] = ratesProviderBase.singleCreditCurveParameterSensitivity(pointSp, legalEntityId, currency).Sensitivity.toArray(); } DoubleMatrix jacT = MATRIX_ALGEBRA.getTranspose(DoubleMatrix.ofUnsafe(res)); LUDecompositionResult luRes = DECOMPOSITION.apply(jacT); DoubleArray vS = luRes.solve(vLambda); return(vS); }
internal override DoubleArray computedBucketedCs01(ResolvedCdsTrade trade, IList <ResolvedCdsTrade> bucketCds, CreditRatesProvider ratesProvider, ReferenceData refData) { checkCdsBucket(trade, bucketCds); ResolvedCds product = trade.Product; Currency currency = product.Currency; StandardId legalEntityId = product.LegalEntityId; LocalDate valuationDate = ratesProvider.ValuationDate; ImmutableCreditRatesProvider immutableRatesProvider = ratesProvider.toImmutableCreditRatesProvider(); int nBucket = bucketCds.Count; double[] res = new double[nBucket]; DoubleArray impSp = impliedSpread(bucketCds, ratesProvider, refData); NodalCurve creditCurveBase = Calibrator.calibrate(bucketCds, impSp, DoubleArray.filled(nBucket), CurveName.of("baseImpliedCreditCurve"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); Pair <StandardId, Currency> lePair = Pair.of(legalEntityId, currency); IsdaCreditDiscountFactors df = IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurveBase); CreditRatesProvider ratesProviderBase = immutableRatesProvider.toBuilder().creditCurves(ImmutableMap.of(lePair, LegalEntitySurvivalProbabilities.of(legalEntityId, df))).build(); double pvBase = Pricer.presentValueOnSettle(trade, ratesProviderBase, PriceType.DIRTY, refData).Amount; for (int i = 0; i < nBucket; ++i) { double[] bumpedSp = impSp.toArray(); bumpedSp[i] += bumpAmount; NodalCurve creditCurveBump = Calibrator.calibrate(bucketCds, DoubleArray.ofUnsafe(bumpedSp), DoubleArray.filled(nBucket), CurveName.of("bumpedImpliedCreditCurve"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); IsdaCreditDiscountFactors dfBump = IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurveBump); CreditRatesProvider ratesProviderBump = immutableRatesProvider.toBuilder().creditCurves(ImmutableMap.of(lePair, LegalEntitySurvivalProbabilities.of(legalEntityId, dfBump))).build(); double pvBumped = Pricer.presentValueOnSettle(trade, ratesProviderBump, PriceType.DIRTY, refData).Amount; res[i] = (pvBumped - pvBase) / bumpAmount; } return(DoubleArray.ofUnsafe(res)); }
//------------------------------------------------------------------------- private System.Func <ResolvedCdsTrade, CdsQuote> createQuoteValueFunction(CreditRatesProvider ratesProviderNew, CdsQuoteConvention targetConvention, ReferenceData refData) { System.Func <ResolvedCdsTrade, CdsQuote> quoteValueFunction; if (targetConvention.Equals(CdsQuoteConvention.POINTS_UPFRONT)) { quoteValueFunction = (ResolvedCdsTrade x) => { double puf = pointsUpfront(x, ratesProviderNew, refData); return(CdsQuote.of(targetConvention, puf)); }; } else if (targetConvention.Equals(CdsQuoteConvention.QUOTED_SPREAD)) { quoteValueFunction = (ResolvedCdsTrade x) => { double puf = pointsUpfront(x, ratesProviderNew, refData); return(quotedSpreadFromPointsUpfront(x, CdsQuote.of(CdsQuoteConvention.POINTS_UPFRONT, puf), ratesProviderNew, refData)); }; } else { throw new System.ArgumentException("unsuported CDS quote convention"); } return(quoteValueFunction); }
//------------------------------------------------------------------------- public override CurrencyAmount parallelCs01(ResolvedCdsTrade trade, IList <ResolvedCdsTrade> bucketCds, CreditRatesProvider ratesProvider, ReferenceData refData) { checkCdsBucket(trade, bucketCds); ResolvedCds product = trade.Product; Currency currency = product.Currency; StandardId legalEntityId = product.LegalEntityId; LocalDate valuationDate = ratesProvider.ValuationDate; ImmutableCreditRatesProvider immutableRatesProvider = ratesProvider.toImmutableCreditRatesProvider(); int nBucket = bucketCds.Count; DoubleArray impSp = impliedSpread(bucketCds, ratesProvider, refData); NodalCurve creditCurveBase = Calibrator.calibrate(bucketCds, impSp, DoubleArray.filled(nBucket), CurveName.of("baseImpliedCreditCurve"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); Pair <StandardId, Currency> lePair = Pair.of(legalEntityId, currency); IsdaCreditDiscountFactors df = IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurveBase); CreditRatesProvider ratesProviderBase = immutableRatesProvider.toBuilder().creditCurves(ImmutableMap.of(lePair, LegalEntitySurvivalProbabilities.of(legalEntityId, df))).build(); CurrencyAmount pvBase = Pricer.presentValueOnSettle(trade, ratesProviderBase, PriceType.DIRTY, refData); DoubleArray bumpedSp = DoubleArray.of(nBucket, i => impSp.get(i) + bumpAmount); NodalCurve creditCurveBump = Calibrator.calibrate(bucketCds, bumpedSp, DoubleArray.filled(nBucket), CurveName.of("bumpedImpliedCreditCurve"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); IsdaCreditDiscountFactors dfBump = IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurveBump); CreditRatesProvider ratesProviderBump = immutableRatesProvider.toBuilder().creditCurves(ImmutableMap.of(lePair, LegalEntitySurvivalProbabilities.of(legalEntityId, dfBump))).build(); CurrencyAmount pvBumped = Pricer.presentValueOnSettle(trade, ratesProviderBump, PriceType.DIRTY, refData); return(CurrencyAmount.of(currency, (pvBumped.Amount - pvBase.Amount) / bumpAmount)); }
internal virtual double recoveryRate(ResolvedCds cds, CreditRatesProvider ratesProvider) { RecoveryRates recoveryRates = ratesProvider.recoveryRates(cds.LegalEntityId); ArgChecker.isTrue(recoveryRates is ConstantRecoveryRates, "recoveryRates must be ConstantRecoveryRates"); return(recoveryRates.recoveryRate(cds.ProtectionEndDate)); }
private double getIndexFactor(ResolvedCds cds, CreditRatesProvider ratesProvider) { LegalEntitySurvivalProbabilities survivalProbabilities = ratesProvider.survivalProbabilities(cds.LegalEntityId, cds.Currency); // instance is checked in pricer double indexFactor = ((IsdaCreditDiscountFactors)survivalProbabilities.SurvivalProbabilities).Curve.Metadata.getInfo(CurveInfoType.CDS_INDEX_FACTOR); return(indexFactor); }
//------------------------------------------------------------------------- /// <summary> /// Computes the first order sensitivities of a function of a {@code CreditRatesProvider} to a double by finite difference. /// <para> /// The finite difference is computed by forward type. /// The function should return a value in the same currency for any rates provider of {@code CreditRatesProvider}. /// /// </para> /// </summary> /// <param name="provider"> the rates provider </param> /// <param name="valueFn"> the function from a rate provider to a currency amount for which the sensitivity should be computed </param> /// <returns> the curve sensitivity </returns> public virtual CurrencyParameterSensitivities sensitivity(CreditRatesProvider provider, System.Func <ImmutableCreditRatesProvider, CurrencyAmount> valueFn) { ImmutableCreditRatesProvider immutableProvider = provider.toImmutableCreditRatesProvider(); CurrencyAmount valueInit = valueFn(immutableProvider); CurrencyParameterSensitivities discounting = sensitivityDiscountCurve(immutableProvider, valueFn, ImmutableCreditRatesProvider.meta().discountCurves(), valueInit); CurrencyParameterSensitivities credit = sensitivityCreidtCurve(immutableProvider, valueFn, ImmutableCreditRatesProvider.meta().creditCurves(), valueInit); return(discounting.combinedWith(credit)); }
public virtual void test_singleDiscountCurveParameterSensitivity() { ZeroRateSensitivity zeroPt = ZeroRateSensitivity.of(USD, 10d, 5d); CreditCurveZeroRateSensitivity creditPt = CreditCurveZeroRateSensitivity.of(LEGAL_ENTITY_ABC, JPY, 2d, 3d); FxForwardSensitivity fxPt = FxForwardSensitivity.of(CurrencyPair.of(JPY, USD), USD, LocalDate.of(2017, 2, 14), 15d); CreditRatesProvider test = ImmutableCreditRatesProvider.builder().creditCurves(ImmutableMap.of(Pair.of(LEGAL_ENTITY_ABC, USD), LegalEntitySurvivalProbabilities.of(LEGAL_ENTITY_ABC, CRD_ABC_USD), Pair.of(LEGAL_ENTITY_ABC, JPY), LegalEntitySurvivalProbabilities.of(LEGAL_ENTITY_ABC, CRD_ABC_JPY), Pair.of(LEGAL_ENTITY_DEF, JPY), LegalEntitySurvivalProbabilities.of(LEGAL_ENTITY_DEF, CRD_DEF))).discountCurves(ImmutableMap.of(USD, DSC_USD, JPY, DSC_JPY)).recoveryRateCurves(ImmutableMap.of(LEGAL_ENTITY_ABC, RR_ABC, LEGAL_ENTITY_DEF, RR_DEF)).valuationDate(VALUATION).build(); CurrencyParameterSensitivities computed = CurrencyParameterSensitivities.of(test.singleDiscountCurveParameterSensitivity(zeroPt.combinedWith(creditPt).combinedWith(fxPt).build(), USD)); CurrencyParameterSensitivities expected = DSC_USD.parameterSensitivity(zeroPt); assertTrue(computed.equalWithTolerance(expected, 1.0e-14)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the risky annuity, which is RPV01 per unit notional. /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="priceType"> the price type </param> /// <param name="refData"> the reference data </param> /// <returns> the risky annuity </returns> public virtual double riskyAnnuity(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, PriceType priceType, ReferenceData refData) { if (isExpired(cds, ratesProvider)) { return(0d); } LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); return(riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, priceType)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the par spread of the CDS product. /// <para> /// The par spread is a coupon rate such that the clean PV is 0. /// The result is represented in decimal form. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the par spread </returns> public virtual double parSpread(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { ArgChecker.isTrue(cds.ProtectionEndDate.isAfter(ratesProvider.ValuationDate), "CDS already expired"); LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double protectionLeg = this.protectionLeg(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate); double riskyAnnuity = this.riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, PriceType.CLEAN); return(protectionLeg / riskyAnnuity); }
/// <summary> /// Calculates the expected loss of the CDS product. /// <para> /// The expected loss is the (undiscounted) expected default settlement value paid by the protection seller. /// The resulting value is always positive. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <returns> the expected loss </returns> public virtual CurrencyAmount expectedLoss(ResolvedCds cds, CreditRatesProvider ratesProvider) { if (isExpired(cds, ratesProvider)) { return(CurrencyAmount.of(cds.Currency, 0d)); } double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double survivalProbability = rates.Second.survivalProbability(cds.ProtectionEndDate); double el = (1d - recoveryRate) * (1d - survivalProbability); return(CurrencyAmount.of(cds.Currency, Math.Abs(cds.Notional) * el)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the trade. /// <para> /// The present value of the product is based on the valuation date. /// </para> /// <para> /// This method can calculate the clean or dirty present value, see <seealso cref="PriceType"/>. /// If calculating the clean value, the accrued interest is calculated based on the step-in date. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="priceType"> the price type </param> /// <param name="refData"> the reference data </param> /// <returns> the price </returns> public virtual CurrencyAmount presentValue(ResolvedCdsTrade trade, CreditRatesProvider ratesProvider, PriceType priceType, ReferenceData refData) { CurrencyAmount pvProduct = productPricer.presentValue(trade.Product, ratesProvider, ratesProvider.ValuationDate, priceType, refData); if (!trade.UpfrontFee.Present) { return(pvProduct); } Payment upfront = trade.UpfrontFee.get(); CurrencyAmount pvUpfront = upfrontPricer.presentValue(upfront, ratesProvider.discountFactors(upfront.Currency).toDiscountFactors()); return(pvProduct.plus(pvUpfront)); }
public virtual void pricePufTest() { double premium = 150d * ONE_BP; Cds product = Cds.of(BUY, LEGAL_ENTITY, GBP, 1.0e6, START_DATE, END_DATE, Frequency.P3M, DEFAULT_CALENDAR, premium); TradeInfo info = TradeInfo.builder().tradeDate(TODAY).settlementDate(product.SettlementDateOffset.adjust(TODAY, REF_DATA)).build(); ResolvedCdsTrade trade = CdsTrade.builder().product(product).info(info).build().resolve(REF_DATA); NodalCurve cc = CALIB.calibrate(ImmutableList.of(trade), DoubleArray.of(0.0123), DoubleArray.of(0.0), CurveName.of("test"), TODAY, DSC_CURVE, REC_RATES, REF_DATA); CreditRatesProvider rates = RATES_PROVIDER.toImmutableCreditRatesProvider().toBuilder().creditCurves(ImmutableMap.of(Pair.of(LEGAL_ENTITY, GBP), LegalEntitySurvivalProbabilities.of(LEGAL_ENTITY, IsdaCreditDiscountFactors.of(GBP, TODAY, cc)))).build(); double pointsUpFront = CONV.pointsUpfront(trade, rates, REF_DATA); double cleanPrice = CONV.cleanPrice(trade, rates, REF_DATA); double cleanPriceRe = CONV.cleanPriceFromPointsUpfront(pointsUpFront); assertEquals(cleanPrice, cleanPriceRe, TOL); }
/// <summary> /// Calculates the expected loss of the CDS index product. /// <para> /// The expected loss is the (undiscounted) expected default settlement value paid by the protection seller. /// The resulting value is always positive. /// /// </para> /// </summary> /// <param name="cdsIndex"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <returns> the expected loss </returns> public virtual CurrencyAmount expectedLoss(ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider) { if (isExpired(cdsIndex, ratesProvider)) { return(CurrencyAmount.of(cdsIndex.Currency, 0d)); } ResolvedCds cds = cdsIndex.toSingleNameCds(); double recoveryRate = underlyingPricer.recoveryRate(cds, ratesProvider); Triple <CreditDiscountFactors, LegalEntitySurvivalProbabilities, double> rates = reduceDiscountFactors(cds, ratesProvider); double survivalProbability = rates.Second.survivalProbability(cds.ProtectionEndDate); double el = (1d - recoveryRate) * (1d - survivalProbability) * rates.Third; return(CurrencyAmount.of(cds.Currency, Math.Abs(cds.Notional) * el)); }
/// <summary> /// Calculates the par spread sensitivity of the product. /// <para> /// The par spread sensitivity of the product is the sensitivity of par spread to the underlying curves. /// The resulting sensitivity is based on the currency of the CDS product. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the par spread </returns> public virtual PointSensitivityBuilder parSpreadSensitivity(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { ArgChecker.isTrue(cds.ProtectionEndDate.isAfter(ratesProvider.ValuationDate), "CDS already expired"); LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double protectionLeg = this.protectionLeg(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate); double riskyAnnuityInv = 1d / riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, PriceType.CLEAN); PointSensitivityBuilder protectionLegSensi = protectionLegSensitivity(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate).multipliedBy(riskyAnnuityInv); PointSensitivityBuilder riskyAnnuitySensi = riskyAnnuitySensitivity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate).multipliedBy(-protectionLeg * riskyAnnuityInv * riskyAnnuityInv); return(protectionLegSensi.combinedWith(riskyAnnuitySensi)); }
// internal price computation with specified coupon rate internal virtual double price(ResolvedCds cds, CreditRatesProvider ratesProvider, double fractionalSpread, LocalDate referenceDate, PriceType priceType, ReferenceData refData) { if (!cds.ProtectionEndDate.isAfter(ratesProvider.ValuationDate)) { //short cut already expired CDSs return(0d); } LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double protectionLeg = this.protectionLeg(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate); double rpv01 = riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, priceType); return(protectionLeg - rpv01 * fractionalSpread); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the recovery01 of the CDS product. /// <para> /// The recovery01 is defined as the present value sensitivity to the recovery rate. /// Since the ISDA standard model requires the recovery rate to be constant throughout the lifetime of the CDS, /// one currency amount is returned by this method. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the recovery01 </returns> public virtual CurrencyAmount recovery01(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { if (isExpired(cds, ratesProvider)) { return(CurrencyAmount.of(cds.Currency, 0d)); } LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); validateRecoveryRates(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double protectionFull = this.protectionFull(cds, rates.First, rates.Second, referenceDate, effectiveStartDate); return(CurrencyAmount.of(cds.Currency, -cds.BuySell.normalize(cds.Notional) * protectionFull)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the risky PV01 of the CDS index product. /// <para> /// RPV01 is defined as minus of the present value sensitivity to coupon rate. /// /// </para> /// </summary> /// <param name="cdsIndex"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="priceType"> the price type </param> /// <param name="refData"> the reference date </param> /// <returns> the RPV01 </returns> public virtual CurrencyAmount rpv01(ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, PriceType priceType, ReferenceData refData) { if (isExpired(cdsIndex, ratesProvider)) { return(CurrencyAmount.of(cdsIndex.Currency, 0d)); } ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); Triple <CreditDiscountFactors, LegalEntitySurvivalProbabilities, double> rates = reduceDiscountFactors(cds, ratesProvider); double riskyAnnuity = underlyingPricer.riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, priceType); double amount = cds.BuySell.normalize(cds.Notional) * riskyAnnuity * rates.Third; return(CurrencyAmount.of(cds.Currency, amount)); }
/// <summary> /// Calculates the price sensitivity of the product. /// <para> /// The price sensitivity of the product is the sensitivity of price to the underlying curves. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder priceSensitivity(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { if (isExpired(cds, ratesProvider)) { return(PointSensitivityBuilder.none()); } LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); PointSensitivityBuilder protectionLegSensi = protectionLegSensitivity(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate); PointSensitivityBuilder riskyAnnuitySensi = riskyAnnuitySensitivity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate).multipliedBy(-cds.FixedRate); return(protectionLegSensi.combinedWith(riskyAnnuitySensi)); }
//------------------------------------------------------------------------- // extract CDS trades from credit curve private ImmutableList <ResolvedCdsTrade> getBucketCds(ResolvedCds product, CreditRatesProvider ratesProvider) { CreditDiscountFactors creditCurve = ratesProvider.survivalProbabilities(product.LegalEntityId, product.Currency).SurvivalProbabilities; int nNodes = creditCurve.ParameterCount; ImmutableList.Builder <ResolvedCdsTrade> 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 ResolvedCdsTrade, "ResolvedTrade must be ResolvedCdsTrade"); builder.add((ResolvedCdsTrade)trade); } return(builder.build()); }
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)); }
/// <summary> /// Converts points upfront to quoted spread. /// <para> /// Thus {@code quote} must be {@code CdsQuoteConvention.POINTS_UPFRONT}. /// </para> /// <para> /// The relevant discount curve and recovery rate curve must be stored in {@code ratesProvider}. /// The credit curve is internally calibrated to convert one quote type to the other quote type. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <param name="quote"> the quote </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="refData"> the reference data </param> /// <returns> the quote </returns> public virtual CdsQuote quotedSpreadFromPointsUpfront(ResolvedCdsTrade trade, CdsQuote quote, CreditRatesProvider ratesProvider, ReferenceData refData) { ArgChecker.notNull(trade, "trade"); ArgChecker.notNull(quote, "quote"); ArgChecker.notNull(ratesProvider, "ratesProvider"); ArgChecker.notNull(refData, "refData"); ArgChecker.isTrue(quote.QuoteConvention.Equals(CdsQuoteConvention.POINTS_UPFRONT), "quote must be points upfront"); ResolvedCds product = trade.Product; Currency currency = product.Currency; StandardId legalEntityId = product.LegalEntityId; LocalDate valuationDate = ratesProvider.ValuationDate; NodalCurve creditCurve = calibrator.calibrate(ImmutableList.of(trade), DoubleArray.of(product.FixedRate), DoubleArray.of(quote.QuotedValue), CurveName.of("temp"), valuationDate, ratesProvider.discountFactors(currency), ratesProvider.recoveryRates(legalEntityId), refData); CreditRatesProvider ratesProviderNew = ratesProvider.toImmutableCreditRatesProvider().toBuilder().creditCurves(ImmutableMap.of(Pair.of(legalEntityId, currency), LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, creditCurve)))).build(); double sp = pricer.parSpread(trade, ratesProviderNew, refData); return(CdsQuote.of(CdsQuoteConvention.QUOTED_SPREAD, sp)); }
//------------------------------------------------------------------------- //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void sensitivity_credit_isda() public virtual void sensitivity_credit_isda() { LocalDate valuationDate = LocalDate.of(2014, 1, 3); CreditRatesProvider rates = CreditRatesProviderDataSets.createCreditRatesProvider(valuationDate); CurrencyParameterSensitivities sensiComputed = FD_CALCULATOR.sensitivity(rates, this.creditFunction); IList <IsdaCreditDiscountFactors> curves = CreditRatesProviderDataSets.getAllDiscountFactors(valuationDate); assertEquals(sensiComputed.size(), curves.Count); foreach (IsdaCreditDiscountFactors curve in curves) { DoubleArray time = curve.ParameterKeys; DoubleArray sensiValueComputed = sensiComputed.getSensitivity(curve.Curve.Name, USD).Sensitivity; assertEquals(sensiValueComputed.size(), time.size()); for (int i = 0; i < time.size(); i++) { assertEquals(time.get(i), sensiValueComputed.get(i), TOLERANCE_DELTA); } } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the jump-to-default of the CDS product. /// <para> /// The jump-to-default is the value of the product in case of immediate default. /// /// </para> /// </summary> /// <param name="cds"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the jump-to-default </returns> public virtual JumpToDefault jumpToDefault(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { StandardId legalEntityId = cds.LegalEntityId; Currency currency = cds.Currency; if (isExpired(cds, ratesProvider)) { return(JumpToDefault.of(currency, ImmutableMap.of(legalEntityId, 0d))); } LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = this.recoveryRate(cds, ratesProvider); Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider); double protectionFull = this.protectionFull(cds, rates.First, rates.Second, referenceDate, effectiveStartDate); double lgd = 1d - recoveryRate; double rpv01 = riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, PriceType.CLEAN); double jtd = lgd - (lgd * protectionFull - cds.FixedRate * rpv01); return(JumpToDefault.of(currency, ImmutableMap.of(legalEntityId, cds.BuySell.normalize(cds.Notional) * jtd))); }
/// <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); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the jump-to-default of the CDS index product. /// <para> /// The jump-to-default is the value of the product in case of immediate default of a constituent single name. /// </para> /// <para> /// Under the homogeneous pool assumption, the jump-to-default values are the same for all of the undefaulted names, /// and zero for defaulted names. Thus the resulting object contains a single number. /// /// </para> /// </summary> /// <param name="cdsIndex"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="refData"> the reference data </param> /// <returns> the recovery01 </returns> public virtual JumpToDefault jumpToDefault(ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { StandardId indexId = cdsIndex.CdsIndexId; Currency currency = cdsIndex.Currency; if (isExpired(cdsIndex, ratesProvider)) { return(JumpToDefault.of(currency, ImmutableMap.of(indexId, 0d))); } ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = underlyingPricer.recoveryRate(cds, ratesProvider); Triple <CreditDiscountFactors, LegalEntitySurvivalProbabilities, double> rates = reduceDiscountFactors(cds, ratesProvider); double protectionFull = underlyingPricer.protectionFull(cds, rates.First, rates.Second, referenceDate, effectiveStartDate); double rpv01 = underlyingPricer.riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, PriceType.CLEAN); double lgd = 1d - recoveryRate; double numTotal = cdsIndex.LegalEntityIds.size(); double jtd = (lgd - (lgd * protectionFull - cds.FixedRate * rpv01)) / numTotal; return(JumpToDefault.of(currency, ImmutableMap.of(indexId, cds.BuySell.normalize(cds.Notional) * jtd))); }
/// <summary> /// Calculates the market quote sensitivities from parameter sensitivity. /// <para> /// This calculates the market quote sensitivities of credit derivatives. /// The input parameter sensitivities must be computed based on the credit rates provider. /// /// </para> /// </summary> /// <param name="paramSensitivities"> the curve parameter sensitivities </param> /// <param name="provider"> the credit rates provider, containing Jacobian calibration information </param> /// <returns> the market quote sensitivities </returns> public virtual CurrencyParameterSensitivities sensitivity(CurrencyParameterSensitivities paramSensitivities, CreditRatesProvider provider) { CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty(); foreach (CurrencyParameterSensitivity paramSens in paramSensitivities.Sensitivities) { // find the matching calibration info Curve curve = provider.findData(paramSens.MarketDataName).filter(v => v is Curve).map(v => (Curve)v).orElseThrow(() => new System.ArgumentException("Market Quote sensitivity requires curve: " + paramSens.MarketDataName)); JacobianCalibrationMatrix info = curve.Metadata.findInfo(CurveInfoType.JACOBIAN).orElseThrow(() => new System.ArgumentException("Market Quote sensitivity requires Jacobian calibration information")); // calculate the market quote sensitivity using the Jacobian DoubleMatrix jacobian = info.JacobianMatrix; DoubleArray paramSensMatrix = paramSens.Sensitivity; DoubleArray marketQuoteSensMatrix = (DoubleArray)MATRIX_ALGEBRA.multiply(paramSensMatrix, jacobian); DoubleArray marketQuoteSens = marketQuoteSensMatrix; // split between different curves IDictionary <CurveName, DoubleArray> split = info.splitValues(marketQuoteSens); foreach (KeyValuePair <CurveName, DoubleArray> entry in split.SetOfKeyValuePairs()) { CurveName curveName = entry.Key; CurrencyParameterSensitivity maketQuoteSens = provider.findData(curveName).map(c => c.createParameterSensitivity(paramSens.Currency, entry.Value)).orElse(CurrencyParameterSensitivity.of(curveName, paramSens.Currency, entry.Value)); result = result.combinedWith(maketQuoteSens); } } return(result); }
/// <summary> /// Computes the market clean price. /// <para> /// The market clean price is usually expressed in percentage. /// Here a fraction of notional is returned, e.g., 0.98 is 98(%) clean price. /// </para> /// <para> /// A relevant credit curve must be pre-calibrated and stored in {@code ratesProvider}. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="refData"> the reference data </param> /// <returns> the clean price </returns> public virtual double cleanPrice(ResolvedCdsTrade trade, CreditRatesProvider ratesProvider, ReferenceData refData) { double puf = pointsUpfront(trade, ratesProvider, refData); return(1d - puf); }
/// <summary> /// Computes the points upfront. /// <para> /// The points upfront quote is usually expressed in percentage. /// Here a fraction of notional is returned, e.g., 0.01 is 1(%) points up-front /// </para> /// <para> /// The relevant credit curve must be pre-calibrated and stored in {@code ratesProvider}. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="refData"> the reference data </param> /// <returns> the points upfront </returns> public virtual double pointsUpfront(ResolvedCdsTrade trade, CreditRatesProvider ratesProvider, ReferenceData refData) { return(pricer.price(trade, ratesProvider, PriceType.CLEAN, refData)); }