/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(CapitalIndexedBondPaymentPeriod beanToCopy) { this.currency = beanToCopy.getCurrency(); this.notional = beanToCopy.getNotional(); this.realCoupon = beanToCopy.getRealCoupon(); this.startDate = beanToCopy.getStartDate(); this.endDate = beanToCopy.getEndDate(); this.unadjustedStartDate = beanToCopy.getUnadjustedStartDate(); this.unadjustedEndDate = beanToCopy.getUnadjustedEndDate(); this.detachmentDate = beanToCopy.getDetachmentDate(); this.rateComputation = beanToCopy.getRateComputation(); }
/** * Calculates the forecast value of a single payment period. * * @param period the period to price * @param ratesProvider the rates provider, used to determine price index values * @return the forecast value of the period */ public double forecastValue(CapitalIndexedBondPaymentPeriod period, RatesProvider ratesProvider) { if (period.getPaymentDate().isBefore(ratesProvider.getValuationDate())) { return 0d; } double rate = rateComputationFn.rate( period.getRateComputation(), period.getStartDate(), period.getEndDate(), ratesProvider); return period.getNotional() * period.getRealCoupon() * (rate + 1d); }
@Override public LocalDate getPeriodEndDate(LocalDate date) { return periodicPayments.stream() .filter(p -> p.contains(date)) .map(p -> p.getUnadjustedEndDate()) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Date is not contained in any period")); }
ExplainMapBuilder builder) { Currency currency = period.getCurrency(); LocalDate paymentDate = period.getPaymentDate(); builder.put(ExplainKey.ENTRY_TYPE, "CapitalIndexedBondPaymentPeriod"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.START_DATE, period.getStartDate()); builder.put(ExplainKey.UNADJUSTED_START_DATE, period.getUnadjustedStartDate()); builder.put(ExplainKey.END_DATE, period.getEndDate()); builder.put(ExplainKey.UNADJUSTED_END_DATE, period.getUnadjustedEndDate()); builder.put(ExplainKey.DAYS, (int) DAYS.between(period.getUnadjustedStartDate(), period.getUnadjustedEndDate())); if (paymentDate.isBefore(ratesProvider.getValuationDate())) { builder.put(ExplainKey.COMPLETED, Boolean.TRUE);
for (int loopcpn = 0; loopcpn < nbCoupon; loopcpn++) { CapitalIndexedBondPaymentPeriod period = bond.getPeriodicPayments().get(loopcpn); if ((bond.hasExCouponPeriod() && !settlementDate.isAfter(period.getDetachmentDate())) || (!bond.hasExCouponPeriod() && period.getPaymentDate().isAfter(settlementDate))) { mdAtFirstCoupon += period.getRealCoupon() / Math.pow(factorOnPeriod, pow + 1) * (pow + factorToNext) / couponPerYear; pvAtFirstCoupon += period.getRealCoupon() / Math.pow(factorOnPeriod, pow); ++pow;
public void test_builder() { ResolvedCapitalIndexedBond test = sut(); assertEquals(test.getCurrency(), USD); assertEquals(test.getDayCount(), ACT_ACT_ISDA); assertEquals(test.getStartDate(), PERIODIC[0].getStartDate()); assertEquals(test.getEndDate(), PERIODIC[3].getEndDate()); assertEquals(test.getUnadjustedStartDate(), PERIODIC[0].getUnadjustedStartDate()); assertEquals(test.getUnadjustedEndDate(), PERIODIC[3].getUnadjustedEndDate()); assertEquals(test.getLegalEntityId(), LEGAL_ENTITY); assertEquals(test.getNominalPayment(), NOMINAL); assertEquals(test.getNotional(), NOTIONAL); assertEquals(test.getPeriodicPayments().toArray(), PERIODIC); assertEquals(test.getSettlementDateOffset(), SETTLE_OFFSET); assertEquals(test.getYieldConvention(), US_IL_REAL); assertEquals(test.hasExCouponPeriod(), false); assertEquals(test.getFirstIndexValue(), RATE_CALC.getFirstIndexValue().getAsDouble()); assertEquals(test.findPeriod(PERIODIC[0].getUnadjustedStartDate()), Optional.of(test.getPeriodicPayments().get(0))); assertEquals(test.findPeriod(LocalDate.MIN), Optional.empty()); assertEquals(test.findPeriodIndex(PERIODIC[0].getUnadjustedStartDate()), OptionalInt.of(0)); assertEquals(test.findPeriodIndex(PERIODIC[1].getUnadjustedStartDate()), OptionalInt.of(1)); assertEquals(test.findPeriodIndex(LocalDate.MIN), OptionalInt.empty()); assertEquals( test.calculateSettlementDateFromValuation(date(2015, 6, 30), REF_DATA), SETTLE_OFFSET.adjust(date(2015, 6, 30), REF_DATA)); }
bondPeriodsBuilder.add(CapitalIndexedBondPaymentPeriod.builder() .unadjustedStartDate(period.getUnadjustedStartDate()) .unadjustedEndDate(period.getUnadjustedEndDate()) .withUnitCoupon(bondPeriods.get(0).getStartDate(), bondPeriods.get(0).getUnadjustedStartDate()); return ResolvedCapitalIndexedBond.builder() .securityId(securityId)
/** * Calculates the accrued interest of the bond with the specified date. * * @param referenceDate the reference date * @return the accrued interest of the product */ public double accruedInterest(LocalDate referenceDate) { if (getUnadjustedStartDate().isAfter(referenceDate)) { return 0d; } double notional = getNotional(); CapitalIndexedBondPaymentPeriod period = findPeriod(referenceDate) .orElseThrow(() -> new IllegalArgumentException("Date outside range of bond")); LocalDate previousAccrualDate = period.getUnadjustedStartDate(); double realCoupon = period.getRealCoupon(); double couponPerYear = getFrequency().eventsPerYear(); double rate = realCoupon * couponPerYear; double accruedInterest = yieldConvention.equals(CapitalIndexedBondYieldConvention.JP_IL_COMPOUND) || yieldConvention.equals(CapitalIndexedBondYieldConvention.JP_IL_SIMPLE) ? yearFraction(previousAccrualDate, referenceDate, DayCounts.ACT_365F) * rate * notional : yearFraction(previousAccrualDate, referenceDate) * rate * notional; double result = 0d; if (hasExCouponPeriod() && !referenceDate.isBefore(period.getDetachmentDate())) { result = accruedInterest - notional * rate * yearFraction(previousAccrualDate, period.getUnadjustedEndDate()); } else { result = accruedInterest; } return result; }
private double ratioPeriodToNextCoupon(CapitalIndexedBondPaymentPeriod bond, LocalDate settlementDate) { double nbDayToSpot = DAYS.between(settlementDate, bond.getUnadjustedEndDate()); double nbDaysPeriod = DAYS.between(bond.getUnadjustedStartDate(), bond.getUnadjustedEndDate()); return nbDayToSpot / nbDaysPeriod; }
if (yieldConvention.equals(CapitalIndexedBondYieldConvention.US_IL_REAL)) { double pvAtFirstCoupon; double cpnRate = bond.getPeriodicPayments().get(0).getRealCoupon(); if (Math.abs(yield) > 1.0E-8) { double factorOnPeriod = 1d + yield / couponPerYear; double realRate = period.getRealCoupon(); double firstYearFraction = bond.yearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate()); double v = 1d / (1d + yield / couponPerYear); double rs = ratioPeriodToNextCoupon(period, settlementDate); if (yieldConvention.equals(CapitalIndexedBondYieldConvention.GB_IL_FLOAT)) { RateComputation obs = period.getRateComputation(); LocalDateDoubleTimeSeries ts = ratesProvider.priceIndexValues(bond.getRateCalculation().getIndex()).getFixings(); YearMonth lastKnownFixingMonth = YearMonth.from(ts.getLatestDate()); double firstCashFlow = firstYearFraction * realRate * indexRatio * couponPerYear; CapitalIndexedBondPaymentPeriod secondPeriod = bond.getPeriodicPayments().get(periodIndex + 1); double secondYearFraction = bond.yearFraction(secondPeriod.getUnadjustedStartDate(), secondPeriod.getUnadjustedEndDate()); double secondCashFlow = secondYearFraction * realRate * indexRatio * couponPerYear; double vn = Math.pow(v, nbCoupon - 1); } else { CapitalIndexedBondPaymentPeriod secondPeriod = bond.getPeriodicPayments().get(periodIndex + 1); double secondYearFraction = bond.yearFraction(secondPeriod.getUnadjustedStartDate(), secondPeriod.getUnadjustedEndDate()); double secondCashFlow = realRate * indexRatio * secondYearFraction * couponPerYear; double vn = Math.pow(v, nbCoupon - 1); for (int loopcpn = 0; loopcpn < nbCoupon; loopcpn++) { CapitalIndexedBondPaymentPeriod paymentPeriod = bond.getPeriodicPayments().get(loopcpn + periodIndex);
public void test_explainPresentValue_past() { ExplainMapBuilder builder = ExplainMap.builder(); PRICER.explainPresentValue(PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY, builder); ExplainMap explain = builder.build(); assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "CapitalIndexedBondPaymentPeriod"); assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_INTERP.getPaymentDate()); assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_INTERP.getCurrency()); assertEquals(explain.get(ExplainKey.START_DATE).get(), START); assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), START_UNADJ); assertEquals(explain.get(ExplainKey.END_DATE).get(), END); assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), END_UNADJ); assertEquals(explain.get(ExplainKey.DAYS).get().intValue(), (int) DAYS.between(START_UNADJ, END_UNADJ)); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0d, NOTIONAL * TOL); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0d, NOTIONAL * TOL); }
PointSensitivityBuilder presentValueSensitivity( ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, LegalEntityDiscountingProvider discountingProvider, LocalDate referenceDate) { IssuerCurveDiscountFactors issuerDf = issuerCurveDf(bond, discountingProvider); PointSensitivityBuilder pointNominal = periodPricer.presentValueSensitivity(bond.getNominalPayment(), ratesProvider, issuerDf); PointSensitivityBuilder pointCoupon = PointSensitivityBuilder.none(); for (CapitalIndexedBondPaymentPeriod period : bond.getPeriodicPayments()) { if ((bond.hasExCouponPeriod() && period.getDetachmentDate().isAfter(referenceDate)) || (!bond.hasExCouponPeriod() && period.getPaymentDate().isAfter(referenceDate))) { pointCoupon = pointCoupon.combinedWith( periodPricer.presentValueSensitivity(period, ratesProvider, issuerDf)); } } return pointNominal.combinedWith(pointCoupon); }
public void test_builder_fail() { CapitalIndexedBondPaymentPeriod period = CapitalIndexedBondPaymentPeriod.builder() .startDate(PERIODIC[2].getStartDate()) .endDate(PERIODIC[2].getEndDate()) .currency(GBP) .notional(NOTIONAL) .rateComputation(PERIODIC[2].getRateComputation()) .realCoupon(COUPON) .build(); assertThrowsIllegalArg(() -> ResolvedCapitalIndexedBond.builder() .dayCount(ACT_ACT_ISDA) .legalEntityId(LEGAL_ENTITY) .nominalPayment(NOMINAL) .periodicPayments(PERIODIC[0], PERIODIC[1], period, PERIODIC[3]) .settlementDateOffset(SETTLE_OFFSET) .yieldConvention(US_IL_REAL) .build()); }
public void test_accruedInterest_exCoupon_in() { CapitalIndexedBondPaymentPeriod period = PRODUCT_EX_COUPON.getPeriodicPayments().get(16); LocalDate refDate = period.getDetachmentDate(); double computed = PRODUCT_EX_COUPON.accruedInterest(refDate); Schedule sch = SCHEDULE.createSchedule(REF_DATA).toUnadjusted(); double factor = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), refDate, sch); double factorTotal = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate(), sch); assertEquals(computed, (factor - factorTotal) * REAL_COUPON_VALUE * NOTIONAL * 2d, TOL * REAL_COUPON_VALUE * NOTIONAL); }
public void test_accruedInterest_jpw() { double accPositive = PRODUCT_JPW.accruedInterest(LocalDate.of(2016, 3, 9)); CapitalIndexedBondPaymentPeriod period = PRODUCT_JPW.getPeriodicPayments().get(4); double yc = PRODUCT_JPW.getDayCount().relativeYearFraction(period.getStartDate(), period.getEndDate()); double expected = CPN_VALUE_JPW * 2d * yc * NTNL; // accrual of total period based on ACT/365F assertEquals(accPositive, expected, NTNL * NOTIONAL); double accZero = PRODUCT_JPW.accruedInterest(LocalDate.of(2016, 3, 10)); assertEquals(accZero, 0d); }
static ResolvedCapitalIndexedBond sut2() { return ResolvedCapitalIndexedBond.builder() .securityId(CapitalIndexedBondTest.sut2().getSecurityId()) .dayCount(NL_365) .legalEntityId(LegalEntityId.of("OG-Ticker", "US-Govt1")) .nominalPayment(PERIODIC[1].withUnitCoupon(PERIODIC[0].getStartDate(), PERIODIC[0].getUnadjustedStartDate())) .periodicPayments(PERIODIC[0], PERIODIC[1]) .frequency(CapitalIndexedBondTest.sut2().getAccrualSchedule().getFrequency()) .rollConvention(CapitalIndexedBondTest.sut2().getAccrualSchedule().calculatedRollConvention()) .settlementDateOffset(DaysAdjustment.ofBusinessDays(3, GBLO)) .yieldConvention(GB_IL_FLOAT) .rateCalculation(CapitalIndexedBondTest.sut2().getRateCalculation()) .build(); }
public void test_methods() { CapitalIndexedBondPaymentPeriod test = CapitalIndexedBondPaymentPeriod.builder() .currency(USD) .notional(NOTIONAL) .realCoupon(REAL_COUPON) .build(); assertEquals(test.getPaymentDate(), END); assertEquals(test.adjustPaymentDate(TemporalAdjusters.ofDateAdjuster(d -> d.plusDays(2))), test); ImmutableSet.Builder<Index> builder = ImmutableSet.builder(); test.collectIndices(builder); ImmutableSet<Index> set = builder.build(); assertEquals(set.size(), 1); CapitalIndexedBondPaymentPeriod expected = CapitalIndexedBondPaymentPeriod.builder() .currency(USD) .notional(NOTIONAL) .realCoupon(1d) .build(); assertEquals(test.withUnitCoupon(bondStart, bondStartUnadj), expected);
double presentValueCoupon( ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, IssuerCurveDiscountFactors discountFactors, LocalDate referenceDate1, LocalDate referenceDate2) { double pvDiff = 0d; for (CapitalIndexedBondPaymentPeriod period : bond.getPeriodicPayments()) { if (period.getDetachmentDate().isAfter(referenceDate1) && !period.getDetachmentDate().isAfter(referenceDate2)) { pvDiff += periodPricer.presentValue(period, ratesProvider, discountFactors); } } return pvDiff; }
/** * The unadjusted start date. * <p> * This is the unadjusted first coupon period date of the bond. * * @return the unadjusted start date */ public LocalDate getUnadjustedStartDate() { return periodicPayments.get(0).getUnadjustedStartDate(); }
/** * Gets the currency of the product. * <p> * All payments in the bond will have this currency. * * @return the currency */ public Currency getCurrency() { return nominalPayment.getCurrency(); }