com.opengamma.strata.pricer.capfloor.SabrIborCapletFloorletPeriodPricer Maven / Gradle / Ivy
/*
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.capfloor;
import static com.opengamma.strata.market.model.SabrParameterType.ALPHA;
import static com.opengamma.strata.market.model.SabrParameterType.BETA;
import static com.opengamma.strata.market.model.SabrParameterType.NU;
import static com.opengamma.strata.market.model.SabrParameterType.RHO;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.value.ValueDerivatives;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.capfloor.IborCapletFloorletPeriod;
import com.opengamma.strata.product.common.PutCall;
/**
* Pricer for caplet/floorlet in SABR model.
*
* The value of the caplet/floorlet after expiry is a fixed payoff amount. The value is zero if valuation date is
* after payment date of the caplet/floorlet.
*/
public class SabrIborCapletFloorletPeriodPricer
extends VolatilityIborCapletFloorletPeriodPricer {
/**
* Default implementation.
*/
public static final SabrIborCapletFloorletPeriodPricer DEFAULT = new SabrIborCapletFloorletPeriodPricer();
@Override
protected void validate(IborCapletFloorletVolatilities volatilities) {
ArgChecker.isTrue(volatilities instanceof SabrIborCapletFloorletVolatilities, "volatilities must be SABR volatilities");
}
//-------------------------------------------------------------------------
/**
* Calculates the present value sensitivity of the Ibor caplet/floorlet to the rate curves.
*
* The present value sensitivity is computed in a "sticky model parameter" style, i.e. the sensitivity to the
* curve nodes with the SABR model parameters unchanged. This sensitivity does not include a potential
* re-calibration of the model parameters to the raw market data.
*
* @param period the Ibor caplet/floorlet period
* @param ratesProvider the rates provider
* @param volatilities the volatilities
* @return the point sensitivity to the rate curves
*/
public PointSensitivityBuilder presentValueSensitivityRatesStickyModel(
IborCapletFloorletPeriod period,
RatesProvider ratesProvider,
SabrIborCapletFloorletVolatilities volatilities) {
Currency currency = period.getCurrency();
if (ratesProvider.getValuationDate().isAfter(period.getPaymentDate())) {
return PointSensitivityBuilder.none();
}
double expiry = volatilities.relativeTime(period.getFixingDateTime());
PutCall putCall = period.getPutCall();
double strike = period.getStrike();
double indexRate = ratesProvider.iborIndexRates(period.getIndex()).rate(period.getIborRate().getObservation());
PointSensitivityBuilder dfSensi = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(period.getPaymentDate());
double factor = period.getNotional() * period.getYearFraction();
if (expiry < 0d) { // option expired already, but not yet paid
double sign = putCall.isCall() ? 1d : -1d;
double payoff = Math.max(sign * (indexRate - strike), 0d);
return dfSensi.multipliedBy(payoff * factor);
}
ValueDerivatives volatilityAdj = volatilities.volatilityAdjoint(expiry, strike, indexRate);
PointSensitivityBuilder indexRateSensiSensi =
ratesProvider.iborIndexRates(period.getIndex()).ratePointSensitivity(period.getIborRate().getObservation());
double df = ratesProvider.discountFactor(currency, period.getPaymentDate());
double fwdPv = factor * volatilities.price(expiry, putCall, strike, indexRate, volatilityAdj.getValue());
double fwdDelta = factor * volatilities.priceDelta(expiry, putCall, strike, indexRate, volatilityAdj.getValue());
double fwdVega = factor * volatilities.priceVega(expiry, putCall, strike, indexRate, volatilityAdj.getValue());
return dfSensi.multipliedBy(fwdPv).combinedWith(
indexRateSensiSensi.multipliedBy(fwdDelta * df + fwdVega * volatilityAdj.getDerivative(0) * df));
}
//-------------------------------------------------------------------------
/**
* Calculates the present value sensitivity to the SABR model parameters of the Ibor caplet/floorlet.
*
* The sensitivity of the present value to the SABR model parameters, alpha, beta, rho and nu.
*
* @param period the Ibor caplet/floorlet period
* @param ratesProvider the rates provider
* @param volatilities the volatilities
* @return the point sensitivity to the SABR model parameters
*/
public PointSensitivityBuilder presentValueSensitivityModelParamsSabr(
IborCapletFloorletPeriod period,
RatesProvider ratesProvider,
SabrIborCapletFloorletVolatilities volatilities) {
double expiry = volatilities.relativeTime(period.getFixingDateTime());
if (expiry < 0d) { // option expired already
return PointSensitivityBuilder.none();
}
Currency currency = period.getCurrency();
PutCall putCall = period.getPutCall();
double strike = period.getStrike();
double indexRate = ratesProvider.iborIndexRates(period.getIndex()).rate(period.getIborRate().getObservation());
double factor = period.getNotional() * period.getYearFraction();
ValueDerivatives volatilityAdj = volatilities.volatilityAdjoint(expiry, strike, indexRate);
DoubleArray derivative = volatilityAdj.getDerivatives();
double df = ratesProvider.discountFactor(currency, period.getPaymentDate());
double vega = df * factor * volatilities.priceVega(expiry, putCall, strike, indexRate, volatilityAdj.getValue());
IborCapletFloorletVolatilitiesName name = volatilities.getName();
return PointSensitivityBuilder.of(
IborCapletFloorletSabrSensitivity.of(name, expiry, ALPHA, currency, vega * derivative.get(2)),
IborCapletFloorletSabrSensitivity.of(name, expiry, BETA, currency, vega * derivative.get(3)),
IborCapletFloorletSabrSensitivity.of(name, expiry, RHO, currency, vega * derivative.get(4)),
IborCapletFloorletSabrSensitivity.of(name, expiry, NU, currency, vega * derivative.get(5)));
}
}