/** Tests related to the discounting method for bond security. */ public class BondSecurityFRDiscountingMethodTest { // Calculators private static final PresentValueCalculator PVC = PresentValueCalculator.getInstance(); private static final BondSecurityDiscountingMethod METHOD = BondSecurityDiscountingMethod.getInstance(); private static final double TOLERANCE_PRICE = 1.0E-8; private static final String REPO_TYPE = "General collateral"; private static final Currency EUR = Currency.EUR; private static final Calendar TARGET = new MondayToFridayCalendar("TARGET"); private static final DayCount DAY_COUNT_ACTACTICMA = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ICMA"); private static final BusinessDayConvention BUSINESS_DAY_FOL = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Following"); private static final boolean IS_EOM_FIXED = false; // To derivatives private static final DayCount ACT_ACT = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ISDA"); private static final String CREDIT_CURVE_NAME = "Credit"; private static final String REPO_CURVE_NAME = "Repo"; private static final String FORWARD_CURVE_NAME = "Forward"; private static final String[] CURVES_NAME = { CREDIT_CURVE_NAME, REPO_CURVE_NAME, FORWARD_CURVE_NAME }; private static final YieldCurveBundle CURVES = TestsDataSetsSABR.createCurvesBond1(); // FRTR 4 1/2 04/25/41 - ISIN: FR0010773192 private static final String ISSUER_FR = "FRANCE (GOVT OF)"; private static final YieldConvention YIELD_CONVENTION_FRANCE = SimpleYieldConvention.FRANCE_COMPOUND_METHOD; private static final int SETTLEMENT_DAYS_FR = 3; private static final Period PAYMENT_TENOR_FR = Period.ofMonths(12); // private static final int COUPON_PER_YEAR_FR = 1; private static final ZonedDateTime BOND_START_FR = DateUtils.getUTCDate(2009, 4, 25); private static final ZonedDateTime BOND_MATURITY_FR = DateUtils.getUTCDate(2041, 4, 25); private static final ZonedDateTime BOND_FIRSTCPN_FR = DateUtils.getUTCDate(2010, 4, 25); private static final double RATE_FR = 0.0450; private static final BondFixedSecurityDefinition BOND_FR_SECURITY_DEFINITION = BondFixedSecurityDefinition.from( EUR, BOND_START_FR, BOND_FIRSTCPN_FR, BOND_MATURITY_FR, PAYMENT_TENOR_FR, RATE_FR, SETTLEMENT_DAYS_FR, TARGET, DAY_COUNT_ACTACTICMA, BUSINESS_DAY_FOL, YIELD_CONVENTION_FRANCE, IS_EOM_FIXED, ISSUER_FR); }
/** * Compute the present value of a bond transaction from its yield-to-maturity. * * @param bond The bond transaction. * @param curves The curve bundle. * @param yield The bond yield. * @return The present value. */ public double presentValueFromYield( final BondTransaction<? extends BondSecurity<? extends Payment, ? extends Coupon>> bond, final YieldCurveBundle curves, final double yield) { ArgumentChecker.notNull(bond, "Bond"); ArgumentChecker.isTrue( bond instanceof BondFixedTransaction, "Present value from clean price only for fixed coupon bond"); final BondFixedTransaction bondFixed = (BondFixedTransaction) bond; double cleanPrice = METHOD_SECURITY.cleanPriceFromYield(bondFixed.getBondStandard(), yield); return presentValueFromCleanPrice(bond, curves, cleanPrice); }
/** Class with methods related to bond transaction valued by discounting. */ public final class BondTransactionDiscountingMethod { private static final Logger LOGGER = LoggerFactory.getLogger(BondTransactionDiscountingMethod.class); /** The unique instance of the class. */ private static final BondTransactionDiscountingMethod INSTANCE = new BondTransactionDiscountingMethod(); /** * Return the class instance. * * @return The instance. */ public static BondTransactionDiscountingMethod getInstance() { return INSTANCE; } /** Constructor */ private BondTransactionDiscountingMethod() {} /** The present value calculator (for the different parts of the bond transaction). */ private static final PresentValueCalculator PVC = PresentValueCalculator.getInstance(); /** The present value calculator (for the different parts of the bond transaction). */ private static final PresentValueCurveSensitivityCalculator PVSC = PresentValueCurveSensitivityCalculator.getInstance(); private static final BondSecurityDiscountingMethod METHOD_SECURITY = BondSecurityDiscountingMethod.getInstance(); /** * Compute the present value of a fixed coupon bond transaction. * * @param bond The bond transaction. * @param curves The curve bundle. * @return The present value. */ public double presentValue(final BondFixedTransaction bond, final YieldCurveBundle curves) { final double pvNominal = bond.getBondTransaction().getNominal().accept(PVC, curves); final double pvCoupon = bond.getBondTransaction().getCoupon().accept(PVC, curves); final double settlementAmount = -(bond.getTransactionPrice() * bond.getBondTransaction().getCoupon().getNthPayment(0).getNotional() + bond.getBondTransaction().getAccruedInterest()) * bond.getQuantity(); final PaymentFixed settlement = new PaymentFixed( bond.getBondTransaction().getCurrency(), bond.getBondTransaction().getSettlementTime(), settlementAmount, bond.getBondTransaction().getRepoCurveName()); final double pvSettlement = settlement.accept(PVC, curves); return (pvNominal + pvCoupon) * bond.getQuantity() + pvSettlement; } /** * Compute the present value of a Ibor coupon bond (FRN) transaction. * * @param bond The bond transaction. * @param curves The curve bundle. * @return The present value. */ public double presentValue(final BondIborTransaction bond, final YieldCurveBundle curves) { final double pvNominal = bond.getBondTransaction().getNominal().accept(PVC, curves); final double pvCoupon = bond.getBondTransaction().getCoupon().accept(PVC, curves); final double settlementAmount = bond.getTransactionPrice() * bond.getBondTransaction() .getCoupon() .getNthPayment(0) .getNotional(); // FIXME: add accrued. LOGGER.error("The FRN settlement amount does not include the accrued interests."); final PaymentFixed settlement = new PaymentFixed( bond.getBondTransaction().getCurrency(), bond.getBondTransaction().getSettlementTime(), settlementAmount, bond.getBondTransaction().getRepoCurveName()); final double pvSettlement = settlement.accept(PVC, curves); return (pvNominal + pvCoupon) * bond.getQuantity() + pvSettlement; } /** * Compute the present value of a bond transaction from its clean price. * * @param bond The bond transaction. * @param curves The curve bundle. * @param cleanPrice The bond clean price. * @return The present value. */ public double presentValueFromCleanPrice( final BondTransaction<? extends BondSecurity<? extends Payment, ? extends Coupon>> bond, final YieldCurveBundle curves, final double cleanPrice) { ArgumentChecker.isTrue( bond instanceof BondFixedTransaction, "Present value from clean price only for fixed coupon bond"); final BondFixedTransaction bondFixed = (BondFixedTransaction) bond; final double dfSettle = curves .getCurve(bondFixed.getBondStandard().getRepoCurveName()) .getDiscountFactor(bondFixed.getBondTransaction().getSettlementTime()); final double pvPriceStandard = (cleanPrice * bondFixed.getNotionalStandard() + bondFixed.getBondStandard().getAccruedInterest()) * dfSettle; final double pvNominalStandard = bond.getBondStandard().getNominal().accept(PVC, curves); final double pvCouponStandard = bond.getBondStandard().getCoupon().accept(PVC, curves); final double pvDiscountingStandard = (pvNominalStandard + pvCouponStandard); final double pvNominalTransaction = bond.getBondTransaction().getNominal().accept(PVC, curves); final double pvCouponTransaction = bond.getBondTransaction().getCoupon().accept(PVC, curves); final double pvDiscountingTransaction = (pvNominalTransaction + pvCouponTransaction); return (pvDiscountingTransaction - pvDiscountingStandard + pvPriceStandard) * bond.getQuantity(); } /** * Compute the present value of a bond transaction from its yield-to-maturity. * * @param bond The bond transaction. * @param curves The curve bundle. * @param yield The bond yield. * @return The present value. */ public double presentValueFromYield( final BondTransaction<? extends BondSecurity<? extends Payment, ? extends Coupon>> bond, final YieldCurveBundle curves, final double yield) { ArgumentChecker.notNull(bond, "Bond"); ArgumentChecker.isTrue( bond instanceof BondFixedTransaction, "Present value from clean price only for fixed coupon bond"); final BondFixedTransaction bondFixed = (BondFixedTransaction) bond; double cleanPrice = METHOD_SECURITY.cleanPriceFromYield(bondFixed.getBondStandard(), yield); return presentValueFromCleanPrice(bond, curves, cleanPrice); } /** * Compute the present value sensitivity of a bond transaction. * * @param bond The bond transaction. * @param curves The curve bundle. * @return The present value sensitivity. */ public InterestRateCurveSensitivity presentValueSensitivity( final BondFixedTransaction bond, final YieldCurveBundle curves) { final InterestRateCurveSensitivity pvsNominal = new InterestRateCurveSensitivity( bond.getBondTransaction().getNominal().accept(PVSC, curves)); final InterestRateCurveSensitivity pvsCoupon = new InterestRateCurveSensitivity( bond.getBondTransaction().getCoupon().accept(PVSC, curves)); final double settlementAmount = -(bond.getTransactionPrice() * bond.getBondTransaction().getCoupon().getNthPayment(0).getNotional() + bond.getBondTransaction().getAccruedInterest()) * bond.getQuantity(); final PaymentFixed settlement = new PaymentFixed( bond.getBondTransaction().getCurrency(), bond.getBondTransaction().getSettlementTime(), settlementAmount, bond.getBondTransaction().getRepoCurveName()); final InterestRateCurveSensitivity pvsSettlement = new InterestRateCurveSensitivity(settlement.accept(PVSC, curves)); return pvsNominal.plus(pvsCoupon).multipliedBy(bond.getQuantity()).plus(pvsSettlement); } public InterestRateCurveSensitivity presentValueSensitivity( final BondIborTransaction bond, final YieldCurveBundle curves) { final InterestRateCurveSensitivity pvsNominal = new InterestRateCurveSensitivity( bond.getBondTransaction().getNominal().accept(PVSC, curves)); final InterestRateCurveSensitivity pvsCoupon = new InterestRateCurveSensitivity( bond.getBondTransaction().getCoupon().accept(PVSC, curves)); final double settlementAmount = bond.getTransactionPrice() * bond.getBondTransaction() .getCoupon() .getNthPayment(0) .getNotional(); // FIXME: add accrued. LOGGER.error("The FRN settlement amount does not include the accrued interests."); final PaymentFixed settlement = new PaymentFixed( bond.getBondTransaction().getCurrency(), bond.getBondTransaction().getSettlementTime(), settlementAmount, bond.getBondTransaction().getRepoCurveName()); final InterestRateCurveSensitivity pvsSettlement = new InterestRateCurveSensitivity(settlement.accept(PVSC, curves)); return pvsNominal.plus(pvsCoupon).multipliedBy(bond.getQuantity()).plus(pvsSettlement); } }