All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.pricer.swaption.SabrSwaptionPhysicalProductPricer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.pricer.swaption;

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 java.time.ZonedDateTime;

import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.value.ValueDerivatives;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.impl.option.BlackFormulaRepository;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer;
import com.opengamma.strata.product.swap.ResolvedSwap;
import com.opengamma.strata.product.swap.ResolvedSwapLeg;
import com.opengamma.strata.product.swap.Swap;
import com.opengamma.strata.product.swaption.ResolvedSwaption;

/**
 * Pricer for swaption with physical settlement in SABR model on the swap rate.
 * 

* The swap underlying the swaption must have a fixed leg on which the forward rate is computed. * The underlying swap must be single currency. *

* The volatility parameters are not adjusted for the underlying swap convention. * The volatilities from the provider are taken as such. *

* The value of the swaption after expiry is 0. For a swaption which already expired, negative number is returned by * the method, {@link SabrSwaptionVolatilities#relativeTime(ZonedDateTime)}. */ public class SabrSwaptionPhysicalProductPricer extends VolatilitySwaptionPhysicalProductPricer { /** * Default implementation. */ public static final SabrSwaptionPhysicalProductPricer DEFAULT = new SabrSwaptionPhysicalProductPricer(DiscountingSwapProductPricer.DEFAULT); /** * Creates an instance. * * @param swapPricer the pricer for {@link Swap} */ public SabrSwaptionPhysicalProductPricer(DiscountingSwapProductPricer swapPricer) { super(swapPricer); } //------------------------------------------------------------------------- /** * Calculates the present value sensitivity of the swaption product 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 swaption the swaption product * @param ratesProvider the rates provider * @param swaptionVolatilities the volatilities * @return the point sensitivity to the rate curves */ public PointSensitivityBuilder presentValueSensitivityRatesStickyModel( ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); ZonedDateTime expiryDateTime = swaption.getExpiry(); double expiry = swaptionVolatilities.relativeTime(expiryDateTime); ResolvedSwap underlying = swaption.getUnderlying(); ResolvedSwapLeg fixedLeg = fixedLeg(underlying); if (expiry < 0d) { // Option has expired already return PointSensitivityBuilder.none(); } double forward = forwardRate(swaption, ratesProvider); double pvbp = getSwapPricer().getLegPricer().pvbp(fixedLeg, ratesProvider); double strike = getSwapPricer().getLegPricer().couponEquivalent(fixedLeg, ratesProvider, pvbp); double tenor = swaptionVolatilities.tenor(fixedLeg.getStartDate(), fixedLeg.getEndDate()); double shift = swaptionVolatilities.shift(expiry, tenor); ValueDerivatives volatilityAdj = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward); boolean isCall = fixedLeg.getPayReceive().isPay(); // Payer at strike is exercise when rate > strike, i.e. call on rate // Backward sweep PointSensitivityBuilder pvbpDr = getSwapPricer().getLegPricer().pvbpSensitivity(fixedLeg, ratesProvider); PointSensitivityBuilder forwardDr = getSwapPricer().parRateSensitivity(underlying, ratesProvider); double shiftedForward = forward + shift; double shiftedStrike = strike + shift; double price = BlackFormulaRepository.price(shiftedForward, shiftedStrike, expiry, volatilityAdj.getValue(), isCall); double delta = BlackFormulaRepository.delta(shiftedForward, shiftedStrike, expiry, volatilityAdj.getValue(), isCall); double vega = BlackFormulaRepository.vega(shiftedForward, shiftedStrike, expiry, volatilityAdj.getValue()); double sign = swaption.getLongShort().sign(); return pvbpDr.multipliedBy(price * sign * Math.signum(pvbp)) .combinedWith(forwardDr.multipliedBy((delta + vega * volatilityAdj.getDerivative(0)) * Math.abs(pvbp) * sign)); } //------------------------------------------------------------------------- /** * Calculates the present value sensitivity to the SABR model parameters of the swaption product. *

* The sensitivity of the present value to the SABR model parameters, alpha, beta, rho and nu. * * @param swaption the swaption product * @param ratesProvider the rates provider * @param swaptionVolatilities the volatilities * @return the point sensitivity to the SABR model parameters */ public PointSensitivityBuilder presentValueSensitivityModelParamsSabr( ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.getExpiry()); ResolvedSwap underlying = swaption.getUnderlying(); ResolvedSwapLeg fixedLeg = fixedLeg(underlying); double tenor = swaptionVolatilities.tenor(fixedLeg.getStartDate(), fixedLeg.getEndDate()); double shift = swaptionVolatilities.shift(expiry, tenor); double pvbp = getSwapPricer().getLegPricer().pvbp(fixedLeg, ratesProvider); double strike = getSwapPricer().getLegPricer().couponEquivalent(fixedLeg, ratesProvider, pvbp); if (expiry < 0d) { // Option has expired already return PointSensitivityBuilder.none(); } double forward = forwardRate(swaption, ratesProvider); double volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward); DoubleArray derivative = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward).getDerivatives(); // Backward sweep double vega = Math.abs(pvbp) * BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility) * swaption.getLongShort().sign(); // sensitivities Currency ccy = fixedLeg.getCurrency(); SwaptionVolatilitiesName name = swaptionVolatilities.getName(); return PointSensitivityBuilder.of( SwaptionSabrSensitivity.of(name, expiry, tenor, ALPHA, ccy, vega * derivative.get(2)), SwaptionSabrSensitivity.of(name, expiry, tenor, BETA, ccy, vega * derivative.get(3)), SwaptionSabrSensitivity.of(name, expiry, tenor, RHO, ccy, vega * derivative.get(4)), SwaptionSabrSensitivity.of(name, expiry, tenor, NU, ccy, vega * derivative.get(5))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy