/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ResolvedFixedCouponBond beanToCopy) { this.securityId = beanToCopy.getSecurityId(); this.nominalPayment = beanToCopy.getNominalPayment(); this.periodicPayments = beanToCopy.getPeriodicPayments(); this.frequency = beanToCopy.getFrequency(); this.rollConvention = beanToCopy.getRollConvention(); this.fixedRate = beanToCopy.getFixedRate(); this.dayCount = beanToCopy.getDayCount(); this.yieldConvention = beanToCopy.getYieldConvention(); this.legalEntityId = beanToCopy.getLegalEntityId(); this.settlementDateOffset = beanToCopy.getSettlementDateOffset(); }
static RepoCurveDiscountFactors repoCurveDf(ResolvedFixedCouponBond bond, LegalEntityDiscountingProvider provider) { return provider.repoCurveDiscountFactors(bond.getSecurityId(), bond.getLegalEntityId(), bond.getCurrency()); }
public void test_getters() { ResolvedFixedCouponBond test = sut(); ImmutableList<FixedCouponBondPaymentPeriod> payments = test.getPeriodicPayments(); assertEquals(test.getStartDate(), payments.get(0).getStartDate()); assertEquals(test.getEndDate(), payments.get(payments.size() - 1).getEndDate()); assertEquals(test.getUnadjustedStartDate(), payments.get(0).getUnadjustedStartDate()); assertEquals(test.getUnadjustedEndDate(), payments.get(payments.size() - 1).getUnadjustedEndDate()); assertEquals(test.hasExCouponPeriod(), true); }
static IssuerCurveDiscountFactors issuerCurveDf(ResolvedFixedCouponBond bond, LegalEntityDiscountingProvider provider) { return provider.issuerCurveDiscountFactors(bond.getLegalEntityId(), bond.getCurrency()); }
ImmutableList<FixedCouponBondPaymentPeriod> payments = bond.getPeriodicPayments(); int nCoupon = payments.size() - couponIndex(payments, settlementDate); FixedCouponBondYieldConvention yieldConv = bond.getYieldConvention(); if (nCoupon == 1) { if (yieldConv.equals(US_STREET) || yieldConv.equals(DE_BONDS)) { double couponPerYear = bond.getFrequency().eventsPerYear(); double factorToNextCoupon = factorToNextCoupon(bond, settlementDate); double timeToPay = factorToNextCoupon / couponPerYear; LocalDate maturityDate = bond.getUnadjustedEndDate(); if (settlementDate.isAfter(maturityDate)) { return 0d; double maturity = bond.getDayCount().relativeYearFraction(settlementDate, maturityDate); double num = 1d + bond.getFixedRate() * maturity; double den = 1d + yield * maturity; double dirtyPrice = dirtyPriceFromCleanPrice(bond, settlementDate, num / den);
public void test_presentValue_noExcoupon() { CurrencyAmount computed = PRICER.presentValue(PRODUCT_NO_EXCOUPON, PROVIDER); CurrencyAmount expected = PRICER_NOMINAL.presentValue(PRODUCT.getNominalPayment(), DSC_FACTORS_ISSUER); int size = PRODUCT.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = PRODUCT.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValue(payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER)); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); }
public void test_resolve() { FixedCouponBond base = sut(); ResolvedFixedCouponBond resolved = base.resolve(REF_DATA); assertEquals(resolved.getLegalEntityId(), LEGAL_ENTITY); assertEquals(resolved.getSettlementDateOffset(), DATE_OFFSET); assertEquals(resolved.getYieldConvention(), YIELD_CONVENTION); ImmutableList<FixedCouponBondPaymentPeriod> periodicPayments = resolved.getPeriodicPayments(); int expNum = 20; assertEquals(periodicPayments.size(), expNum); LocalDate unadjustedEnd = END_DATE; Schedule unadjusted = PERIOD_SCHEDULE.createSchedule(REF_DATA).toUnadjusted(); for (int i = 0; i < expNum; ++i) { FixedCouponBondPaymentPeriod payment = periodicPayments.get(expNum - 1 - i); assertEquals(payment.getCurrency(), EUR); assertEquals(payment.getNotional(), NOTIONAL); assertEquals(payment.getFixedRate(), FIXED_RATE); assertEquals(payment.getUnadjustedEndDate(), unadjustedEnd); assertEquals(payment.getEndDate(), BUSINESS_ADJUST.adjust(unadjustedEnd, REF_DATA)); assertEquals(payment.getPaymentDate(), payment.getEndDate()); LocalDate unadjustedStart = unadjustedEnd.minusMonths(6); assertEquals(payment.getUnadjustedStartDate(), unadjustedStart); assertEquals(payment.getStartDate(), BUSINESS_ADJUST.adjust(unadjustedStart, REF_DATA)); assertEquals(payment.getYearFraction(), unadjusted.getPeriod(expNum - 1 - i).yearFraction(DAY_COUNT, unadjusted)); assertEquals(payment.getDetachmentDate(), EX_COUPON.adjust(payment.getPaymentDate(), REF_DATA)); unadjustedEnd = unadjustedStart; } Payment expectedPayment = Payment.of(CurrencyAmount.of(EUR, NOTIONAL), BUSINESS_ADJUST.adjust(END_DATE, REF_DATA)); assertEquals(resolved.getNominalPayment(), expectedPayment); }
private LocalDate standardSettlementDate( ResolvedFixedCouponBond product, LegalEntityDiscountingProvider provider, ReferenceData refData) { return product.getSettlementDateOffset().adjust(provider.getValuationDate(), refData); }
double yield) { int nbCoupon = bond.getPeriodicPayments().size(); double couponPerYear = bond.getFrequency().eventsPerYear(); double factorToNextCoupon = factorToNextCoupon(bond, settlementDate); double factorOnPeriod = 1 + yield / couponPerYear; double nominal = bond.getNotional(); double fixedRate = bond.getFixedRate(); double cvAtFirstCoupon = 0; double pvAtFirstCoupon = 0; int pow = 0; for (int loopcpn = 0; loopcpn < nbCoupon; loopcpn++) { FixedCouponBondPaymentPeriod period = bond.getPeriodicPayments().get(loopcpn); if ((period.hasExCouponPeriod() && !settlementDate.isAfter(period.getDetachmentDate())) || (!period.hasExCouponPeriod() && period.getPaymentDate().isAfter(settlementDate))) {
public void test_findPeriod() { ResolvedFixedCouponBond test = sut(); ImmutableList<FixedCouponBondPaymentPeriod> payments = test.getPeriodicPayments(); assertEquals(test.findPeriod(test.getUnadjustedStartDate()), Optional.of(payments.get(0))); assertEquals(test.findPeriod(test.getUnadjustedEndDate().minusDays(1)), Optional.of(payments.get(payments.size() - 1))); assertEquals(test.findPeriod(LocalDate.MIN), Optional.empty()); assertEquals(test.findPeriod(LocalDate.MAX), Optional.empty()); }
/** * Calculates the yield of the fixed coupon bond product from dirty price. * <p> * The dirty price must be fractional. * If the analytic formula is not available, the yield is computed by solving * a root-finding problem with {@link #dirtyPriceFromYield(ResolvedFixedCouponBond, LocalDate, double)}. * The result is also expressed in fraction. * * @param bond the product * @param settlementDate the settlement date * @param dirtyPrice the dirty price * @return the yield of the product */ public double yieldFromDirtyPrice(ResolvedFixedCouponBond bond, LocalDate settlementDate, double dirtyPrice) { if (bond.getYieldConvention().equals(JP_SIMPLE)) { double cleanPrice = cleanPriceFromDirtyPrice(bond, settlementDate, dirtyPrice); LocalDate maturityDate = bond.getUnadjustedEndDate(); double maturity = bond.getDayCount().relativeYearFraction(settlementDate, maturityDate); return (bond.getFixedRate() + (1d - cleanPrice) / maturity) / cleanPrice; } final Function<Double, Double> priceResidual = new Function<Double, Double>() { @Override public Double apply(final Double y) { return dirtyPriceFromYield(bond, settlementDate, y) - dirtyPrice; } }; double[] range = ROOT_BRACKETER.getBracketedPoints(priceResidual, 0.00, 0.20); double yield = ROOT_FINDER.getRoot(priceResidual, range[0], range[1]); return yield; }
/** * Calculates the Macaulay duration of the fixed coupon bond product from yield. * <p> * Macaulay defined an alternative way of weighting the future cash flows. * <p> * The input yield must be fractional. The dirty price and its derivative are * computed for {@link FixedCouponBondYieldConvention}, and the result is expressed in fraction. * * @param bond the product * @param settlementDate the settlement date * @param yield the yield * @return the modified duration of the product */ public double macaulayDurationFromYield(ResolvedFixedCouponBond bond, LocalDate settlementDate, double yield) { ImmutableList<FixedCouponBondPaymentPeriod> payments = bond.getPeriodicPayments(); int nCoupon = payments.size() - couponIndex(payments, settlementDate); FixedCouponBondYieldConvention yieldConv = bond.getYieldConvention(); if ((yieldConv.equals(US_STREET)) && (nCoupon == 1)) { return factorToNextCoupon(bond, settlementDate) / bond.getFrequency().eventsPerYear(); } if ((yieldConv.equals(US_STREET)) || (yieldConv.equals(GB_BUMP_DMO)) || (yieldConv.equals(DE_BONDS))) { return modifiedDurationFromYield(bond, settlementDate, yield) * (1d + yield / bond.getFrequency().eventsPerYear()); } throw new UnsupportedOperationException("The convention " + yieldConv.name() + " is not supported."); }
private double factorToNextCoupon(ResolvedFixedCouponBond bond, LocalDate settlementDate) { if (bond.getPeriodicPayments().get(0).getStartDate().isAfter(settlementDate)) { return 0d; } int couponIndex = couponIndex(bond.getPeriodicPayments(), settlementDate); double factorSpot = accruedYearFraction(bond, settlementDate); double factorPeriod = bond.getPeriodicPayments().get(couponIndex).getYearFraction(); return (factorPeriod - factorSpot) / factorPeriod; }
private double dirtyPriceFromYieldStandard( ResolvedFixedCouponBond bond, LocalDate settlementDate, double yield) { int nbCoupon = bond.getPeriodicPayments().size(); double factorOnPeriod = 1 + yield / ((double) bond.getFrequency().eventsPerYear()); double fixedRate = bond.getFixedRate(); double pvAtFirstCoupon = 0; int pow = 0; for (int loopcpn = 0; loopcpn < nbCoupon; loopcpn++) { FixedCouponBondPaymentPeriod period = bond.getPeriodicPayments().get(loopcpn); if ((period.hasExCouponPeriod() && !settlementDate.isAfter(period.getDetachmentDate())) || (!period.hasExCouponPeriod() && period.getPaymentDate().isAfter(settlementDate))) { pvAtFirstCoupon += fixedRate * period.getYearFraction() / Math.pow(factorOnPeriod, pow); ++pow; } } pvAtFirstCoupon += 1d / Math.pow(factorOnPeriod, pow - 1); return pvAtFirstCoupon * Math.pow(factorOnPeriod, -factorToNextCoupon(bond, settlementDate)); }
private CurrencyAmount presentValueCoupon( ResolvedFixedCouponBond bond, IssuerCurveDiscountFactors discountFactors, LocalDate referenceDate) { double total = 0d; for (FixedCouponBondPaymentPeriod period : bond.getPeriodicPayments()) { if (period.getDetachmentDate().isAfter(referenceDate)) { total += periodPricer.presentValue(period, discountFactors); } } return CurrencyAmount.of(bond.getCurrency(), total); }
@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 payment that was made for the trade. * <p> * This is the payment that was made on the settlement date, based on the quantity and clean price. * * @param trade the trade * @return the payment that was made */ public Payment upfrontPayment(ResolvedFixedCouponBondTrade trade) { ResolvedFixedCouponBond product = trade.getProduct(); Currency currency = product.getCurrency(); if (!trade.getSettlement().isPresent()) { return Payment.of(CurrencyAmount.zero(currency), product.getStartDate()); // date doesn't matter as it is zero } // payment is based on the dirty price ResolvedFixedCouponBondSettlement settlement = trade.getSettlement().get(); LocalDate settlementDate = settlement.getSettlementDate(); double cleanPrice = settlement.getPrice(); double dirtyPrice = productPricer.dirtyPriceFromCleanPrice(product, settlementDate, cleanPrice); // calculate payment double quantity = trade.getQuantity(); double notional = product.getNotional(); return Payment.of(CurrencyAmount.of(currency, -quantity * notional * dirtyPrice), settlementDate); }
@ImmutableValidator private void validate() { int size = deliveryBasket.size(); ArgChecker.isTrue(size == conversionFactors.size(), "The delivery basket size should be the same as the conversion factor size"); ArgChecker.inOrderOrEqual(firstNoticeDate, lastNoticeDate, "firstNoticeDate", "lastNoticeDate"); ArgChecker.inOrderOrEqual(firstDeliveryDate, lastDeliveryDate, "firstDeliveryDate", "lastDeliveryDate"); ArgChecker.inOrderOrEqual(firstNoticeDate, firstDeliveryDate, "firstNoticeDate", "firstDeliveryDate"); ArgChecker.inOrderOrEqual(lastNoticeDate, lastDeliveryDate, "lastNoticeDate", "lastDeliveryDate"); if (size > 1) { double notional = getNotional(); Currency currency = getCurrency(); for (int i = 1; i < size; ++i) { ArgChecker.isTrue(deliveryBasket.get(i).getNotional() == notional); ArgChecker.isTrue(deliveryBasket.get(i).getCurrency().equals(currency)); } } }
private PointSensitivityBuilder presentValueSensitivityNominal( ResolvedFixedCouponBond bond, IssuerCurveDiscountFactors discountFactors) { Payment nominal = bond.getNominalPayment(); PointSensitivityBuilder pt = nominalPricer.presentValueSensitivity(nominal, discountFactors.getDiscountFactors()); if (pt instanceof ZeroRateSensitivity) { return IssuerCurveZeroRateSensitivity.of((ZeroRateSensitivity) pt, discountFactors.getLegalEntityGroup()); } return pt; // NoPointSensitivity }
/** * Calculates the accrued year fraction of the fixed coupon bond with the specified settlement date. * * @param bond the product * @param settlementDate the settlement date * @return the accrued year fraction of the product */ public double accruedYearFraction(ResolvedFixedCouponBond bond, LocalDate settlementDate) { if (bond.getUnadjustedStartDate().isAfter(settlementDate)) { return 0d; } FixedCouponBondPaymentPeriod period = bond.findPeriod(settlementDate) .orElseThrow(() -> new IllegalArgumentException("Date outside range of bond")); LocalDate previousAccrualDate = period.getUnadjustedStartDate(); double accruedYearFraction = bond.yearFraction(previousAccrualDate, settlementDate); double result = 0d; if (settlementDate.isAfter(period.getDetachmentDate())) { result = accruedYearFraction - period.getYearFraction(); } else { result = accruedYearFraction; } return result; }