/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ResolvedCdsIndex beanToCopy) { this.buySell = beanToCopy.getBuySell(); this.cdsIndexId = beanToCopy.getCdsIndexId(); this.legalEntityIds = beanToCopy.getLegalEntityIds(); this.paymentPeriods = beanToCopy.getPaymentPeriods(); this.protectionEndDate = beanToCopy.getProtectionEndDate(); this.dayCount = beanToCopy.getDayCount(); this.paymentOnDefault = beanToCopy.getPaymentOnDefault(); this.protectionStart = beanToCopy.getProtectionStart(); this.stepinDateOffset = beanToCopy.getStepinDateOffset(); this.settlementDateOffset = beanToCopy.getSettlementDateOffset(); }
/** * Calculates the price sensitivity of the product. * <p> * The price sensitivity of the product is the sensitivity of price to the underlying curves. * * @param cdsIndex the product * @param ratesProvider the rates provider * @param referenceDate the reference date * @param refData the reference data * @return the present value sensitivity */ public PointSensitivityBuilder priceSensitivity( ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { ResolvedCds cds = cdsIndex.toSingleNameCds(); return underlyingPricer.priceSensitivity(cds, ratesProvider, referenceDate, refData); }
/** * Calculates the accrued premium per fractional spread for unit notional. * * @param stepinDate the step-in date * @return the accrued year fraction */ public double accruedYearFraction(LocalDate stepinDate) { if (stepinDate.isBefore(getAccrualStartDate())) { return 0d; } if (stepinDate.isEqual(getAccrualEndDate())) { return paymentPeriods.get(paymentPeriods.size() - 1).getYearFraction(); } CreditCouponPaymentPeriod period = findPeriod(stepinDate) .orElseThrow(() -> new IllegalArgumentException("Date outside range")); return dayCount.relativeYearFraction(period.getStartDate(), stepinDate); }
private ImmutableList<ResolvedCdsIndexTrade> getBucketCdsIndex(ResolvedCdsIndex product, CreditRatesProvider ratesProvider) { CreditDiscountFactors creditCurve = ratesProvider.survivalProbabilities(product.getCdsIndexId(), product.getCurrency()).getSurvivalProbabilities(); int nNodes = creditCurve.getParameterCount(); Builder<ResolvedCdsIndexTrade> builder = ImmutableList.builder(); for (int i = 0; i < nNodes; ++i) { ParameterMetadata metadata = creditCurve.getParameterMetadata(i); ArgChecker.isTrue(metadata instanceof ResolvedTradeParameterMetadata, "ParameterMetadata of credit curve must be ResolvedTradeParameterMetadata"); ResolvedTradeParameterMetadata tradeMetadata = (ResolvedTradeParameterMetadata) metadata; ResolvedTrade trade = tradeMetadata.getTrade(); ArgChecker.isTrue(trade instanceof ResolvedCdsIndexTrade, "ResolvedTrade must be ResolvedCdsIndexTrade"); builder.add((ResolvedCdsIndexTrade) trade); } return builder.build(); }
public void test_builder() { ResolvedCdsIndex test = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .cdsIndexId(INDEX_ID) .legalEntityIds(LEGAL_ENTITIES) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); assertEquals(test.getBuySell(), BUY); assertEquals(test.getCurrency(), USD); assertEquals(test.getAccrualStartDate(), PAYMENTS.get(0).getStartDate()); assertEquals(test.getAccrualEndDate(), PAYMENTS.get(42).getEndDate()); assertEquals(test.getDayCount(), ACT_360); assertEquals(test.getFixedRate(), COUPON); assertEquals(test.getCdsIndexId(), INDEX_ID); assertEquals(test.getLegalEntityIds(), LEGAL_ENTITIES); assertEquals(test.getNotional(), NOTIONAL); assertEquals(test.getPaymentOnDefault(), ACCRUED_PREMIUM); assertEquals(test.getPaymentPeriods(), PAYMENTS); assertEquals(test.getProtectionEndDate(), PAYMENTS.get(42).getEffectiveEndDate()); assertEquals(test.getSettlementDateOffset(), SETTLE_DAY_ADJ); assertEquals(test.getProtectionStart(), BEGINNING); assertEquals(test.getStepinDateOffset(), STEPIN_DAY_ADJ); }
ReferenceData refData) { StandardId indexId = cdsIndex.getCdsIndexId(); Currency currency = cdsIndex.getCurrency(); if (isExpired(cdsIndex, ratesProvider)) { return JumpToDefault.of(currency, ImmutableMap.of(indexId, 0d)); ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.getStepinDateOffset().adjust(ratesProvider.getValuationDate(), refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); cds, rates.getFirst(), rates.getSecond(), referenceDate, stepinDate, effectiveStartDate, PriceType.CLEAN); double lgd = 1d - recoveryRate; double numTotal = cdsIndex.getLegalEntityIds().size(); double jtd = (lgd - (lgd * protectionFull - cds.getFixedRate() * rpv01)) / numTotal; return JumpToDefault.of(currency, ImmutableMap.of(indexId, cds.getBuySell().normalize(cds.getNotional()) * jtd));
public void jumpToDefaultTest() { JumpToDefault computed = PRICER.jumpToDefault(PRODUCT, RATES_PROVIDER, SETTLEMENT_STD, REF_DATA); LocalDate stepinDate = PRODUCT.getStepinDateOffset().adjust(VALUATION_DATE, REF_DATA); double dirtyPvMod = PRICER.presentValue(PRODUCT, RATES_PROVIDER, SETTLEMENT_STD, PriceType.DIRTY, REF_DATA).getAmount() / INDEX_FACTOR; double accrued = PRODUCT.accruedYearFraction(stepinDate) * PRODUCT.getFixedRate() * PRODUCT.getBuySell().normalize(NOTIONAL); double protection = PRODUCT.getBuySell().normalize(NOTIONAL) * (1d - RECOVERY_RATE); double expected = (protection - accrued - dirtyPvMod) / ((double) LEGAL_ENTITIES.size()); assertEquals(computed.getCurrency(), USD); assertTrue(computed.getAmounts().size() == 1); assertEquals(computed.getAmounts().get(INDEX_ID), expected, NOTIONAL * TOL); }
/** * Calculates the expected loss of the CDS index product. * <p> * The expected loss is the (undiscounted) expected default settlement value paid by the protection seller. * The resulting value is always positive. * * @param cdsIndex the product * @param ratesProvider the rates provider * @return the expected loss */ public CurrencyAmount expectedLoss( ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider) { if (isExpired(cdsIndex, ratesProvider)) { return CurrencyAmount.of(cdsIndex.getCurrency(), 0d); } ResolvedCds cds = cdsIndex.toSingleNameCds(); double recoveryRate = underlyingPricer.recoveryRate(cds, ratesProvider); Triple<CreditDiscountFactors, LegalEntitySurvivalProbabilities, Double> rates = reduceDiscountFactors(cds, ratesProvider); double survivalProbability = rates.getSecond().survivalProbability(cds.getProtectionEndDate()); double el = (1d - recoveryRate) * (1d - survivalProbability) * rates.getThird(); return CurrencyAmount.of(cds.getCurrency(), Math.abs(cds.getNotional()) * el); }
boolean isExpired(ResolvedCdsIndex index, CreditRatesProvider ratesProvider) { return !index.getProtectionEndDate().isAfter(ratesProvider.getValuationDate()); }
public void test_totoSingleNameCds() { ResolvedCdsIndex base = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .cdsIndexId(INDEX_ID) .legalEntityIds(LEGAL_ENTITIES) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); ResolvedCds test = base.toSingleNameCds(); ResolvedCds expected = ResolvedCds.builder() .buySell(BUY) .dayCount(ACT_360) .legalEntityId(INDEX_ID) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); assertEquals(test, expected); }
public void test_accruedYearFraction() { double eps = 1.0e-15; ResolvedCdsIndex test = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .cdsIndexId(INDEX_ID) .legalEntityIds(LEGAL_ENTITIES) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); double accStart = test.accruedYearFraction(START_DATE.minusDays(1)); double accNextMinusOne = test.accruedYearFraction(START_DATE.plusMonths(3).minusDays(1)); double accNext = test.accruedYearFraction(START_DATE.plusMonths(3)); double accNextOne = test.accruedYearFraction(START_DATE.plusMonths(3).plusDays(1)); double accMod = test.accruedYearFraction(START_DATE.plusYears(1)); double accEnd = test.accruedYearFraction(END_DATE); double accEndOne = test.accruedYearFraction(END_DATE.plusDays(1)); assertEquals(accStart, 0d); assertEquals(accNext, 0d); assertEquals(accNextMinusOne, ACT_360.relativeYearFraction(START_DATE, START_DATE.plusMonths(3).minusDays(1)), eps); assertEquals(accNextOne, 1d / 360d, eps); // 2.x assertEquals(accMod, 0.24722222222222223, eps); assertEquals(accEnd, 0.25555555555555554, eps); assertEquals(accEndOne, 0.25833333333333336, eps); }
public void test_serialization() { ResolvedCdsIndex test = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .cdsIndexId(INDEX_ID) .legalEntityIds(LEGAL_ENTITIES) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); assertSerialization(test); }
public void test_effectiveStartDate() { ResolvedCdsIndex test1 = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .build(); LocalDate date1 = LocalDate.of(2016, 3, 22); assertEquals(test1.calculateEffectiveStartDate(date1), date1.minusDays(1)); LocalDate date2 = LocalDate.of(2013, 9, 22); assertEquals(test1.calculateEffectiveStartDate(date2), START_DATE.minusDays(1)); ResolvedCdsIndex test2 = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .build(); LocalDate date3 = LocalDate.of(2016, 3, 22); assertEquals(test2.calculateEffectiveStartDate(date3), date3); LocalDate date4 = LocalDate.of(2013, 9, 22); assertEquals(test2.calculateEffectiveStartDate(date4), START_DATE);
/** * Obtains the effective start date from the step-in date. * * @param stepinDate the step-in date * @return the effective start date */ public LocalDate calculateEffectiveStartDate(LocalDate stepinDate) { LocalDate startDate = stepinDate.isAfter(getAccrualStartDate()) ? stepinDate : getAccrualStartDate(); return protectionStart.isBeginning() ? startDate.minusDays(1) : startDate; }
/** * Calculates the risky PV01 of the CDS index product. * <p> * RPV01 is defined as minus of the present value sensitivity to coupon rate. * * @param cdsIndex the product * @param ratesProvider the rates provider * @param referenceDate the reference date * @param priceType the price type * @param refData the reference date * @return the RPV01 */ public CurrencyAmount rpv01( ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, PriceType priceType, ReferenceData refData) { if (isExpired(cdsIndex, ratesProvider)) { return CurrencyAmount.of(cdsIndex.getCurrency(), 0d); } ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.getStepinDateOffset().adjust(ratesProvider.getValuationDate(), refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); Triple<CreditDiscountFactors, LegalEntitySurvivalProbabilities, Double> rates = reduceDiscountFactors(cds, ratesProvider); double riskyAnnuity = underlyingPricer.riskyAnnuity( cds, rates.getFirst(), rates.getSecond(), referenceDate, stepinDate, effectiveStartDate, priceType); double amount = cds.getBuySell().normalize(cds.getNotional()) * riskyAnnuity * rates.getThird(); return CurrencyAmount.of(cds.getCurrency(), amount); }
/** * Computes bucketed CS01 for CDS index using a single credit curve. * <p> * This is coherent to the pricer {@link IsdaHomogenousCdsIndexTradePricer}. * The relevant credit curve must be stored in {@code RatesProvider}. * * @param trade the trade * @param bucketCdsIndex the CDS index bucket * @param ratesProvider the rates provider * @param refData the reference data * @return the bucketed CS01 */ public CurrencyParameterSensitivity bucketedCs01( ResolvedCdsIndexTrade trade, List<ResolvedCdsIndexTrade> bucketCdsIndex, CreditRatesProvider ratesProvider, ReferenceData refData) { ResolvedCdsTrade cdsTrade = trade.toSingleNameCds(); List<ResolvedCdsTrade> bucketCds = bucketCdsIndex.stream() .map(ResolvedCdsIndexTrade::toSingleNameCds) .collect(Collectors.toList()); List<ResolvedTradeParameterMetadata> metadata = bucketCdsIndex.stream() .map(t -> ResolvedTradeParameterMetadata.of(t, t.getProduct().getProtectionEndDate().toString())) .collect(Guavate.toImmutableList()); CurrencyParameterSensitivity bucketedCs01 = bucketedCs01(cdsTrade, bucketCds, metadata, ratesProvider, refData); double indexFactor = getIndexFactor(cdsTrade.getProduct(), ratesProvider); return bucketedCs01.multipliedBy(indexFactor); }
public void coverage() { ResolvedCdsIndex test1 = ResolvedCdsIndex.builder() .buySell(BUY) .dayCount(ACT_360) .cdsIndexId(INDEX_ID) .legalEntityIds(LEGAL_ENTITIES) .paymentOnDefault(ACCRUED_PREMIUM) .protectionStart(BEGINNING) .paymentPeriods(PAYMENTS) .protectionEndDate(PAYMENTS.get(PAYMENTS.size() - 1).getEffectiveEndDate()) .settlementDateOffset(SETTLE_DAY_ADJ) .stepinDateOffset(STEPIN_DAY_ADJ) .build(); coverImmutableBean(test1); ResolvedCdsIndex test2 = ResolvedCdsIndex.builder() .buySell(BuySell.SELL) .dayCount(DayCounts.ACT_365F) .cdsIndexId(StandardId.of("OG", "AA-INDEX")) .legalEntityIds(ImmutableList.of(StandardId.of("OG", "ABC1"), StandardId.of("OG", "ABC2"))) .paymentOnDefault(PaymentOnDefault.NONE) .protectionStart(ProtectionStartOfDay.NONE) .paymentPeriods(PAYMENTS.get(0)) .protectionEndDate(PAYMENTS.get(0).getEffectiveEndDate()) .settlementDateOffset(DaysAdjustment.NONE) .stepinDateOffset(DaysAdjustment.NONE) .build(); coverBeanEquals(test1, test2); }
@Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 244977400: // buySell return ((ResolvedCdsIndex) bean).getBuySell(); case -464117509: // cdsIndexId return ((ResolvedCdsIndex) bean).getCdsIndexId(); case 1085098268: // legalEntityIds return ((ResolvedCdsIndex) bean).getLegalEntityIds(); case -1674414612: // paymentPeriods return ((ResolvedCdsIndex) bean).getPaymentPeriods(); case -1193325040: // protectionEndDate return ((ResolvedCdsIndex) bean).getProtectionEndDate(); case 1905311443: // dayCount return ((ResolvedCdsIndex) bean).getDayCount(); case -480203780: // paymentOnDefault return ((ResolvedCdsIndex) bean).getPaymentOnDefault(); case 2103482633: // protectionStart return ((ResolvedCdsIndex) bean).getProtectionStart(); case 852621746: // stepinDateOffset return ((ResolvedCdsIndex) bean).getStepinDateOffset(); case 135924714: // settlementDateOffset return ((ResolvedCdsIndex) bean).getSettlementDateOffset(); } return super.propertyGet(bean, propertyName, quiet); }
return CurrencyAmount.of(cdsIndex.getCurrency(), 0d); ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.getStepinDateOffset().adjust(ratesProvider.getValuationDate(), refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate);
/** * Calculates the par spread of the CDS index product. * <p> * The par spread is a coupon rate such that the clean PV is 0. * The result is represented in decimal form. * * @param cdsIndex the product * @param ratesProvider the rates provider * @param referenceDate the reference date * @param refData the reference data * @return the par spread */ public double parSpread( ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData) { ResolvedCds cds = cdsIndex.toSingleNameCds(); return underlyingPricer.parSpread(cds, ratesProvider, referenceDate, refData); }