/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.bond.provider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.interestrate.bond.definition.BillSecurity; import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.financial.convention.yield.SimpleYieldConvention; import com.opengamma.financial.convention.yield.YieldConvention; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.tuple.DoublesPair; /** * Class with methods related to bill security valued by discounting. * <P> Reference: Bill pricing, version 1.0. OpenGamma documentation, January 2012. */ public final class BillSecurityDiscountingMethod { /** * The unique instance of the class. */ private static final BillSecurityDiscountingMethod INSTANCE = new BillSecurityDiscountingMethod(); /** * Return the class instance. * @return The instance. */ public static BillSecurityDiscountingMethod getInstance() { return INSTANCE; } /** * Constructor */ private BillSecurityDiscountingMethod() { } /** * Computes the present value of the bill security by discounting. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @return The present value. */ public MultipleCurrencyAmount presentValue(final BillSecurity bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double pvBill = bill.getNotional() * issuer.getDiscountFactor(bill.getIssuerEntity(), bill.getEndTime()); return MultipleCurrencyAmount.of(bill.getCurrency(), pvBill); } /** * Compute the bill price from the yield. The price is the relative price at settlement. The yield is in the bill yield convention. * @param bill The bill. * @param yield The yield in the bill yield convention. * @return The price. */ public double priceFromYield(final BillSecurity bill, final double yield) { return priceFromYield(bill.getYieldConvention(), yield, bill.getAccrualFactor()); } /** * Compute the bill price from the yield. The price is the relative price at settlement. * @param convention The yield convention. * @param yield The yield in the bill yield convention. * @param accrualFactor The accrual factor between settlement and maturity. * @return The price. */ public double priceFromYield(final YieldConvention convention, final double yield, final double accrualFactor) { if (convention == SimpleYieldConvention.DISCOUNT) { return 1.0 - accrualFactor * yield; } if (convention == SimpleYieldConvention.INTERESTATMTY) { return 1.0 / (1 + accrualFactor * yield); } throw new UnsupportedOperationException("The convention " + convention.getName() + " is not supported."); } /** * Computes the bill yield from the price. The yield is in the bill yield convention. * @param bill The bill. * @param price The price. The price is the relative price at settlement. * @return The yield. */ public double yieldFromCleanPrice(final BillSecurity bill, final double price) { if (bill.getYieldConvention() == SimpleYieldConvention.DISCOUNT) { return (1.0 - price) / bill.getAccrualFactor(); } if (bill.getYieldConvention() == SimpleYieldConvention.INTERESTATMTY) { return (1.0 / price - 1) / bill.getAccrualFactor(); } throw new UnsupportedOperationException("The convention " + bill.getYieldConvention().getName() + " is not supported."); } /** * Computes the derivative of the bill yield with respect to the price. The yield is in the bill yield convention. * @param bill The bill. * @param price The price. The price is the relative price at settlement. * @return The yield derivative. */ public double yieldFromPriceDerivative(final BillSecurity bill, final double price) { if (bill.getYieldConvention() == SimpleYieldConvention.DISCOUNT) { return -1.0 / bill.getAccrualFactor(); } if (bill.getYieldConvention() == SimpleYieldConvention.INTERESTATMTY) { return -1.0 / (price * price * bill.getAccrualFactor()); } throw new UnsupportedOperationException("The convention " + bill.getYieldConvention().getName() + " is not supported."); } /** * Computes the present value of the bill security by discounting from its yield. * @param bill The bill. * @param yield The bill yield. * @param issuer The issuer and multi-curves provider. * @return The present value. */ public MultipleCurrencyAmount presentValueFromYield(final BillSecurity bill, final double yield, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double price = priceFromYield(bill, yield); return presentValueFromPrice(bill, price, issuer); } /** * Computes the present value of the bill security by discounting from its price. * @param bill The bill. * @param price The (dirty) price at settlement. * @param issuer The issuer and multi-curves provider. * @return The present value. */ public MultipleCurrencyAmount presentValueFromPrice(final BillSecurity bill, final double price, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double pvBill = bill.getNotional() * price * issuer.getMulticurveProvider().getDiscountFactor(bill.getCurrency(), bill.getSettlementTime()); return MultipleCurrencyAmount.of(bill.getCurrency(), pvBill); } /** * Compute the bill price from the curves. The price is the relative price at settlement. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @return The price. */ public double priceFromCurves(final BillSecurity bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double pvBill = bill.getNotional() * issuer.getDiscountFactor(bill.getIssuerEntity(), bill.getEndTime()); final double price = pvBill / (bill.getNotional() * issuer.getMulticurveProvider().getDiscountFactor(bill.getCurrency(), bill.getSettlementTime())); return price; } /** * Computes the bill yield from the curves. The yield is in the bill yield convention. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @return The yield. */ public double yieldFromCurves(final BillSecurity bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double pvBill = bill.getNotional() * issuer.getDiscountFactor(bill.getIssuerEntity(), bill.getEndTime()); final double price = pvBill / (bill.getNotional() * issuer.getMulticurveProvider().getDiscountFactor(bill.getCurrency(), bill.getSettlementTime())); return yieldFromCleanPrice(bill, price); } /** * Computes the bill present value curve sensitivity. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @return The sensitivity. */ public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final BillSecurity bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final double dfEnd = issuer.getDiscountFactor(bill.getIssuerEntity(), bill.getEndTime()); // Backward sweep final double pvBar = 1.0; final double dfEndBar = bill.getNotional() * pvBar; final Map<String, List<DoublesPair>> resultMapCredit = new HashMap<>(); final List<DoublesPair> listDiscounting = new ArrayList<>(); listDiscounting.add(DoublesPair.of(bill.getEndTime(), -bill.getEndTime() * dfEnd * dfEndBar)); resultMapCredit.put(issuer.getName(bill.getIssuerEntity()), listDiscounting); final MulticurveSensitivity result = MulticurveSensitivity.ofYieldDiscounting(resultMapCredit); return MultipleCurrencyMulticurveSensitivity.of(bill.getCurrency(), result); } }