/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.bond;
import java.time.LocalDate;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.StandardId;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.currency.Payment;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.CompoundedRateType;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.bond.BondPaymentPeriod;
import com.opengamma.strata.product.bond.CapitalIndexedBondPaymentPeriod;
import com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention;
import com.opengamma.strata.product.bond.KnownAmountBondPaymentPeriod;
import com.opengamma.strata.product.bond.ResolvedCapitalIndexedBond;
import com.opengamma.strata.product.bond.ResolvedCapitalIndexedBondTrade;
/**
* Pricer for for capital index bond trades.
* <p>
* This function provides the ability to price a {@link ResolvedCapitalIndexedBondTrade}.
*
* <h4>Price</h4>
* Strata uses <i>decimal prices</i> for bonds in the trade model, pricers and market data.
* For example, a price of 99.32% is represented in Strata by 0.9932.
*/
public class DiscountingCapitalIndexedBondTradePricer {
/**
* Default implementation.
*/
public static final DiscountingCapitalIndexedBondTradePricer DEFAULT =
new DiscountingCapitalIndexedBondTradePricer(DiscountingCapitalIndexedBondProductPricer.DEFAULT);
/**
* Pricer for {@link ResolvedCapitalIndexedBond}.
*/
private final DiscountingCapitalIndexedBondProductPricer productPricer;
/**
* Creates an instance.
*
* @param productPricer pricer for {@link ResolvedCapitalIndexedBond}
*/
public DiscountingCapitalIndexedBondTradePricer(DiscountingCapitalIndexedBondProductPricer productPricer) {
this.productPricer = ArgChecker.notNull(productPricer, "productPricer");
}
//-------------------------------------------------------------------------
/**
* Calculates the present value of the bond trade.
* <p>
* The present value of the trade is the value on the valuation date.
* The result is expressed using the payment currency of the bond.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @return the present value of the bond trade
*/
public CurrencyAmount presentValue(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider) {
validate(ratesProvider, discountingProvider);
LocalDate settlementDate = trade.getSettlementDate();
CurrencyAmount pvProduct = productPricer.presentValue(trade.getProduct(), ratesProvider,
discountingProvider, settlementDate);
return presentValueFromProductPresentValue(trade, ratesProvider, discountingProvider, pvProduct);
}
/**
* Calculates the present value of the bond trade with z-spread.
* <p>
* The present value of the trade is the value on the valuation date.
* The result is expressed using the payment currency of the bond.
* <p>
* The z-spread is a parallel shift applied to continuously compounded rates or periodic
* compounded rates of the discounting curve.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the present value of the bond trade
*/
public CurrencyAmount presentValueWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
validate(ratesProvider, discountingProvider);
LocalDate settlementDate = trade.getSettlementDate();
CurrencyAmount pvProduct = productPricer.presentValueWithZSpread(
trade.getProduct(), ratesProvider,
discountingProvider,
settlementDate,
zSpread,
compoundedRateType,
periodsPerYear);
return presentValueFromProductPresentValue(trade, ratesProvider, discountingProvider, pvProduct);
}
//-------------------------------------------------------------------------
/**
* Calculates the present value sensitivity of the bond trade.
* <p>
* The present value sensitivity of the trade is the sensitivity of the present value to
* the underlying curves.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @return the present value sensitivity of the bond trade
*/
public PointSensitivities presentValueSensitivity(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider) {
validate(ratesProvider, discountingProvider);
LocalDate settlementDate = trade.getSettlementDate();
PointSensitivityBuilder productSensi = productPricer.presentValueSensitivity(trade.getProduct(),
ratesProvider, discountingProvider, settlementDate);
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, productSensi).build();
}
/**
* Calculates the present value sensitivity of the bond trade with z-spread.
* <p>
* The present value sensitivity of the trade is the sensitivity of the present value to
* the underlying curves.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the present value sensitivity of the bond trade
*/
public PointSensitivities presentValueSensitivityWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
validate(ratesProvider, discountingProvider);
LocalDate settlementDate = trade.getSettlementDate();
PointSensitivityBuilder productSensi = productPricer.presentValueSensitivityWithZSpread(trade.getProduct(),
ratesProvider, discountingProvider, settlementDate, zSpread, compoundedRateType, periodsPerYear);
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, productSensi).build();
}
//-------------------------------------------------------------------------
/**
* Calculates the present value of the bond trade from the clean price.
* <p>
* Since the sign of the settlement notional is opposite to that of the product, negative amount will be returned
* for positive quantity of trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param refData the reference data used to calculate the settlement date
* @param discountingProvider the discount factors provider
* @param cleanRealPrice the clean real price
* @return the present value of the settlement
*/
public CurrencyAmount presentValueFromCleanPrice(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice) {
validate(ratesProvider, discountingProvider);
ResolvedCapitalIndexedBond bond = trade.getProduct();
LocalDate standardSettlementDate = bond.calculateSettlementDateFromValuation(ratesProvider.getValuationDate(), refData);
LocalDate tradeSettlementDate = trade.getSettlementDate();
StandardId legalEntityId = bond.getLegalEntityId();
Currency currency = bond.getCurrency();
double df = discountingProvider
.repoCurveDiscountFactors(bond.getSecurityId(), legalEntityId, currency).discountFactor(standardSettlementDate);
CurrencyAmount pvStandard = forecastValueStandardFromCleanPrice(
bond, ratesProvider, standardSettlementDate, cleanRealPrice).multipliedBy(df);
if (standardSettlementDate.isEqual(tradeSettlementDate)) {
return presentValueFromProductPresentValue(trade, ratesProvider, discountingProvider, pvStandard);
}
// check coupon payment between two settlement dates
IssuerCurveDiscountFactors discountFactors =
discountingProvider.issuerCurveDiscountFactors(legalEntityId, currency);
double pvDiff = 0d;
if (standardSettlementDate.isAfter(tradeSettlementDate)) {
pvDiff = -productPricer.presentValueCoupon(
bond, ratesProvider, discountFactors, tradeSettlementDate, standardSettlementDate);
} else {
pvDiff = productPricer.presentValueCoupon(
bond, ratesProvider, discountFactors, standardSettlementDate, tradeSettlementDate);
}
return presentValueFromProductPresentValue(
trade, ratesProvider, discountingProvider, pvStandard.plus(pvDiff));
}
/**
* Calculates the present value of the settlement of the bond trade from the clean price with z-spread.
* <p>
* Since the sign of the settlement notional is opposite to that of the product, negative amount will be returned
* for positive quantity of trade.
* <p>
* The z-spread is a parallel shift applied to continuously compounded rates or periodic
* compounded rates of the discounting curve.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @param cleanRealPrice the clean real price
* @return the present value of the settlement
*/
public CurrencyAmount presentValueFromCleanPriceWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
validate(ratesProvider, discountingProvider);
ResolvedCapitalIndexedBond bond = trade.getProduct();
LocalDate standardSettlementDate = bond.calculateSettlementDateFromValuation(ratesProvider.getValuationDate(), refData);
LocalDate tradeSettlementDate = trade.getSettlementDate();
StandardId legalEntityId = bond.getLegalEntityId();
Currency currency = bond.getCurrency();
double df = discountingProvider
.repoCurveDiscountFactors(bond.getSecurityId(), legalEntityId, currency).discountFactor(standardSettlementDate);
CurrencyAmount pvStandard = forecastValueStandardFromCleanPrice(
bond, ratesProvider, standardSettlementDate, cleanRealPrice).multipliedBy(df);
if (standardSettlementDate.isEqual(tradeSettlementDate)) {
return presentValueFromProductPresentValue(trade, ratesProvider, discountingProvider, pvStandard);
}
// check coupon payment between two settlement dates
IssuerCurveDiscountFactors discountFactors =
discountingProvider.issuerCurveDiscountFactors(legalEntityId, currency);
double pvDiff = 0d;
if (standardSettlementDate.isAfter(tradeSettlementDate)) {
pvDiff = -productPricer.presentValueCouponWithZSpread(
bond,
ratesProvider,
discountFactors,
tradeSettlementDate,
standardSettlementDate,
zSpread,
compoundedRateType,
periodsPerYear);
} else {
pvDiff = productPricer.presentValueCouponWithZSpread(
bond,
ratesProvider,
discountFactors,
standardSettlementDate,
tradeSettlementDate,
zSpread,
compoundedRateType,
periodsPerYear);
}
return presentValueFromProductPresentValue(
trade, ratesProvider, discountingProvider, pvStandard.plus(pvDiff));
}
//-------------------------------------------------------------------------
/**
* Calculates the present value sensitivity of the settlement of the bond trade from the real clean price.
* <p>
* The present value sensitivity of the settlement is the sensitivity of the present value to
* the underlying curves.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param refData the reference data used to calculate the settlement date
* @param discountingProvider the discount factors provider
* @param cleanRealPrice the clean real price
* @return the present value sensitivity of the settlement
*/
public PointSensitivities presentValueSensitivityFromCleanPrice(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice) {
validate(ratesProvider, discountingProvider);
ResolvedCapitalIndexedBond bond = trade.getProduct();
LocalDate standardSettlementDate = bond.calculateSettlementDateFromValuation(ratesProvider.getValuationDate(), refData);
LocalDate tradeSettlementDate = trade.getSettlementDate();
StandardId legalEntityId = bond.getLegalEntityId();
Currency currency = bond.getCurrency();
RepoCurveDiscountFactors repoDiscountFactors =
discountingProvider.repoCurveDiscountFactors(bond.getSecurityId(), legalEntityId, currency);
double df = repoDiscountFactors.discountFactor(standardSettlementDate);
PointSensitivityBuilder dfSensi = repoDiscountFactors.zeroRatePointSensitivity(standardSettlementDate);
PointSensitivityBuilder pvSensiStandard = forecastValueSensitivityStandardFromCleanPrice(bond, ratesProvider,
standardSettlementDate, cleanRealPrice).multipliedBy(df).combinedWith(dfSensi.multipliedBy(
forecastValueStandardFromCleanPrice(bond, ratesProvider, standardSettlementDate, cleanRealPrice)
.getAmount()));
if (standardSettlementDate.isEqual(tradeSettlementDate)) {
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, pvSensiStandard).build();
}
// check coupon payment between two settlement dates
IssuerCurveDiscountFactors issuerDiscountFactors =
discountingProvider.issuerCurveDiscountFactors(legalEntityId, currency);
PointSensitivityBuilder pvSensiDiff = PointSensitivityBuilder.none();
if (standardSettlementDate.isAfter(tradeSettlementDate)) {
pvSensiDiff = pvSensiDiff.combinedWith(productPricer.presentValueSensitivityCoupon(bond, ratesProvider,
issuerDiscountFactors, tradeSettlementDate, standardSettlementDate).multipliedBy(-1d));
} else {
pvSensiDiff = pvSensiDiff.combinedWith(productPricer.presentValueSensitivityCoupon(bond, ratesProvider,
issuerDiscountFactors, standardSettlementDate, tradeSettlementDate));
}
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, pvSensiStandard.combinedWith(pvSensiDiff)).build();
}
/**
* Calculates the present value sensitivity of the settlement of the bond trade from the real clean price
* with z-spread.
* <p>
* The present value sensitivity of the settlement is the sensitivity of the present value to
* the underlying curves.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param refData the reference data used to calculate the settlement date
* @param discountingProvider the discount factors provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @param cleanRealPrice the clean real price
* @return the present value sensitivity of the settlement
*/
public PointSensitivities presentValueSensitivityFromCleanPriceWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
validate(ratesProvider, discountingProvider);
ResolvedCapitalIndexedBond bond = trade.getProduct();
LocalDate standardSettlementDate = bond.calculateSettlementDateFromValuation(ratesProvider.getValuationDate(), refData);
LocalDate tradeSettlementDate = trade.getSettlementDate();
StandardId legalEntityId = bond.getLegalEntityId();
Currency currency = bond.getCurrency();
RepoCurveDiscountFactors repoDiscountFactors =
discountingProvider.repoCurveDiscountFactors(bond.getSecurityId(), legalEntityId, currency);
double df = repoDiscountFactors.discountFactor(standardSettlementDate);
PointSensitivityBuilder dfSensi = repoDiscountFactors.zeroRatePointSensitivity(standardSettlementDate);
PointSensitivityBuilder pvSensiStandard = forecastValueSensitivityStandardFromCleanPrice(bond, ratesProvider,
standardSettlementDate, cleanRealPrice).multipliedBy(df).combinedWith(dfSensi.multipliedBy(
forecastValueStandardFromCleanPrice(bond, ratesProvider, standardSettlementDate, cleanRealPrice)
.getAmount()));
if (standardSettlementDate.isEqual(tradeSettlementDate)) {
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, pvSensiStandard).build();
}
// check coupon payment between two settlement dates
IssuerCurveDiscountFactors issuerDiscountFactors =
discountingProvider.issuerCurveDiscountFactors(legalEntityId, currency);
PointSensitivityBuilder pvSensiDiff = PointSensitivityBuilder.none();
if (standardSettlementDate.isAfter(tradeSettlementDate)) {
pvSensiDiff = pvSensiDiff.combinedWith(productPricer.presentValueSensitivityCouponWithZSpread(
bond,
ratesProvider,
issuerDiscountFactors,
tradeSettlementDate,
standardSettlementDate,
zSpread,
compoundedRateType,
periodsPerYear)
.multipliedBy(-1d));
} else {
pvSensiDiff = pvSensiDiff.combinedWith(productPricer.presentValueSensitivityCouponWithZSpread(
bond,
ratesProvider,
issuerDiscountFactors,
standardSettlementDate,
tradeSettlementDate,
zSpread,
compoundedRateType,
periodsPerYear));
}
return presentValueSensitivityFromProductPresentValueSensitivity(
trade, ratesProvider, discountingProvider, pvSensiStandard.combinedWith(pvSensiDiff)).build();
}
//-------------------------------------------------------------------------
/**
* Calculates the currency exposure of the bond trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param cleanRealPrice the clean real price
* @return the currency exposure of the trade
*/
public MultiCurrencyAmount currencyExposureFromCleanPrice(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice) {
CurrencyAmount pv = presentValueFromCleanPrice(
trade, ratesProvider, discountingProvider, refData, cleanRealPrice);
return MultiCurrencyAmount.of(pv);
}
/**
* Calculates the currency exposure of the bond trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @return the currency exposure of the trade
*/
public MultiCurrencyAmount currencyExposure(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider) {
CurrencyAmount pv = presentValue(trade, ratesProvider, discountingProvider);
return MultiCurrencyAmount.of(pv);
}
/**
* Calculates the currency exposure of the bond trade with z-spread.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @param cleanRealPrice the clean real price
* @return the currency exposure of the trade
*/
public MultiCurrencyAmount currencyExposureFromCleanPriceWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double cleanRealPrice,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
CurrencyAmount pv = presentValueFromCleanPriceWithZSpread(
trade,
ratesProvider,
discountingProvider,
refData,
cleanRealPrice,
zSpread,
compoundedRateType,
periodsPerYear);
return MultiCurrencyAmount.of(pv);
}
/**
* Calculates the currency exposure of the bond trade with z-spread.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the currency exposure of the trade
*/
public MultiCurrencyAmount currencyExposureWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
CurrencyAmount pv = presentValueWithZSpread(
trade,
ratesProvider,
discountingProvider,
zSpread,
compoundedRateType,
periodsPerYear);
return MultiCurrencyAmount.of(pv);
}
/**
* Calculates the current of the bond trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @return the current cash
*/
public CurrencyAmount currentCash(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider) {
LocalDate valuationDate = ratesProvider.getValuationDate();
LocalDate settlementDate = trade.getSettlementDate();
BondPaymentPeriod settle = trade.getSettlement();
CurrencyAmount cashProduct = productPricer.currentCash(trade.getProduct(), ratesProvider, settlementDate);
double cashSettle =
settle.getPaymentDate().isEqual(valuationDate) ? netAmount(trade, ratesProvider).getAmount() : 0d;
return cashProduct.plus(cashSettle);
}
//-------------------------------------------------------------------------
/**
* Calculates the net amount of the settlement of the bond trade.
* <p>
* Since the sign of the settlement notional is opposite to that of the product, negative amount will be returned
* for positive quantity of trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @return the net amount
*/
public CurrencyAmount netAmount(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider) {
BondPaymentPeriod settlement = trade.getSettlement();
if (settlement instanceof KnownAmountBondPaymentPeriod) {
Payment payment = ((KnownAmountBondPaymentPeriod) settlement).getPayment();
return payment.getValue();
} else if (settlement instanceof CapitalIndexedBondPaymentPeriod) {
CapitalIndexedBondPaymentPeriod casted = (CapitalIndexedBondPaymentPeriod) settlement;
double netAmount = productPricer.getPeriodPricer().forecastValue(casted, ratesProvider);
return CurrencyAmount.of(casted.getCurrency(), netAmount);
}
throw new UnsupportedOperationException("unsupported settlement type");
}
//-------------------------------------------------------------------------
private CurrencyAmount presentValueSettlement(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider) {
BondPaymentPeriod settlement = trade.getSettlement();
ResolvedCapitalIndexedBond product = trade.getProduct();
RepoCurveDiscountFactors discountFactors = discountingProvider.repoCurveDiscountFactors(
product.getSecurityId(), product.getLegalEntityId(), product.getCurrency());
return netAmount(trade, ratesProvider).multipliedBy(discountFactors.discountFactor(settlement.getPaymentDate()));
}
private CurrencyAmount presentValueFromProductPresentValue(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
CurrencyAmount productPresentValue) {
CurrencyAmount pvProduct = productPresentValue.multipliedBy(trade.getQuantity());
CurrencyAmount pvPayment = presentValueSettlement(trade, ratesProvider, discountingProvider);
return pvProduct.plus(pvPayment);
}
CurrencyAmount forecastValueStandardFromCleanPrice(
ResolvedCapitalIndexedBond product,
RatesProvider ratesProvider,
LocalDate standardSettlementDate,
double realCleanPrice) {
double notional = product.getNotional();
double netAmountReal = realCleanPrice * notional + product.accruedInterest(standardSettlementDate);
double indexRatio = product.getYieldConvention().equals(CapitalIndexedBondYieldConvention.GB_IL_FLOAT) ?
1d :
productPricer.indexRatio(product, ratesProvider, standardSettlementDate);
return CurrencyAmount.of(product.getCurrency(), indexRatio * netAmountReal);
}
//-------------------------------------------------------------------------
private PointSensitivityBuilder netAmountSensitivity(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider) {
BondPaymentPeriod settlement = trade.getSettlement();
if (settlement instanceof KnownAmountBondPaymentPeriod) {
return PointSensitivityBuilder.none();
} else if (settlement instanceof CapitalIndexedBondPaymentPeriod) {
CapitalIndexedBondPaymentPeriod casted = (CapitalIndexedBondPaymentPeriod) settlement;
return productPricer.getPeriodPricer().forecastValueSensitivity(casted, ratesProvider);
}
throw new UnsupportedOperationException("unsupported settlement type");
}
private PointSensitivityBuilder presentValueSensitivitySettlement(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider) {
BondPaymentPeriod settlement = trade.getSettlement();
ResolvedCapitalIndexedBond product = trade.getProduct();
RepoCurveDiscountFactors discountFactors = discountingProvider.repoCurveDiscountFactors(
product.getSecurityId(), product.getLegalEntityId(), product.getCurrency());
double df = discountFactors.discountFactor(settlement.getPaymentDate());
double netAmount = netAmount(trade, ratesProvider).getAmount();
PointSensitivityBuilder dfSensi =
discountFactors.zeroRatePointSensitivity(settlement.getPaymentDate()).multipliedBy(netAmount);
PointSensitivityBuilder naSensi = netAmountSensitivity(trade, ratesProvider).multipliedBy(df);
return dfSensi.combinedWith(naSensi);
}
private PointSensitivityBuilder presentValueSensitivityFromProductPresentValueSensitivity(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
PointSensitivityBuilder productPresnetValueSensitivity) {
PointSensitivityBuilder sensiProduct = productPresnetValueSensitivity.multipliedBy(trade.getQuantity());
PointSensitivityBuilder sensiPayment =
presentValueSensitivitySettlement(trade, ratesProvider, discountingProvider);
return sensiProduct.combinedWith(sensiPayment);
}
PointSensitivityBuilder forecastValueSensitivityStandardFromCleanPrice(
ResolvedCapitalIndexedBond product,
RatesProvider ratesProvider,
LocalDate standardSettlementDate,
double realCleanPrice) {
if (product.getYieldConvention().equals(CapitalIndexedBondYieldConvention.GB_IL_FLOAT)) {
return PointSensitivityBuilder.none();
}
double notional = product.getNotional();
double netAmountReal = realCleanPrice * notional + product.accruedInterest(standardSettlementDate);
PointSensitivityBuilder indexRatioSensi =
productPricer.indexRatioSensitivity(product, ratesProvider, standardSettlementDate);
return indexRatioSensi.multipliedBy(netAmountReal);
}
//-------------------------------------------------------------------------
private void validate(RatesProvider ratesProvider, LegalEntityDiscountingProvider discountingProvider) {
ArgChecker.isTrue(ratesProvider.getValuationDate().isEqual(discountingProvider.getValuationDate()),
"the rates providers should be for the same date");
}
//-------------------------------------------------------------------------
/**
* Calculates the present value of the bond trade.
* <p>
* The present value of the trade is the value on the valuation date.
* The result is expressed using the payment currency of the bond.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @return the present value of the bond trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public CurrencyAmount presentValue(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData) {
return presentValue(trade, ratesProvider, discountingProvider);
}
/**
* Calculates the present value of the bond trade with z-spread.
* <p>
* The present value of the trade is the value on the valuation date.
* The result is expressed using the payment currency of the bond.
* <p>
* The z-spread is a parallel shift applied to continuously compounded rates or periodic
* compounded rates of the discounting curve.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the present value of the bond trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public CurrencyAmount presentValueWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
return presentValueWithZSpread(trade, ratesProvider, discountingProvider, zSpread, compoundedRateType, periodsPerYear);
}
//-------------------------------------------------------------------------
/**
* Calculates the present value sensitivity of the bond trade.
* <p>
* The present value sensitivity of the trade is the sensitivity of the present value to
* the underlying curves.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @return the present value sensitivity of the bond trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public PointSensitivities presentValueSensitivity(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData) {
return presentValueSensitivity(trade, ratesProvider, discountingProvider);
}
/**
* Calculates the present value sensitivity of the bond trade with z-spread.
* <p>
* The present value sensitivity of the trade is the sensitivity of the present value to
* the underlying curves.
* <p>
* Coupon payments of the underlying product are considered based on the settlement date of the trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the present value sensitivity of the bond trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public PointSensitivities presentValueSensitivityWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
return presentValueSensitivityWithZSpread(
trade, ratesProvider, discountingProvider, zSpread, compoundedRateType, periodsPerYear);
}
/**
* Calculates the currency exposure of the bond trade.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @return the currency exposure of the trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public MultiCurrencyAmount currencyExposure(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData) {
return currencyExposure(trade, ratesProvider, discountingProvider);
}
/**
* Calculates the currency exposure of the bond trade with z-spread.
*
* @param trade the trade
* @param ratesProvider the rates provider, used to determine price index values
* @param discountingProvider the discount factors provider
* @param refData the reference data used to calculate the settlement date
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodsPerYear the number of periods per year
* @return the currency exposure of the trade
* @deprecated Use the method of the same name that does not take {@code ReferenceData}
*/
@Deprecated
public MultiCurrencyAmount currencyExposureWithZSpread(
ResolvedCapitalIndexedBondTrade trade,
RatesProvider ratesProvider,
LegalEntityDiscountingProvider discountingProvider,
ReferenceData refData,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
return currencyExposureWithZSpread(
trade, ratesProvider, discountingProvider, zSpread, compoundedRateType, periodsPerYear);
}
}