com.opengamma.strata.pricer.bond.BlackBondFutureOptionMarginedProductPricer 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.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.pricer.impl.option.BlackFormulaRepository;
import com.opengamma.strata.product.bond.BondFuture;
import com.opengamma.strata.product.bond.ResolvedBondFuture;
import com.opengamma.strata.product.bond.ResolvedBondFutureOption;
import com.opengamma.strata.product.option.FutureOptionPremiumStyle;
/**
* Pricer of options on bond future with a log-normal model on the underlying future price.
*
* Price
* Strata uses decimal prices for bond futures options in the trade model, pricers and market data.
* This is coherent with the pricing of {@link BondFuture}.
*/
public final class BlackBondFutureOptionMarginedProductPricer {
/**
* Default implementation.
*/
public static final BlackBondFutureOptionMarginedProductPricer DEFAULT =
new BlackBondFutureOptionMarginedProductPricer(DiscountingBondFutureProductPricer.DEFAULT);
/**
* The underlying future pricer.
* The pricer take only the curves as inputs, no model parameters.
*/
private final DiscountingBondFutureProductPricer futurePricer;
/**
* Creates an instance.
*
* @param futurePricer the pricer for {@link ResolvedBondFutureOption}
*/
public BlackBondFutureOptionMarginedProductPricer(
DiscountingBondFutureProductPricer futurePricer) {
this.futurePricer = ArgChecker.notNull(futurePricer, "futurePricer");
}
//-------------------------------------------------------------------------
/**
* Returns the underlying future pricer function.
*
* @return the future pricer
*/
DiscountingBondFutureProductPricer getFuturePricer() {
return futurePricer;
}
//-------------------------------------------------------------------------
/**
* 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 option the option product
* @param price the price of the product, in decimal form
* @return the index
*/
double marginIndex(ResolvedBondFutureOption option, double price) {
double notional = option.getUnderlyingFuture().getNotional();
return price * notional;
}
/**
* Calculates the margin index sensitivity of the bond future product.
*
* For two consecutive settlement prices C1 and C2, the daily margin is computed as
* {@code marginIndex(future, C2) - marginIndex(future, C1)}.
* The margin index sensitivity if the sensitivity of the margin index to the underlying curves.
*
* @param option the option product
* @param priceSensitivity the price sensitivity of the product
* @return the index sensitivity
*/
PointSensitivities marginIndexSensitivity(ResolvedBondFutureOption option, PointSensitivities priceSensitivity) {
double notional = option.getUnderlyingFuture().getNotional();
return priceSensitivity.multipliedBy(notional);
}
//-------------------------------------------------------------------------
/**
* Calculates the price of the bond future option product.
*
* The price of the option is the price on the valuation date.
*
* This calculates the underlying future price using the future pricer.
*
* Strata uses decimal prices for bond futures. This is coherent with the pricing of {@link BondFuture}.
* For example, a price of 1.32% is represented in Strata by 0.0132.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the price of the product, in decimal form
*/
public double price(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
double futurePrice = futurePrice(futureOption, discountingProvider);
return price(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the price of the bond future option product
* based on the price of the underlying future.
*
* The price of the option is the price on the valuation date.
*
* Strata uses decimal prices for bond futures. This is coherent with the pricing of {@link BondFuture}.
* For example, a price of 1.32% is represented in Strata by 0.0132.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the price of the underlying future
* @return the price of the product, in decimal form
*/
public double price(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double strike = futureOption.getStrikePrice();
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
double volatility = volatilities.volatility(
futureOption.getExpiry(), future.getLastTradeDate(), strike, futurePrice);
double timeToExpiry = volatilities.relativeTime(futureOption.getExpiry());
double price = BlackFormulaRepository.price(
futurePrice, strike, timeToExpiry, volatility, futureOption.getPutCall().isCall());
return price;
}
double price(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BondFutureVolatilities volatilities) {
ArgChecker.isTrue(volatilities instanceof BlackBondFutureVolatilities,
"Provider must be of type BlackVolatilityBondFutureProvider");
return price(futureOption, discountingProvider, (BlackBondFutureVolatilities) volatilities);
}
//-------------------------------------------------------------------------
/**
* Calculates the delta of the bond future option product.
*
* The delta of the product is the sensitivity of the option price to the future price.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* This calculates the underlying future price using the future pricer.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the price curve sensitivity of the product
*/
public double deltaStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
double futurePrice = futurePrice(futureOption, discountingProvider);
return deltaStickyStrike(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the delta of the bond future option product based on the price of the underlying future.
*
* The delta of the product is the sensitivity of the option price to the future price.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the price of the underlying future
* @return the price curve sensitivity of the product
*/
public double deltaStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double strike = futureOption.getStrikePrice();
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
double volatility = volatilities.volatility(futureOption.getExpiry(),
future.getLastTradeDate(), strike, futurePrice);
double timeToExpiry = volatilities.relativeTime(futureOption.getExpiry());
double delta = BlackFormulaRepository.delta(
futurePrice, strike, timeToExpiry, volatility, futureOption.getPutCall().isCall());
return delta;
}
//-------------------------------------------------------------------------
/**
* Calculates the gamma of the bond future option product.
*
* The gamma of the product is the sensitivity of the option delta to the future price.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* This calculates the underlying future price using the future pricer.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the price curve sensitivity of the product
*/
public double gammaStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
double futurePrice = futurePrice(futureOption, discountingProvider);
return gammaStickyStrike(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the gamma of the bond future option product based on the price of the underlying future.
*
* The gamma of the product is the sensitivity of the option delta to the future price.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the price of the underlying future
* @return the price curve sensitivity of the product
*/
public double gammaStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double strike = futureOption.getStrikePrice();
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
double volatility = volatilities.volatility(futureOption.getExpiry(),
future.getLastTradeDate(), strike, futurePrice);
double timeToExpiry = volatilities.relativeTime(futureOption.getExpiry());
double gamma = BlackFormulaRepository.gamma(futurePrice, strike, timeToExpiry, volatility);
return gamma;
}
//-------------------------------------------------------------------------
/**
* Calculates the theta of the bond future option product.
*
* The theta of the product is the minus of the option price sensitivity to the time to expiry.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* This calculates the underlying future price using the future pricer.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the price curve sensitivity of the product
*/
public double theta(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
double futurePrice = futurePrice(futureOption, discountingProvider);
return theta(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the theta of the bond future option product based on the price of the underlying future.
*
* The theta of the product is minus of the option price sensitivity to the time to expiry.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the price of the underlying future
* @return the price curve sensitivity of the product
*/
public double theta(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double strike = futureOption.getStrikePrice();
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
double volatility = volatilities.volatility(futureOption.getExpiry(),
future.getLastTradeDate(), strike, futurePrice);
double timeToExpiry = volatilities.relativeTime(futureOption.getExpiry());
double theta = BlackFormulaRepository.driftlessTheta(futurePrice, strike, timeToExpiry, volatility);
return theta;
}
//-------------------------------------------------------------------------
/**
* Calculates the price sensitivity of the bond future option product based on curves.
*
* The price sensitivity of the product is the sensitivity of the price to the underlying curves.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* This calculates the underlying future price using the future pricer.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the price curve sensitivity of the product
*/
public PointSensitivities priceSensitivityRatesStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double futurePrice = futurePrice(futureOption, discountingProvider);
return priceSensitivityRatesStickyStrike(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the price sensitivity of the bond future option product based on the price of the underlying future.
*
* The price sensitivity of the product is the sensitivity of the price to the underlying curves.
* The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the price of the underlying future
* @return the price curve sensitivity of the product
*/
public PointSensitivities priceSensitivityRatesStickyStrike(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
double delta = deltaStickyStrike(futureOption, discountingProvider, volatilities, futurePrice);
PointSensitivities futurePriceSensitivity =
futurePricer.priceSensitivity(futureOption.getUnderlyingFuture(), discountingProvider);
return futurePriceSensitivity.multipliedBy(delta);
}
PointSensitivities priceSensitivity(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BondFutureVolatilities volatilities) {
ArgChecker.isTrue(volatilities instanceof BlackBondFutureVolatilities,
"Provider must be of type BlackVolatilityBondFutureProvider");
return priceSensitivityRatesStickyStrike(
futureOption, discountingProvider, (BlackBondFutureVolatilities) volatilities);
}
//-------------------------------------------------------------------------
/**
* Calculates the price sensitivity to the Black volatility used for the pricing of the bond future option.
*
* This calculates the underlying future price using the future pricer.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @return the sensitivity
*/
public BondFutureOptionSensitivity priceSensitivityModelParamsVolatility(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities) {
double futurePrice = futurePrice(futureOption, discountingProvider);
return priceSensitivityModelParamsVolatility(futureOption, discountingProvider, volatilities, futurePrice);
}
/**
* Calculates the price sensitivity to the Black volatility used for the pricing of the bond future option
* based on the price of the underlying future.
*
* @param futureOption the option product
* @param discountingProvider the discounting provider
* @param volatilities the volatilities
* @param futurePrice the underlying future price
* @return the sensitivity
*/
public BondFutureOptionSensitivity priceSensitivityModelParamsVolatility(
ResolvedBondFutureOption futureOption,
LegalEntityDiscountingProvider discountingProvider,
BlackBondFutureVolatilities volatilities,
double futurePrice) {
ArgChecker.isTrue(futureOption.getPremiumStyle().equals(FutureOptionPremiumStyle.DAILY_MARGIN),
"Premium style should be DAILY_MARGIN");
double strike = futureOption.getStrikePrice();
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
double volatility = volatilities.volatility(futureOption.getExpiry(),
future.getLastTradeDate(), strike, futurePrice);
double timeToExpiry = volatilities.relativeTime(futureOption.getExpiry());
double vega = BlackFormulaRepository.vega(futurePrice, strike, timeToExpiry, volatility);
return BondFutureOptionSensitivity.of(
volatilities.getName(), timeToExpiry, future.getLastTradeDate(), strike, futurePrice, future.getCurrency(), vega);
}
//-------------------------------------------------------------------------
// calculate the price of the underlying future
private double futurePrice(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider) {
ResolvedBondFuture future = futureOption.getUnderlyingFuture();
return futurePricer.price(future, discountingProvider);
}
}