/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ResolvedCapitalIndexedBond beanToCopy) { this.securityId = beanToCopy.getSecurityId(); this.nominalPayment = beanToCopy.getNominalPayment(); this.periodicPayments = beanToCopy.getPeriodicPayments(); this.frequency = beanToCopy.getFrequency(); this.rollConvention = beanToCopy.getRollConvention(); this.dayCount = beanToCopy.getDayCount(); this.yieldConvention = beanToCopy.getYieldConvention(); this.legalEntityId = beanToCopy.getLegalEntityId(); this.settlementDateOffset = beanToCopy.getSettlementDateOffset(); this.rateCalculation = beanToCopy.getRateCalculation(); }
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); }
/** * 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; }
/** * Calculates the dirty real price of the bond from its settlement date and clean real price. * * @param bond the product * @param settlementDate the settlement date * @param cleanPrice the clean real price * @return the price of the bond product */ public double dirtyRealPriceFromCleanRealPrice( ResolvedCapitalIndexedBond bond, LocalDate settlementDate, double cleanPrice) { double notional = bond.getNotional(); return cleanPrice + bond.accruedInterest(settlementDate) / notional; }
static RepoCurveDiscountFactors repoCurveDf(ResolvedCapitalIndexedBond bond, LegalEntityDiscountingProvider provider) { return provider.repoCurveDiscountFactors(bond.getSecurityId(), bond.getLegalEntityId(), bond.getCurrency()); }
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)); }
ArgChecker.isTrue(settlementDate.isBefore(bond.getUnadjustedEndDate()), "settlement date must be before end date"); int periodIndex = bond.findPeriodIndex(settlementDate) .orElseThrow(() -> new IllegalArgumentException("Date outside range of bond")); CapitalIndexedBondPaymentPeriod period = bond.getPeriodicPayments().get(periodIndex); int nbCoupon = bond.getPeriodicPayments().size() - periodIndex; double couponPerYear = bond.getFrequency().eventsPerYear(); CapitalIndexedBondYieldConvention yieldConvention = bond.getYieldConvention(); 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 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 indexRatio = ts.getLatestValue() / bond.getFirstIndexValue(); YearMonth endFixingMonth = null; if (obs instanceof InflationEndInterpolatedRateComputation) { } else { double firstCashFlow = firstYearFraction * realRate * indexRatio * couponPerYear; CapitalIndexedBondPaymentPeriod secondPeriod = bond.getPeriodicPayments().get(periodIndex + 1); double secondYearFraction = bond.yearFraction(secondPeriod.getUnadjustedStartDate(), secondPeriod.getUnadjustedEndDate());
CurrencyAmount presentValue( ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, LegalEntityDiscountingProvider discountingProvider, LocalDate referenceDate) { IssuerCurveDiscountFactors issuerDf = issuerCurveDf(bond, discountingProvider); double pvNominal = periodPricer.presentValue(bond.getNominalPayment(), ratesProvider, issuerDf); double pvCoupon = 0d; for (CapitalIndexedBondPaymentPeriod period : bond.getPeriodicPayments()) { if ((bond.hasExCouponPeriod() && period.getDetachmentDate().isAfter(referenceDate)) || (!bond.hasExCouponPeriod() && period.getPaymentDate().isAfter(referenceDate))) { pvCoupon += periodPricer.presentValue(period, ratesProvider, issuerDf); } } return CurrencyAmount.of(bond.getCurrency(), pvCoupon + pvNominal); }
double yield) { int nbCoupon = bond.getPeriodicPayments().size(); double couponPerYear = bond.getFrequency().eventsPerYear(); double factorOnPeriod = 1d + yield / couponPerYear; double pvAtFirstCoupon = 0d; double factorToNext = factorToNextCoupon(bond, settlementDate); 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))) { pvAtFirstCoupon += period.getRealCoupon() / Math.pow(factorOnPeriod, pow); ++pow;
public void test_presentValue() { CurrencyAmount computed = PRICER.presentValue(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER); double expected = PERIOD_PRICER.presentValue(PRODUCT.getNominalPayment(), RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS); int size = PRODUCT.getPeriodicPayments().size(); for (int i = 16; i < size; ++i) { CapitalIndexedBondPaymentPeriod payment = PRODUCT.getPeriodicPayments().get(i); expected += PERIOD_PRICER.presentValue(payment, RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS); } assertEquals(computed.getAmount(), expected, TOL * NOTIONAL); }
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); }
private double factorToNextCoupon(ResolvedCapitalIndexedBond bond, LocalDate settlementDate) { if (bond.getUnadjustedStartDate().isAfter(settlementDate)) { return 0d; } int periodIndex = bond.findPeriodIndex(settlementDate) .orElseThrow(() -> new IllegalArgumentException("Date outside range of bond")); CapitalIndexedBondPaymentPeriod period = bond.getPeriodicPayments().get(periodIndex); LocalDate previousAccrualDate = period.getUnadjustedStartDate(); double factorSpot = bond.yearFraction(previousAccrualDate, settlementDate); double factorPeriod = bond.yearFraction(previousAccrualDate, period.getUnadjustedEndDate()); return (factorPeriod - factorSpot) / factorPeriod; }
public void test_accruedInterest_onPayment() { CapitalIndexedBondPaymentPeriod period = PRODUCT.getPeriodicPayments().get(16); LocalDate refDate = period.getPaymentDate(); double computed = PRODUCT.accruedInterest(refDate); assertEquals(computed, 0d, TOL * REAL_COUPON_VALUE * NOTIONAL); }
CurrencyAmount forecastValueStandardFromCleanPrice( ResolvedCapitalIndexedBond product, RatesProvider ratesProvider, LocalDate standardSettlementDate, double realCleanPrice) { double notional = product.getNotional(); double netAmountReal = realCleanPrice * notional + product.accruedInterest(standardSettlementDate); double indexRatio = product.getYieldConvention().equals(CapitalIndexedBondYieldConvention.GB_IL_FLOAT) ? 1d : productPricer.indexRatio(product, ratesProvider, standardSettlementDate); return CurrencyAmount.of(product.getCurrency(), indexRatio * netAmountReal); }
public void test_priceFromRealYield_ukGov() { LocalDate standardSettle = PRODUCT_GOV.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA); double computed = PRICER.cleanPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV); assertEquals(computed, 3.60, 1.e-2); double computedOnePeriod = PRICER.cleanPriceFromRealYield(PRODUCT_GOV_OP, RATES_PROVS_GB, PRODUCT_GOV_OP .getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA), YIELD_GOV_OP); assertEquals(computedOnePeriod, 3.21, 4.e-2); double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV); double cleanPrice = PRICER.cleanNominalPriceFromDirtyNominalPrice( PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyPrice); assertEquals(computed, cleanPrice); double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyPrice); assertEquals(yieldRe, YIELD_GOV, TOL); }
private double currentCashPayment( ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, LocalDate valuationDate) { double cash = 0d; for (CapitalIndexedBondPaymentPeriod period : bond.getPeriodicPayments()) { if (period.getPaymentDate().isEqual(valuationDate)) { cash += periodPricer.forecastValue(period, ratesProvider); } } return cash; }
double indexRatio(ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, LocalDate settlementDate) { LocalDate endReferenceDate = settlementDate.isBefore(ratesProvider.getValuationDate()) ? ratesProvider.getValuationDate() : settlementDate; RateComputation modifiedComputation = bond.getRateCalculation().createRateComputation(endReferenceDate); return 1d + periodPricer.getRateComputationFn().rate( modifiedComputation, bond.getUnadjustedStartDate(), // dates not used bond.getUnadjustedEndDate(), ratesProvider); }
PointSensitivityBuilder forecastValueSensitivityStandardFromCleanPrice( ResolvedCapitalIndexedBond product, RatesProvider ratesProvider, LocalDate standardSettlementDate, double realCleanPrice) { if (product.getYieldConvention().equals(CapitalIndexedBondYieldConvention.GB_IL_FLOAT)) { return PointSensitivityBuilder.none(); } double notional = product.getNotional(); double netAmountReal = realCleanPrice * notional + product.accruedInterest(standardSettlementDate); PointSensitivityBuilder indexRatioSensi = productPricer.indexRatioSensitivity(product, ratesProvider, standardSettlementDate); return indexRatioSensi.multipliedBy(netAmountReal); }
@Override public double yearFraction(LocalDate firstDate, LocalDate secondDate, ScheduleInfo scheduleInfo) { assertEquals(scheduleInfo.getStartDate(), base.getUnadjustedStartDate()); assertEquals(scheduleInfo.getEndDate(), base.getUnadjustedEndDate()); assertEquals(scheduleInfo.getPeriodEndDate(firstDate), period.getUnadjustedEndDate()); assertEquals(scheduleInfo.getFrequency(), base.getFrequency()); assertEquals(scheduleInfo.isEndOfMonthConvention(), eom.get()); return 0.5; }
/** * Calculates the current cash of the bond product. * * @param bond the product * @param ratesProvider the rates provider, used to determine price index values * @param settlementDate the settlement date * @return the current cash of the product */ public CurrencyAmount currentCash( ResolvedCapitalIndexedBond bond, RatesProvider ratesProvider, LocalDate settlementDate) { LocalDate valuationDate = ratesProvider.getValuationDate(); Currency currency = bond.getCurrency(); CurrencyAmount currentCash = CurrencyAmount.zero(currency); if (settlementDate.isBefore(valuationDate)) { double cashCoupon = bond.hasExCouponPeriod() ? 0d : currentCashPayment(bond, ratesProvider, valuationDate); CapitalIndexedBondPaymentPeriod nominal = bond.getNominalPayment(); double cashNominal = nominal.getPaymentDate().isEqual(valuationDate) ? periodPricer.forecastValue(nominal, ratesProvider) : 0d; currentCash = currentCash.plus(CurrencyAmount.of(currency, cashCoupon + cashNominal)); } return currentCash; }