com.opengamma.strata.pricer.bond.DiscountingBondFutureProductPricer Maven / Gradle / Ivy
/*
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.bond;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Doubles;
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.product.bond.FixedCouponBond;
import com.opengamma.strata.product.bond.ResolvedBondFuture;
import com.opengamma.strata.product.bond.ResolvedFixedCouponBond;
/**
* Pricer for for bond future products.
*
* This function provides the ability to price a {@link ResolvedBondFuture}.
*
*
Price
* Strata uses decimal prices for bond futures in the trade model, pricers and market data.
* This is coherent with the pricing of {@link FixedCouponBond}. The bond futures delivery is a bond
* for an amount computed from the bond future price, a conversion factor and the accrued interest.
*/
public final class DiscountingBondFutureProductPricer {
/**
* Default implementation.
*/
public static final DiscountingBondFutureProductPricer DEFAULT = new DiscountingBondFutureProductPricer(
DiscountingFixedCouponBondProductPricer.DEFAULT);
/**
* Underlying pricer.
*/
private final DiscountingFixedCouponBondProductPricer bondPricer;
/**
* Creates an instance.
*
* @param bondPricer the pricer for {@link ResolvedFixedCouponBond}.
*/
public DiscountingBondFutureProductPricer(DiscountingFixedCouponBondProductPricer bondPricer) {
this.bondPricer = ArgChecker.notNull(bondPricer, "bondPricer");
}
//-------------------------------------------------------------------------
/**
* Calculates the number related to bond futures product on which the daily margin is computed.
*
* For two consecutive settlement prices C1 and C2, the daily margin is computed as
* {@code (marginIndex(future, C2) - marginIndex(future, C1))}.
*
* @param future the future
* @param price the price of the product, in decimal form
* @return the index
*/
double marginIndex(ResolvedBondFuture future, double price) {
return price * future.getNotional();
}
/**
* Calculates the margin index sensitivity of the bond future product.
*
* The margin index sensitivity is the sensitivity of the margin index to the underlying curves.
* For two consecutive settlement prices C1 and C2, the daily margin is computed as
* {@code (marginIndex(future, C2) - marginIndex(future, C1))}.
*
* @param future the future
* @param priceSensitivity the price sensitivity of the product
* @return the index sensitivity
*/
PointSensitivities marginIndexSensitivity(ResolvedBondFuture future, PointSensitivities priceSensitivity) {
return priceSensitivity.multipliedBy(future.getNotional());
}
//-------------------------------------------------------------------------
/**
* Calculates the price of the bond future product.
*
* The price of the product is the price on the valuation date.
*
* Strata uses decimal prices for bond futures. This is coherent with the pricing of {@link FixedCouponBond}.
* For example, a price of 99.32% is represented in Strata by 0.9932.
*
* @param future the future
* @param discountingProvider the discounting provider
* @return the price of the product, in decimal form
*/
public double price(ResolvedBondFuture future, LegalEntityDiscountingProvider discountingProvider) {
ImmutableList basket = future.getDeliveryBasket();
int size = basket.size();
double[] priceBonds = new double[size];
for (int i = 0; i < size; ++i) {
ResolvedFixedCouponBond bond = basket.get(i);
double dirtyPrice = bondPricer.dirtyPriceFromCurves(bond, discountingProvider, future.getLastDeliveryDate());
priceBonds[i] = bondPricer.cleanPriceFromDirtyPrice(
bond, future.getLastDeliveryDate(), dirtyPrice) / future.getConversionFactors().get(i);
}
return Doubles.min(priceBonds);
}
/**
* Calculates the price of the bond future product with z-spread.
*
* The price of the product is the price on the valuation date.
*
* The z-spread is a parallel shift applied to continuously compounded rates or periodic compounded rates
* of the issuer discounting curve.
*
* Strata uses decimal prices for bond futures. This is coherent with the pricing of {@link FixedCouponBond}.
* For example, a price of 99.32% is represented in Strata by 0.9932.
*
* @param future the future
* @param discountingProvider the discounting provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodPerYear the number of periods per year
* @return the price of the product, in decimal form
*/
public double priceWithZSpread(
ResolvedBondFuture future,
LegalEntityDiscountingProvider discountingProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodPerYear) {
ImmutableList basket = future.getDeliveryBasket();
int size = basket.size();
double[] priceBonds = new double[size];
for (int i = 0; i < size; ++i) {
ResolvedFixedCouponBond bond = basket.get(i);
double dirtyPrice = bondPricer.dirtyPriceFromCurvesWithZSpread(
bond, discountingProvider, zSpread, compoundedRateType, periodPerYear, future.getLastDeliveryDate());
priceBonds[i] = bondPricer.cleanPriceFromDirtyPrice(
bond, future.getLastDeliveryDate(), dirtyPrice) / future.getConversionFactors().get(i);
}
return Doubles.min(priceBonds);
}
//-------------------------------------------------------------------------
/**
* Calculates the price sensitivity of the bond future product.
*
* The price sensitivity of the product is the sensitivity of the price to the underlying curves.
*
* Note that the price sensitivity should be no currency.
*
* @param future the future
* @param discountingProvider the discounting provider
* @return the price curve sensitivity of the product
*/
public PointSensitivities priceSensitivity(ResolvedBondFuture future, LegalEntityDiscountingProvider discountingProvider) {
ImmutableList basket = future.getDeliveryBasket();
int size = basket.size();
double[] priceBonds = new double[size];
int indexCTD = 0;
double priceMin = 2d;
for (int i = 0; i < size; i++) {
ResolvedFixedCouponBond bond = basket.get(i);
double dirtyPrice = bondPricer.dirtyPriceFromCurves(bond, discountingProvider, future.getLastDeliveryDate());
priceBonds[i] = bondPricer.cleanPriceFromDirtyPrice(
bond, future.getLastDeliveryDate(), dirtyPrice) / future.getConversionFactors().get(i);
if (priceBonds[i] < priceMin) {
priceMin = priceBonds[i];
indexCTD = i;
}
}
ResolvedFixedCouponBond bond = basket.get(indexCTD);
PointSensitivityBuilder pointSensi = bondPricer.dirtyPriceSensitivity(
bond, discountingProvider, future.getLastDeliveryDate());
return pointSensi.multipliedBy(1d / future.getConversionFactors().get(indexCTD)).build();
}
/**
* Calculates the price sensitivity of the bond future product with z-spread.
*
* The price sensitivity of the product is the sensitivity of the price to the underlying curves.
*
* The z-spread is a parallel shift applied to continuously compounded rates or periodic compounded rates
* of the issuer discounting curve.
*
* Note that the price sensitivity should be no currency.
*
* @param future the future
* @param discountingProvider the discounting provider
* @param zSpread the z-spread
* @param compoundedRateType the compounded rate type
* @param periodPerYear the number of periods per year
* @return the price curve sensitivity of the product
*/
public PointSensitivities priceSensitivityWithZSpread(
ResolvedBondFuture future,
LegalEntityDiscountingProvider discountingProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodPerYear) {
ImmutableList basket = future.getDeliveryBasket();
int size = basket.size();
double[] priceBonds = new double[size];
int indexCTD = 0;
double priceMin = 2d;
for (int i = 0; i < size; i++) {
ResolvedFixedCouponBond bond = basket.get(i);
double dirtyPrice = bondPricer.dirtyPriceFromCurvesWithZSpread(
bond, discountingProvider, zSpread, compoundedRateType, periodPerYear, future.getLastDeliveryDate());
priceBonds[i] = bondPricer.cleanPriceFromDirtyPrice(
bond, future.getLastDeliveryDate(), dirtyPrice) / future.getConversionFactors().get(i);
if (priceBonds[i] < priceMin) {
priceMin = priceBonds[i];
indexCTD = i;
}
}
ResolvedFixedCouponBond bond = basket.get(indexCTD);
PointSensitivityBuilder pointSensi = bondPricer.dirtyPriceSensitivityWithZspread(
bond, discountingProvider, zSpread, compoundedRateType, periodPerYear, future.getLastDeliveryDate());
return pointSensi.multipliedBy(1d / future.getConversionFactors().get(indexCTD)).build();
}
}