/** * 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.BillTransaction; 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.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.tuple.DoublesPair; /** * Class with methods related to bill transaction valued by discounting. * <P> Reference: Bill pricing, version 1.0. OpenGamma documentation, January 2012. */ public final class BillTransactionDiscountingMethod { /** * The unique instance of the class. */ private static final BillTransactionDiscountingMethod INSTANCE = new BillTransactionDiscountingMethod(); /** * Return the class instance. * @return The instance. */ public static BillTransactionDiscountingMethod getInstance() { return INSTANCE; } /** * Constructor */ private BillTransactionDiscountingMethod() { } /** * Methods. */ private static final BillSecurityDiscountingMethod METHOD_SECURITY = BillSecurityDiscountingMethod.getInstance(); /** * Computes the bill transaction present value. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @return The present value. */ public MultipleCurrencyAmount presentValue(final BillTransaction bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final Currency ccy = bill.getCurrency(); final MultipleCurrencyAmount pvBill = METHOD_SECURITY.presentValue(bill.getBillPurchased(), issuer); final double pvSettle = bill.getSettlementAmount() * issuer.getMulticurveProvider().getDiscountFactor(ccy, bill.getBillPurchased().getSettlementTime()); return pvBill.multipliedBy(bill.getQuantity()).plus(MultipleCurrencyAmount.of(ccy, pvSettle)); } /** * Computes the bill transaction present value from the quoted yield to maturity. * @param bill The bill. * @param issuer The issuer and multi-curves provider. * @param yield The yield. * @return The present value. */ public MultipleCurrencyAmount presentValueFromYield(final BillTransaction bill, final double yield, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final Currency ccy = bill.getCurrency(); final MultipleCurrencyAmount pvSecurity = METHOD_SECURITY.presentValueFromYield(bill.getBillStandard(), yield, issuer); final double pvSettle = bill.getSettlementAmount() * issuer.getMulticurveProvider().getDiscountFactor(ccy, bill.getBillPurchased().getSettlementTime()); return pvSecurity.plus(MultipleCurrencyAmount.of(bill.getCurrency(), pvSettle)); } /** * 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 BillTransaction bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final Currency ccy = bill.getCurrency(); final double dfCreditEnd = issuer.getDiscountFactor(bill.getBillPurchased().getIssuerEntity(), bill.getBillPurchased().getEndTime()); final double dfDscSettle = issuer.getMulticurveProvider().getDiscountFactor(ccy, bill.getBillPurchased().getSettlementTime()); // Backward sweep final double pvBar = 1.0; final double dfCreditEndBar = bill.getQuantity() * bill.getBillPurchased().getNotional() * pvBar; final double dfDscSettleBar = bill.getSettlementAmount() * pvBar; final Map<String, List<DoublesPair>> resultMapCredit = new HashMap<>(); final List<DoublesPair> listCredit = new ArrayList<>(); listCredit.add(DoublesPair.of(bill.getBillPurchased().getEndTime(), -bill.getBillPurchased().getEndTime() * dfCreditEnd * dfCreditEndBar)); resultMapCredit.put(issuer.getName(bill.getBillPurchased().getIssuerEntity()), listCredit); final MulticurveSensitivity result = MulticurveSensitivity.ofYieldDiscounting(resultMapCredit); final Map<String, List<DoublesPair>> resultMapDsc = new HashMap<>(); final List<DoublesPair> listDsc = new ArrayList<>(); listDsc.add(DoublesPair.of(bill.getBillPurchased().getSettlementTime(), -bill.getBillPurchased().getSettlementTime() * dfDscSettle * dfDscSettleBar)); resultMapDsc.put(issuer.getMulticurveProvider().getName(ccy), listDsc); return MultipleCurrencyMulticurveSensitivity.of(ccy, result.plus(MulticurveSensitivity.ofYieldDiscounting(resultMapDsc))); } /** * The par spread for which the present value of the bill transaction is 0. If that spread was added to the transaction yield, the new transaction would have a present value of 0. * @param bill The bill transaction. * @param issuer The issuer and multi-curves provider. * @return The spread. */ public double parSpread(final BillTransaction bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final Currency ccy = bill.getCurrency(); final double dfCreditEnd = issuer.getDiscountFactor(bill.getBillPurchased().getIssuerEntity(), bill.getBillPurchased().getEndTime()); final double dfDscSettle = issuer.getMulticurveProvider().getDiscountFactor(ccy, bill.getBillPurchased().getSettlementTime()); final double pricePar = dfCreditEnd / dfDscSettle; return METHOD_SECURITY.yieldFromCleanPrice(bill.getBillPurchased(), pricePar) - METHOD_SECURITY.yieldFromCleanPrice(bill.getBillPurchased(), -bill.getSettlementAmount() / (bill.getQuantity() * bill.getBillPurchased().getNotional())); } /** * The par spread curve sensitivity. * @param bill The bill transaction. * @param issuer The issuer and multi-curves provider. * @return The curve sensitivity. */ public MulticurveSensitivity parSpreadCurveSensitivity(final BillTransaction bill, final IssuerProviderInterface issuer) { ArgumentChecker.notNull(bill, "Bill"); ArgumentChecker.notNull(issuer, "Issuer and multi-curves provider"); final Currency ccy = bill.getCurrency(); final double dfCreditEnd = issuer.getDiscountFactor(bill.getBillPurchased().getIssuerEntity(), bill.getBillPurchased().getEndTime()); final double dfDscSettle = issuer.getMulticurveProvider().getDiscountFactor(ccy, bill.getBillPurchased().getSettlementTime()); final double pricePar = dfCreditEnd / dfDscSettle; // Backward sweep final double spreadBar = 1.0; final double priceParBar = METHOD_SECURITY.yieldFromPriceDerivative(bill.getBillPurchased(), pricePar) * spreadBar; final double dfDscSettleBar = -dfCreditEnd / (dfDscSettle * dfDscSettle) * priceParBar; final double dfCreditEndBar = priceParBar / dfDscSettle; final Map<String, List<DoublesPair>> resultMapCredit = new HashMap<>(); final List<DoublesPair> listCredit = new ArrayList<>(); listCredit.add(DoublesPair.of(bill.getBillPurchased().getEndTime(), -bill.getBillPurchased().getEndTime() * dfCreditEnd * dfCreditEndBar)); resultMapCredit.put(issuer.getName(bill.getBillPurchased().getIssuerEntity()), listCredit); final MulticurveSensitivity result = MulticurveSensitivity.ofYieldDiscounting(resultMapCredit); final Map<String, List<DoublesPair>> resultMapDsc = new HashMap<>(); final List<DoublesPair> listDsc = new ArrayList<>(); listDsc.add(DoublesPair.of(bill.getBillPurchased().getSettlementTime(), -bill.getBillPurchased().getSettlementTime() * dfDscSettle * dfDscSettleBar)); resultMapDsc.put(issuer.getMulticurveProvider().getName(ccy), listDsc); return result.plus(MulticurveSensitivity.ofYieldDiscounting(resultMapDsc)); } }