/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.bond.provider;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.Test;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.temporal.JulianFields;
import com.opengamma.analytics.financial.instrument.bond.BondFixedSecurityDefinition;
import com.opengamma.analytics.financial.instrument.payment.CouponFixedDefinition;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityCouponFixed;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityPaymentFixed;
import com.opengamma.analytics.financial.interestrate.bond.calculator.CleanPriceFromYieldCalculator;
import com.opengamma.analytics.financial.interestrate.bond.calculator.DirtyPriceFromYieldCalculator;
import com.opengamma.analytics.financial.interestrate.bond.calculator.MacaulayDurationFromYieldCalculator;
import com.opengamma.analytics.financial.interestrate.bond.calculator.ModifiedDurationFromPriceCalculator;
import com.opengamma.analytics.financial.interestrate.bond.calculator.ModifiedDurationFromYieldCalculator;
import com.opengamma.analytics.financial.interestrate.bond.calculator.YieldFromPriceCalculator;
import com.opengamma.analytics.financial.interestrate.bond.definition.BondFixedSecurity;
import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.CleanPriceFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.ConvexityFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.DirtyPriceFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.MacaulayDurationFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.ModifiedDurationFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.PresentValueIssuerCalculator;
import com.opengamma.analytics.financial.provider.calculator.issuer.YieldFromCurvesCalculator;
import com.opengamma.analytics.financial.provider.description.IssuerProviderDiscountDataSets;
import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderDiscount;
import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderInterface;
import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderIssuerDecoratedSpread;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscountingDecoratedIssuer;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity;
import com.opengamma.analytics.financial.schedule.ScheduleCalculator;
import com.opengamma.analytics.util.time.TimeCalculator;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConventionFactory;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.calendar.MondayToFridayCalendar;
import com.opengamma.financial.convention.daycount.DayCount;
import com.opengamma.financial.convention.daycount.DayCountFactory;
import com.opengamma.financial.convention.yield.YieldConvention;
import com.opengamma.financial.convention.yield.YieldConventionFactory;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.time.DateUtils;
/**
* Tests related to the discounting method for bond security.
*/
public class BondSecurityDiscountingMethodTest {
private final static IssuerProviderDiscount ISSUER_MULTICURVES = IssuerProviderDiscountDataSets.createIssuerProvider();
private final static String[] ISSUER_NAMES = IssuerProviderDiscountDataSets.getIssuerNames();
// T 4 5/8 11/15/16 - ISIN - US912828FY19
private static final String ISSUER = ISSUER_NAMES[0];
private static final Currency CUR = Currency.USD;
private static final Calendar CALENDAR = new MondayToFridayCalendar("A");
private static final Period PAYMENT_TENOR_FIXED = Period.ofMonths(6);
private static final int COUPON_PER_YEAR = 2;
private static final DayCount DAY_COUNT_FIXED = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ICMA");
private static final BusinessDayConvention BUSINESS_DAY_FIXED = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Following");
private static final boolean IS_EOM_FIXED = false;
private static final Period BOND_TENOR_FIXED = Period.ofYears(10);
private static final int SETTLEMENT_DAYS = 3;
private static final ZonedDateTime START_ACCRUAL_DATE_FIXED = DateUtils.getUTCDate(2006, 11, 15);
private static final ZonedDateTime MATURITY_DATE_FIXED = START_ACCRUAL_DATE_FIXED.plus(BOND_TENOR_FIXED);
private static final double RATE_FIXED = 0.04625;
private static final double NOTIONAL = 100;
private static final YieldConvention YIELD_CONVENTION_FIXED = YieldConventionFactory.INSTANCE.getYieldConvention("STREET CONVENTION");
private static final BondFixedSecurityDefinition BOND_FIXED_SECURITY_DEFINITION = BondFixedSecurityDefinition.from(CUR, MATURITY_DATE_FIXED, START_ACCRUAL_DATE_FIXED, PAYMENT_TENOR_FIXED,
RATE_FIXED, SETTLEMENT_DAYS, NOTIONAL, CALENDAR, DAY_COUNT_FIXED, BUSINESS_DAY_FIXED, YIELD_CONVENTION_FIXED, IS_EOM_FIXED, ISSUER, "RepoType");
// To derivatives
// Spot: middle coupon
private static final ZonedDateTime REFERENCE_DATE_1 = DateUtils.getUTCDate(2011, 8, 18);
private static final ZonedDateTime SPOT_1 = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE_1, SETTLEMENT_DAYS, CALENDAR);
private static final double REFERENCE_TIME_1 = TimeCalculator.getTimeBetween(REFERENCE_DATE_1, SPOT_1);
private static final BondFixedSecurity BOND_FIXED_SECURITY_1 = BOND_FIXED_SECURITY_DEFINITION.toDerivative(REFERENCE_DATE_1);
// Spot: on coupon date
private static final ZonedDateTime REFERENCE_DATE_2 = DateUtils.getUTCDate(2012, 1, 10);
private static final ZonedDateTime SPOT_2 = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE_2, SETTLEMENT_DAYS, CALENDAR);
private static final double REFERENCE_TIME_2 = TimeCalculator.getTimeBetween(REFERENCE_DATE_2, SPOT_2);
private static final BondFixedSecurity BOND_FIXED_SECURITY_2 = BOND_FIXED_SECURITY_DEFINITION.toDerivative(REFERENCE_DATE_2);
// Spot: one day after coupon date
// Calculators
private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance();
private static final PresentValueIssuerCalculator PVIC = PresentValueIssuerCalculator.getInstance();
private static final BondSecurityDiscountingMethod METHOD_BOND_SECURITY = BondSecurityDiscountingMethod.getInstance();
private final static YieldFromCurvesCalculator YFCC = YieldFromCurvesCalculator.getInstance();
private final static YieldFromPriceCalculator YFPC = YieldFromPriceCalculator.getInstance();
private final static ModifiedDurationFromCurvesCalculator MDFC = ModifiedDurationFromCurvesCalculator.getInstance();
private static final ModifiedDurationFromPriceCalculator MDFP = ModifiedDurationFromPriceCalculator.getInstance();
private static final ModifiedDurationFromYieldCalculator MDFY = ModifiedDurationFromYieldCalculator.getInstance();
private static final MacaulayDurationFromCurvesCalculator McDFC = MacaulayDurationFromCurvesCalculator.getInstance();
private static final MacaulayDurationFromYieldCalculator McDFY = MacaulayDurationFromYieldCalculator.getInstance();
private static final DirtyPriceFromYieldCalculator DPFY = DirtyPriceFromYieldCalculator.getInstance();
private static final DirtyPriceFromCurvesCalculator DPFC = DirtyPriceFromCurvesCalculator.getInstance();
private static final ConvexityFromCurvesCalculator CFC = ConvexityFromCurvesCalculator.getInstance();
private static final CleanPriceFromYieldCalculator CPFY = CleanPriceFromYieldCalculator.getInstance();
private static final CleanPriceFromCurvesCalculator CPFC = CleanPriceFromCurvesCalculator.getInstance();
private static final double TOLERANCE_PV = 1.0E-8;
private static final double TOLERANCE_PV_DELTA = 1.0E-4;
private static final double TOLERANCE_PRICE = 1.0E-8;
private static final double TOLERANCE_YIELD = 1.0E-8;
@Test
public void presentValueFixedMiddle() {
final AnnuityPaymentFixed nominal = (AnnuityPaymentFixed) BOND_FIXED_SECURITY_DEFINITION.getNominal().toDerivative(REFERENCE_DATE_1);
AnnuityCouponFixed coupon = BOND_FIXED_SECURITY_DEFINITION.getCoupons().toDerivative(REFERENCE_DATE_1);
coupon = coupon.trimBefore(REFERENCE_TIME_1);
final MulticurveProviderInterface multicurvesDecorated = new MulticurveProviderDiscountingDecoratedIssuer(ISSUER_MULTICURVES, CUR, ISSUER);
final MultipleCurrencyAmount pvNominal = nominal.accept(PVDC, multicurvesDecorated);
final MultipleCurrencyAmount pvCoupon = coupon.accept(PVDC, multicurvesDecorated);
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: present value", pvNominal.getAmount(CUR) + pvCoupon.getAmount(CUR), pv.getAmount(CUR), TOLERANCE_PV);
}
@Test
public void presentValueFixedOnCoupon() {
final AnnuityPaymentFixed nominal = (AnnuityPaymentFixed) BOND_FIXED_SECURITY_DEFINITION.getNominal().toDerivative(REFERENCE_DATE_2);
AnnuityCouponFixed coupon = BOND_FIXED_SECURITY_DEFINITION.getCoupons().toDerivative(REFERENCE_DATE_2);
coupon = coupon.trimBefore(REFERENCE_TIME_2);
final MulticurveProviderInterface multicurvesDecorated = new MulticurveProviderDiscountingDecoratedIssuer(ISSUER_MULTICURVES, CUR, ISSUER);
final MultipleCurrencyAmount pvNominal = nominal.accept(PVDC, multicurvesDecorated);
final MultipleCurrencyAmount pvCoupon = coupon.accept(PVDC, multicurvesDecorated);
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_2, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: present value", pvNominal.getAmount(CUR) + pvCoupon.getAmount(CUR), pv.getAmount(CUR), TOLERANCE_PV);
}
@Test
public void presentValueFixedMethodVsCalculator() {
final MultipleCurrencyAmount pvMethod = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final MultipleCurrencyAmount pvCalculator = BOND_FIXED_SECURITY_1.accept(PVIC, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: present value Method vs Calculator", pvMethod.getAmount(CUR), pvCalculator.getAmount(CUR), TOLERANCE_PV);
}
@Test
/**
* Tests the present value from curves and a z-spread.
*/
public void presentValueFromZSpread() {
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
double zSpread = 0.0;
MultipleCurrencyAmount pvZ = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
assertEquals("Fixed coupon bond security: present value from z-spread", pv.getAmount(CUR), pvZ.getAmount(CUR), TOLERANCE_PV);
IssuerProviderInterface issuerShifted = new IssuerProviderIssuerDecoratedSpread(ISSUER_MULTICURVES, BOND_FIXED_SECURITY_1.getIssuerCcy(), zSpread);
MultipleCurrencyAmount pvZExpected = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, issuerShifted);
assertEquals("Fixed coupon bond security: present value from z-spread", pvZExpected.getAmount(CUR), pvZ.getAmount(CUR), TOLERANCE_PV);
zSpread = 0.0010; // 10bps
issuerShifted = new IssuerProviderIssuerDecoratedSpread(ISSUER_MULTICURVES, BOND_FIXED_SECURITY_1.getIssuerCcy(), zSpread);
pvZ = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
pvZExpected = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, issuerShifted);
assertEquals("Fixed coupon bond security: present value from z-spread", pvZExpected.getAmount(CUR), pvZ.getAmount(CUR), TOLERANCE_PV);
}
@Test
/**
* Tests the present value z-spread sensitivity.
*/
public void presentValueZSpreadSensitivity() {
final double zSpread = 0.0050; // 50bps
final double shift = 1.0E-5;
final double pvzs = METHOD_BOND_SECURITY.presentValueZSpreadSensitivity(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
final MultipleCurrencyAmount pvZUp = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread + shift);
final MultipleCurrencyAmount pvZDown = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread - shift);
assertEquals("Fixed coupon bond security: present value z-spread sensitivity", (pvZUp.getAmount(CUR) - pvZDown.getAmount(CUR)) / (2 * shift), pvzs, TOLERANCE_PV_DELTA);
}
@Test
/**
* Tests the bond security present value from clean price.
*/
public void presentValueFromCleanPrice() {
final double cleanPrice = METHOD_BOND_SECURITY.cleanPriceFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final MultipleCurrencyAmount pvClean = METHOD_BOND_SECURITY.presentValueFromCleanPrice(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES.getMulticurveProvider(), cleanPrice);
final MultipleCurrencyAmount pvCleanExpected = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: present value", pvCleanExpected.getAmount(CUR), pvClean.getAmount(CUR), TOLERANCE_PV);
}
@Test
/**
* Tests the z-spread computation from the present value.
*/
public void zSpreadFromPresentValue() {
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double zSpread = METHOD_BOND_SECURITY.zSpreadFromCurvesAndPV(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, pv);
assertEquals("Fixed coupon bond security: present value from z-spread", 0.0, zSpread, TOLERANCE_PV);
final double zSpreadExpected = 0.0025; // 25bps
final MultipleCurrencyAmount pvZSpread = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpreadExpected);
final double zSpread2 = METHOD_BOND_SECURITY.zSpreadFromCurvesAndPV(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, pvZSpread);
assertEquals("Fixed coupon bond security: present value from z-spread", zSpreadExpected, zSpread2, TOLERANCE_PV);
final double zSpreadExpected3 = 0.0250; // 2.50%
final MultipleCurrencyAmount pvZSpread3 = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpreadExpected3);
final double zSpread3 = METHOD_BOND_SECURITY.zSpreadFromCurvesAndPV(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, pvZSpread3);
assertEquals("Fixed coupon bond security: present value from z-spread", zSpreadExpected3, zSpread3, TOLERANCE_PV);
}
@Test
/**
* Tests the z-spread sensitivity computation from the present value.
*/
public void zSpreadSensitivityFromPresentValue() {
final double zSpread = 0.0025; // 25bps
final MultipleCurrencyAmount pvZSpread = METHOD_BOND_SECURITY.presentValueFromZSpread(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
final double zsComputed = METHOD_BOND_SECURITY.presentValueZSpreadSensitivityFromCurvesAndPV(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, pvZSpread);
final double zsExpected = METHOD_BOND_SECURITY.presentValueZSpreadSensitivity(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
assertEquals("Fixed coupon bond security: z-spread sensitivity", zsExpected, zsComputed, TOLERANCE_PV);
}
@Test
/**
* Tests the z-spread computation from the clean price.
*/
public void zSpreadFromCleanPrice() {
final double zSpreadExpected = 0.0025; // 25bps
final IssuerProviderInterface issuerShifted = new IssuerProviderIssuerDecoratedSpread(ISSUER_MULTICURVES, BOND_FIXED_SECURITY_1.getIssuerCcy(), zSpreadExpected);
final double cleanZSpread = METHOD_BOND_SECURITY.cleanPriceFromCurves(BOND_FIXED_SECURITY_1, issuerShifted);
final double zSpread = METHOD_BOND_SECURITY.zSpreadFromCurvesAndClean(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, cleanZSpread);
assertEquals("Fixed coupon bond security: present value from z-spread", zSpreadExpected, zSpread, TOLERANCE_PV);
}
@Test
/**
* Tests the z-spread sensitivity computation from the present value.
*/
public void zSpreadSensitivityFromCleanPrice() {
final double zSpread = 0.0025; // 25bps
final IssuerProviderInterface issuerShifted = new IssuerProviderIssuerDecoratedSpread(ISSUER_MULTICURVES, BOND_FIXED_SECURITY_1.getIssuerCcy(), zSpread);
final double cleanZSpread = METHOD_BOND_SECURITY.cleanPriceFromCurves(BOND_FIXED_SECURITY_1, issuerShifted);
final double zsComputed = METHOD_BOND_SECURITY.presentValueZSpreadSensitivityFromCurvesAndClean(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, cleanZSpread);
final double zsExpected = METHOD_BOND_SECURITY.presentValueZSpreadSensitivity(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES, zSpread);
assertEquals("Fixed coupon bond security: z-spread sensitivity", zsExpected, zsComputed, TOLERANCE_PV);
}
@Test
public void dirtyPriceFixed() {
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double df = ISSUER_MULTICURVES.getMulticurveProvider().getDiscountFactor(CUR, REFERENCE_TIME_1);
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: dirty price from curves", pv.getAmount(CUR) / df / BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getNotional(), dirty);
assertTrue("Fixed coupon bond security: dirty price is relative price", (0.50 < dirty) & (dirty < 2.0));
}
@Test
public void cleanPriceFixed() {
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double clean = METHOD_BOND_SECURITY.cleanPriceFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: clean price from curves", dirty - BOND_FIXED_SECURITY_1.getAccruedInterest() / BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getNotional(), clean);
}
@Test
public void cleanAndDirtyPriceFixed() {
final double cleanPrice = 0.90;
final double accruedInterest = BOND_FIXED_SECURITY_1.getAccruedInterest() / BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getNotional();
assertEquals("Fixed coupon bond security", cleanPrice + accruedInterest, METHOD_BOND_SECURITY.dirtyPriceFromCleanPrice(BOND_FIXED_SECURITY_1, cleanPrice));
final double dirtyPrice = 0.95;
assertEquals("Fixed coupon bond security", dirtyPrice - accruedInterest, METHOD_BOND_SECURITY.cleanPriceFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice));
assertEquals("Fixed coupon bond security", cleanPrice,
METHOD_BOND_SECURITY.cleanPriceFromDirtyPrice(BOND_FIXED_SECURITY_1, METHOD_BOND_SECURITY.dirtyPriceFromCleanPrice(BOND_FIXED_SECURITY_1, cleanPrice)));
}
@Test
public void dirtyPriceFromYieldUSStreet() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double dirtyPriceExpected = 1.04173525; // To be check with another source.
assertEquals("Fixed coupon bond security: dirty price from yield", dirtyPriceExpected, dirtyPrice, TOLERANCE_PRICE);
}
@Test
public void cleanPriceFromYieldUSStreet() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double cleanPriceExpected = METHOD_BOND_SECURITY.cleanPriceFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double cleanPrice = METHOD_BOND_SECURITY.cleanPriceFromYield(BOND_FIXED_SECURITY_1, yield);
assertEquals("Fixed coupon bond security: dirty price from yield", cleanPriceExpected, cleanPrice, TOLERANCE_PRICE);
}
@Test
public void dirtyPriceFromYieldUSStreetLastPeriod() {
final ZonedDateTime referenceDate = DateUtils.getUTCDate(2016, 6, 3); // In last period
final BondFixedSecurity bondSecurity = BOND_FIXED_SECURITY_DEFINITION.toDerivative(referenceDate);
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(bondSecurity, yield);
final double dirtyPriceExpected = (1 + RATE_FIXED / COUPON_PER_YEAR) / (1 + bondSecurity.getAccrualFactorToNextCoupon() * yield / COUPON_PER_YEAR);
assertEquals("Fixed coupon bond security: dirty price from yield US Street - last period", dirtyPriceExpected, dirtyPrice, TOLERANCE_PRICE);
}
@Test
public void yieldFromDirtyPriceUSStreet() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double yieldComputed = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
assertEquals("Fixed coupon bond security: yield from dirty price", yield, yieldComputed, TOLERANCE_YIELD);
}
@Test
public void yieldFromCurvesUSStreet() {
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double yieldExpected = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double yieldComputed = METHOD_BOND_SECURITY.yieldFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: yield from dirty price", yieldExpected, yieldComputed, TOLERANCE_YIELD);
}
@Test
public void yieldFromCleanPriceUSStreet() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double cleanPrice = METHOD_BOND_SECURITY.cleanPriceFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double yieldComputed = METHOD_BOND_SECURITY.yieldFromCleanPrice(BOND_FIXED_SECURITY_1, cleanPrice);
assertEquals("Fixed coupon bond security: yield from clean price", yield, yieldComputed, TOLERANCE_YIELD);
final double cleanPrice2 = METHOD_BOND_SECURITY.cleanPriceFromYield(BOND_FIXED_SECURITY_1, yieldComputed);
assertEquals("Fixed coupon bond security: yield from clean price", cleanPrice, cleanPrice2, TOLERANCE_YIELD);
}
@Test
public void modifiedDurationFromYieldUSStreet() {
final double yield = 0.04;
final double modifiedDuration = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double modifiedDurationExpected = 4.566199225; // To be check with another source.
assertEquals("Fixed coupon bond security: modified duration from yield US Street - hard coded value", modifiedDurationExpected, modifiedDuration, TOLERANCE_PRICE);
final double shift = 1.0E-6;
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double dirtyP = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield + shift);
final double dirtyM = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield - shift);
final double modifiedDurationFD = -(dirtyP - dirtyM) / (2 * shift) / dirty;
assertEquals("Fixed coupon bond security: modified duration from yield US Street - finite difference", modifiedDurationFD, modifiedDuration, TOLERANCE_PRICE);
}
@Test
public void modifiedDurationFromCurvesUSStreet() {
final double yield = METHOD_BOND_SECURITY.yieldFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double modifiedDurationExpected = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double modifiedDuration = METHOD_BOND_SECURITY.modifiedDurationFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: modified duration from curves US Street", modifiedDurationExpected, modifiedDuration, TOLERANCE_PRICE);
}
@Test
public void modifiedDurationFromDirtyPriceUSStreet() {
final double dirtyPrice = 0.95;
final double yield = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double modifiedDurationExpected = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double modifiedDuration = METHOD_BOND_SECURITY.modifiedDurationFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
assertEquals("Fixed coupon bond security: modified duration from curves US Street", modifiedDurationExpected, modifiedDuration, TOLERANCE_PRICE);
}
@Test
public void modifiedDurationFromYieldUSStreetLastPeriod() {
final ZonedDateTime referenceDate = DateUtils.getUTCDate(2016, 6, 3); // In last period
final BondFixedSecurity bondSecurity = BOND_FIXED_SECURITY_DEFINITION.toDerivative(referenceDate);
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.modifiedDurationFromYield(bondSecurity, yield);
final double dirtyPriceExpected = bondSecurity.getAccrualFactorToNextCoupon() / COUPON_PER_YEAR / (1 + bondSecurity.getAccrualFactorToNextCoupon() * yield / COUPON_PER_YEAR);
assertEquals("Fixed coupon bond security: modified duration from yield US Street - last period", dirtyPriceExpected, dirtyPrice, TOLERANCE_PRICE);
}
@Test
/**
* Tests Macauley duration vs a hard coded value (US Street convention).
*/
public void macauleyDurationFromYieldUSStreet() {
final double yield = 0.04;
final double mc = METHOD_BOND_SECURITY.macaulayDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double mcExpected = 4.851906106 / dirty;
assertEquals("Fixed coupon bond security: Macauley duration from yield US Street: harcoded value", mcExpected, mc, 1E-8);
final double md = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_1, yield);
assertEquals("Fixed coupon bond security: Macauley duration from yield US Street: vs modified duration", md * (1 + yield / COUPON_PER_YEAR), mc, 1E-8);
}
@Test
/**
* Tests Macauley duration from the curves (US Street convention).
*/
public void macauleyDurationFromCurvesUSStreet() {
final double yield = METHOD_BOND_SECURITY.yieldFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double macauleyDurationExpected = METHOD_BOND_SECURITY.macaulayDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double macauleyDuration = METHOD_BOND_SECURITY.macaulayDurationFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: Macauley duration from curves US Street", macauleyDurationExpected, macauleyDuration, 1E-8);
}
@Test
/**
* Tests Macauley duration from a dirty price (US Street convention).
*/
public void macauleyDurationFromDirtyPriceUSStreet() {
final double dirtyPrice = 0.95;
final double yield = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double macauleyDurationExpected = METHOD_BOND_SECURITY.macaulayDurationFromYield(BOND_FIXED_SECURITY_1, yield);
final double macauleyDuration = METHOD_BOND_SECURITY.macaulayDurationFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
assertEquals("Fixed coupon bond security: Macauley duration from curves US Street", macauleyDurationExpected, macauleyDuration, 1E-8);
}
@Test
/**
* Tests convexity vs a hard coded value (US Street convention).
*/
public void convexityDurationFromYieldUSStreet() {
final double yield = 0.04;
final double cv = METHOD_BOND_SECURITY.convexityFromYield(BOND_FIXED_SECURITY_1, yield);
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield);
final double cvExpected = 25.75957016 / dirty;
assertEquals("Fixed coupon bond security: Macauley duration from yield US Street: harcoded value", cvExpected, cv, 1E-8);
final double shift = 1.0E-6;
final double dirtyP = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield + shift);
final double dirtyM = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_1, yield - shift);
final double cvFD = (dirtyP + dirtyM - 2 * dirty) / (shift * shift) / dirty;
assertEquals("Fixed coupon bond security: modified duration from yield US Street - finite difference", cvFD, cv, 1E-2);
}
@Test
/**
* Tests convexity from the curves (US Street convention).
*/
public void convexityFromCurvesUSStreet() {
final double yield = METHOD_BOND_SECURITY.yieldFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double convexityExpected = METHOD_BOND_SECURITY.convexityFromYield(BOND_FIXED_SECURITY_1, yield);
final double convexity = METHOD_BOND_SECURITY.convexityFromCurves(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: convexity from curves US Street", convexityExpected, convexity, 1E-8);
}
@Test
/**
* Tests convexity from a dirty price (US Street convention).
*/
public void convexityFromDirtyPriceUSStreet() {
final double dirtyPrice = 0.95;
final double yield = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
final double convexityExpected = METHOD_BOND_SECURITY.convexityFromYield(BOND_FIXED_SECURITY_1, yield);
final double convexity = METHOD_BOND_SECURITY.convexityFromDirtyPrice(BOND_FIXED_SECURITY_1, dirtyPrice);
assertEquals("Fixed coupon bond security: convexity from curves US Street", convexityExpected, convexity, 1E-8);
}
@Test
public void dirtyPriceCurveSensitivity() {
MulticurveSensitivity sensi = METHOD_BOND_SECURITY.dirtyPriceCurveSensitivity(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES).cleaned();
sensi = sensi.cleaned();
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_1, ISSUER_MULTICURVES);
final double dfSettle = ISSUER_MULTICURVES.getMulticurveProvider().getDiscountFactor(CUR, BOND_FIXED_SECURITY_1.getSettlementTime());
final String DSC_CURVE_NAME = ISSUER_MULTICURVES.getMulticurveProvider().getName(CUR);
final String ISS_CURVE_NAME = ISSUER_MULTICURVES.getName(BOND_FIXED_SECURITY_1.getIssuerCcy());
assertEquals("Fixed coupon bond security: dirty price curve sensitivity: risk-less curve", BOND_FIXED_SECURITY_1.getSettlementTime(), sensi.getYieldDiscountingSensitivities().get(DSC_CURVE_NAME)
.get(0).first, TOLERANCE_PV_DELTA);
assertEquals("Fixed coupon bond security: dirty price curve sensitivity: risk-less curve", BOND_FIXED_SECURITY_1.getSettlementTime() / dfSettle * pv.getAmount(CUR) / NOTIONAL, sensi
.getYieldDiscountingSensitivities().get(DSC_CURVE_NAME).get(0).second, TOLERANCE_PV_DELTA);
final double dfCpn0 = ISSUER_MULTICURVES.getMulticurveProvider().getDiscountFactor(BOND_FIXED_SECURITY_1.getCurrency(), BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getPaymentTime());
assertEquals("Fixed coupon bond security: dirty price curve sensitivity: repo curve", BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getPaymentTime(), sensi.getYieldDiscountingSensitivities()
.get(ISS_CURVE_NAME).get(0).first, TOLERANCE_PV_DELTA);
assertEquals("Fixed coupon bond security: dirty price curve sensitivity: repo curve", -BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getPaymentTime()
* BOND_FIXED_SECURITY_1.getCoupon().getNthPayment(0).getAmount() * dfCpn0 / dfSettle / NOTIONAL, sensi.getYieldDiscountingSensitivities().get(ISS_CURVE_NAME).get(0).second, TOLERANCE_PV_DELTA);
}
@Test
/**
* Tests that the clean price for consecutive dates in the future are relatively smooth (no jump die to miscalculated accrued or missing coupon).
*/
public void cleanPriceSmoothness() {
final int nbDateForward = 150;
final ZonedDateTime[] forwardDate = new ZonedDateTime[nbDateForward];
forwardDate[0] = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE_2, SETTLEMENT_DAYS, CALENDAR); //Spot
final long[] jumpDays = new long[nbDateForward - 1];
for (int loopdate = 1; loopdate < nbDateForward; loopdate++) {
forwardDate[loopdate] = ScheduleCalculator.getAdjustedDate(forwardDate[loopdate - 1], 1, CALENDAR);
jumpDays[loopdate - 1] = forwardDate[loopdate].getLong(JulianFields.MODIFIED_JULIAN_DAY) -
forwardDate[loopdate - 1].getLong(JulianFields.MODIFIED_JULIAN_DAY);
}
final double[] cleanPriceForward = new double[nbDateForward];
for (int loopdate = 0; loopdate < nbDateForward; loopdate++) {
final BondFixedSecurity bondForward = BOND_FIXED_SECURITY_DEFINITION.toDerivative(REFERENCE_DATE_2, forwardDate[loopdate]);
cleanPriceForward[loopdate] = METHOD_BOND_SECURITY.cleanPriceFromCurves(bondForward, ISSUER_MULTICURVES);
}
//Test note: 0.03425 is roughly the difference between the coupon and the risk/free rate. The clean price is decreasing naturally by this amount divided by (roughly) 365 every day.
//Test note: On the coupon date there is a jump in the clean price: If the coupon is included the clean price due to coupon is 0.04625/2*exp(-t*0.0100)*exp(t*0.0120) - 0.04625/2 = 1.59276E-05;
// if the coupon is not included the impact is 0 (t=?). The clean price is thus expected to jump by the above amount when the settlement is on the coupon date 15-May-2012.
final double couponJump = 1.59276E-05;
for (int loopdate = 1; loopdate < nbDateForward; loopdate++) {
assertEquals("Fixed coupon bond security: clean price smoothness " + loopdate, cleanPriceForward[loopdate] - (loopdate == 87 ? couponJump : 0.0), cleanPriceForward[loopdate - 1]
- jumpDays[loopdate - 1] * (0.03425 / 365.0), 3.0E-5);
}
}
// UKT 5 09/07/14 - ISIN-GB0031829509 To check figures in the ex-dividend period
private static final String ISSUER_UK = ISSUER_NAMES[3];
private static final Currency GBP = Currency.GBP;
private static final Period PAYMENT_TENOR_UK = Period.ofMonths(6);
private static final int COUPON_PER_YEAR_G = 2;
private static final Calendar CALENDAR_UK = new MondayToFridayCalendar("A");
private static final DayCount DAY_COUNT_UK = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ICMA"); // To check
private static final BusinessDayConvention BUSINESS_DAY_UK = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Following");
private static final boolean IS_EOM_UK = false;
private static final Period BOND_TENOR_G = Period.ofYears(12);
private static final int SETTLEMENT_DAYS_UK = 1;
private static final int EX_DIVIDEND_DAYS_UK = 7;
private static final ZonedDateTime START_ACCRUAL_DATE_UK = DateUtils.getUTCDate(2002, 9, 7);
private static final ZonedDateTime MATURITY_DATE_UK = START_ACCRUAL_DATE_UK.plus(BOND_TENOR_G);
private static final double RATE_UK = 0.0500;
private static final double NOTIONAL_UK = 100;
private static final YieldConvention YIELD_CONVENTION_UK = YieldConventionFactory.INSTANCE.getYieldConvention("UK:BUMP/DMO METHOD");
private static final BondFixedSecurityDefinition BOND_FIXED_SECURITY_DEFINITION_UK = BondFixedSecurityDefinition.from(GBP, MATURITY_DATE_UK, START_ACCRUAL_DATE_UK, PAYMENT_TENOR_UK, RATE_UK,
SETTLEMENT_DAYS_UK, NOTIONAL_UK, EX_DIVIDEND_DAYS_UK, CALENDAR_UK, DAY_COUNT_UK, BUSINESS_DAY_UK, YIELD_CONVENTION_UK, IS_EOM_UK, ISSUER_UK, "RepoType");
private static final ZonedDateTime REFERENCE_DATE_3 = DateUtils.getUTCDate(2011, 9, 2); // Ex-dividend is 30-Aug-2011
private static final BondFixedSecurity BOND_FIXED_SECURITY_UK = BOND_FIXED_SECURITY_DEFINITION_UK.toDerivative(REFERENCE_DATE_3);
private static final ZonedDateTime SPOT_3 = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE_3, SETTLEMENT_DAYS_UK, CALENDAR);
private static final double REFERENCE_TIME_3 = TimeCalculator.getTimeBetween(REFERENCE_DATE_3, SPOT_3);
@Test
public void presentValueFixedExDividend() {
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_UK, ISSUER_MULTICURVES);
final BondFixedSecurityDefinition bondNoExDefinition = BondFixedSecurityDefinition.from(GBP, MATURITY_DATE_UK, START_ACCRUAL_DATE_UK, PAYMENT_TENOR_UK, RATE_UK, SETTLEMENT_DAYS_UK, NOTIONAL_UK,
0, CALENDAR_UK, DAY_COUNT_UK, BUSINESS_DAY_UK, YIELD_CONVENTION_UK, IS_EOM_UK, ISSUER_UK, "RepoType");
final BondFixedSecurity BondNoEx = bondNoExDefinition.toDerivative(REFERENCE_DATE_3);
final MultipleCurrencyAmount pvNoEx = METHOD_BOND_SECURITY.presentValue(BondNoEx, ISSUER_MULTICURVES);
final CouponFixedDefinition couponDefinitionEx = BOND_FIXED_SECURITY_DEFINITION_UK.getCoupons().getNthPayment(17);
final MulticurveProviderInterface multicurvesDecorated = new MulticurveProviderDiscountingDecoratedIssuer(ISSUER_MULTICURVES, GBP, ISSUER_UK);
final MultipleCurrencyAmount pvCpn = couponDefinitionEx.toDerivative(REFERENCE_DATE_3).accept(PVDC, multicurvesDecorated);
assertEquals("Fixed coupon bond security: present value ex dividend", pvNoEx.getAmount(GBP) - pvCpn.getAmount(GBP), pv.getAmount(GBP), TOLERANCE_PV);
}
@Test
public void dirtyPriceFixedExDividend() {
final MultipleCurrencyAmount pv = METHOD_BOND_SECURITY.presentValue(BOND_FIXED_SECURITY_UK, ISSUER_MULTICURVES);
final double df = ISSUER_MULTICURVES.getMulticurveProvider().getDiscountFactor(GBP, REFERENCE_TIME_3);
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromCurves(BOND_FIXED_SECURITY_UK, ISSUER_MULTICURVES);
assertEquals("Fixed coupon bond security: dirty price from curves", pv.getAmount(GBP) / df / BOND_FIXED_SECURITY_UK.getCoupon().getNthPayment(0).getNotional(), dirty);
assertTrue("Fixed coupon bond security: dirty price is relative price", (0.50 < dirty) & (dirty < 2.0));
}
@Test
public void dirtyPriceFromYieldUKExDividend() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield);
final double dirtyPriceExpected = 1.0277859038; // To be check with another source.
assertEquals("Fixed coupon bond security: dirty price from yield UK", dirtyPriceExpected, dirtyPrice, 1E-8);
}
@Test
public void dirtyPriceFromYieldUKLastPeriod() {
final ZonedDateTime referenceDate = DateUtils.getUTCDate(2014, 6, 3); // In last period
final BondFixedSecurity bondSecurity = BOND_FIXED_SECURITY_DEFINITION_UK.toDerivative(referenceDate);
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(bondSecurity, yield);
final double dirtyPriceExpected = (1 + RATE_UK / COUPON_PER_YEAR_G) * Math.pow(1 + yield / COUPON_PER_YEAR_G, -bondSecurity.getAccrualFactorToNextCoupon());
assertEquals("Fixed coupon bond security: dirty price from yield UK - last period", dirtyPriceExpected, dirtyPrice, 1E-8);
}
@Test
public void yieldFromDirtyPriceUKExDividend() {
final double yield = 0.04;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield);
final double yieldComputed = METHOD_BOND_SECURITY.yieldFromDirtyPrice(BOND_FIXED_SECURITY_UK, dirtyPrice);
assertEquals("Fixed coupon bond security: yield from dirty price UK", yield, yieldComputed, 1E-10);
}
@Test
public void modifiedDurationFromYieldUKExDividend() {
final double yield = 0.04;
final double modifiedDuration = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_UK, yield);
final double modifiedDurationExpected = 2.7757118292; // To be check with another source.
assertEquals("Fixed coupon bond security: modified duration from yield UK DMO - hard coded value", modifiedDurationExpected, modifiedDuration, 1E-8);
final double shift = 1.0E-6;
final double dirty = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield);
final double dirtyP = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield + shift);
final double dirtyM = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield - shift);
final double modifiedDurationFD = -(dirtyP - dirtyM) / (2 * shift) / dirty;
assertEquals("Fixed coupon bond security: modified duration from yield UK DMO - finite difference", modifiedDurationFD, modifiedDuration, 1E-8);
}
@Test
public void macauleyDurationFromYieldUKExDividend() {
final double yield = 0.04;
final double macauleyDuration = METHOD_BOND_SECURITY.macaulayDurationFromYield(BOND_FIXED_SECURITY_UK, yield);
final double macauleyDurationExpected = 2.909894241 / METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_UK, yield); // To be check with another source.
assertEquals("Fixed coupon bond security: Macauley duration from yield UK DMO - hard coded value", macauleyDurationExpected, macauleyDuration, 1E-8);
}
// UKT 6 1/4 11/25/10
private static final DayCount DAY_COUNT_G2 = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ICMA"); // To check
private static final int SETTLEMENT_DAYS_G2 = 1;
private static final int EX_DIVIDEND_DAYS_G2 = 7;
private static final ZonedDateTime START_ACCRUAL_DATE_G2 = DateUtils.getUTCDate(1999, 11, 25);
private static final ZonedDateTime MATURITY_DATE_G2 = DateUtils.getUTCDate(2010, 11, 25);
private static final double RATE_G2 = 0.0625;
private static final double NOTIONAL_G2 = 100;
private static final YieldConvention YIELD_CONVENTION_G2 = YieldConventionFactory.INSTANCE.getYieldConvention("UK:BUMP/DMO METHOD");
private static final BondFixedSecurityDefinition BOND_FIXED_SECURITY_DEFINITION_G2 = BondFixedSecurityDefinition.from(GBP, MATURITY_DATE_G2, START_ACCRUAL_DATE_G2, PAYMENT_TENOR_UK, RATE_G2,
SETTLEMENT_DAYS_G2, NOTIONAL_G2, EX_DIVIDEND_DAYS_G2, CALENDAR_UK, DAY_COUNT_G2, BUSINESS_DAY_UK, YIELD_CONVENTION_G2, IS_EOM_UK, ISSUER_UK, "");
private static final ZonedDateTime REFERENCE_DATE_4 = DateUtils.getUTCDate(2001, 8, 10);
private static final BondFixedSecurity BOND_FIXED_SECURITY_G2 = BOND_FIXED_SECURITY_DEFINITION_G2.toDerivative(REFERENCE_DATE_4);
@Test
public void dirtyPriceFromCleanPriceUK() {
final double cleanPrice = 110.20 / 100.00;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromCleanPrice(BOND_FIXED_SECURITY_G2, cleanPrice);
final double dirtyPriceExpected = 1.11558696;
assertEquals("Fixed coupon bond security: dirty price from clean price", dirtyPriceExpected, dirtyPrice, 1E-8);
}
@Test
public void yieldPriceFromCleanPriceUK() {
final double cleanPrice = 110.20 / 100.00;
final double yield = METHOD_BOND_SECURITY.yieldFromCleanPrice(BOND_FIXED_SECURITY_G2, cleanPrice);
final double yieldExpected = 0.04870;
assertEquals("Fixed coupon bond security: dirty price from clean price", yieldExpected, yield, 1E-5);
}
@Test
public void modifiedDurationFromCleanPriceUK() {
final double cleanPrice = 110.20 / 100.00;
final double dirtyPrice = METHOD_BOND_SECURITY.dirtyPriceFromCleanPrice(BOND_FIXED_SECURITY_G2, cleanPrice);
final double md = METHOD_BOND_SECURITY.modifiedDurationFromDirtyPrice(BOND_FIXED_SECURITY_G2, dirtyPrice);
final double mdExpected = 7.039;
assertEquals("Fixed coupon bond security: dirty price from clean price", mdExpected, md, 1E-3);
}
@Test
public void yieldMethodVsCalculator() {
double yield1 = METHOD_BOND_SECURITY.yieldFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
double yield2 = BOND_FIXED_SECURITY_G2.accept(YFCC, ISSUER_MULTICURVES);
assertEquals("Bill Security: discounting method - yield from curves", yield1, yield2, TOLERANCE_YIELD);
yield1 = METHOD_BOND_SECURITY.yieldFromCleanPrice(BOND_FIXED_SECURITY_G2, 1.1);
yield2 = BOND_FIXED_SECURITY_G2.accept(YFPC, 1.1);
assertEquals("Bond Security: discounting method - yield from price", yield1, yield2, TOLERANCE_YIELD);
}
@Test
public void modifiedDurationMethodVsCalculator() {
double method = METHOD_BOND_SECURITY.modifiedDurationFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
double calculator = BOND_FIXED_SECURITY_G2.accept(MDFC, ISSUER_MULTICURVES);
assertEquals("bond Security: discounting method - modified duration", method, calculator, 1e-9);
method = METHOD_BOND_SECURITY.modifiedDurationFromYield(BOND_FIXED_SECURITY_G2, 0.05);
calculator = BOND_FIXED_SECURITY_G2.accept(MDFY, 0.05);
assertEquals("bond Security: discounting method - modified duration", method, calculator, 1e-9);
method = METHOD_BOND_SECURITY.modifiedDurationFromCleanPrice(BOND_FIXED_SECURITY_G2, 1.00);
calculator = BOND_FIXED_SECURITY_G2.accept(MDFP, 1.00);
assertEquals("bond Security: discounting method - modified duration", method, calculator, 1e-9);
}
@Test
public void macaulayDurationMethodVsCalculator() {
double method = METHOD_BOND_SECURITY.macaulayDurationFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
double calculator = BOND_FIXED_SECURITY_G2.accept(McDFC, ISSUER_MULTICURVES);
assertEquals("bond Security: discounting method - macaulay duration", method, calculator, 1e-9);
method = METHOD_BOND_SECURITY.macaulayDurationFromYield(BOND_FIXED_SECURITY_G2, 0.05);
calculator = BOND_FIXED_SECURITY_G2.accept(McDFY, 0.05);
assertEquals("bond Security: discounting method - macaulay duration", method, calculator, 1e-9);
}
@Test
public void dirtyPriceMethodVsCalculator() {
double method = METHOD_BOND_SECURITY.dirtyPriceFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
double calculator = BOND_FIXED_SECURITY_G2.accept(DPFC, ISSUER_MULTICURVES);
assertEquals("bond Security: discounting method - dirty price", method, calculator, 1e-9);
method = METHOD_BOND_SECURITY.dirtyPriceFromYield(BOND_FIXED_SECURITY_G2, 0.05);
calculator = BOND_FIXED_SECURITY_G2.accept(DPFY, 0.05);
assertEquals("bond Security: discounting method - dirty price", method, calculator, 1e-9);
}
@Test
public void convexityMethodVsCalculator() {
final double method = METHOD_BOND_SECURITY.convexityFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
final double calculator = BOND_FIXED_SECURITY_G2.accept(CFC, ISSUER_MULTICURVES);
assertEquals("bond Security: discounting method - convexity", method, calculator, 1e-9);
}
@Test
public void cleanPriceMethodVsCalculator() {
double method = METHOD_BOND_SECURITY.cleanPriceFromCurves(BOND_FIXED_SECURITY_G2, ISSUER_MULTICURVES);
double calculator = BOND_FIXED_SECURITY_G2.accept(CPFC, ISSUER_MULTICURVES);
assertEquals("bond Security: discounting method - clean price", method, calculator, 1e-9);
method = METHOD_BOND_SECURITY.cleanPriceFromYield(BOND_FIXED_SECURITY_G2, 0.05);
calculator = BOND_FIXED_SECURITY_G2.accept(CPFY, 0.05);
assertEquals("bond Security: discounting method - clean price", method, calculator, 1e-9);
}
}