Main Content

Price Swaptions with Negative Strikes Using the Shifted SABR Model

This example shows how to price swaptions with negative strikes by using the Shifted SABR model. The market Shifted Black volatilities are used to calibrate the Shifted SABR model parameters. The calibrated Shifted SABR model is then used to compute the Shifted Black volatilities for negative strikes.

The swaptions with negative strikes are then priced using the computed Shifted Black volatilities and the swaptionbyblk function with the 'Shift' parameter set to the prespecified shift. Similarly, Shifted SABR Greeks can be computed by using the optsensbysabr function by setting the 'Shift' parameter. Finally, from the swaption prices, the probability density of the underlying asset is computed to show that the swaption prices imply positive probability densities for some negative strikes.

Load the market data.

First, load the market interest rates and swaption volatility data. The market swaption volatilities are quoted in terms of Shifted Black volatilities with a 0.8 percent shift.

Define RateSpec.

ValuationDate = '5-Apr-2016';
EndDates = datemnth(ValuationDate,[1 2 3 6 9 12*[1 2 3 4 5 6 7 8 9 10 12]])';
ZeroRates = [-0.34 -0.29 -0.25 -0.13 -0.07 -0.02 0.010 0.025 ...
    0.031 0.040 0.052 0.090 0.190 0.290 0.410 0.520]'/100;
Compounding = 1;
RateSpec = intenvset('ValuationDate',ValuationDate,'StartDates',ValuationDate, ...
RateSpec = struct with fields:
           FinObj: 'RateSpec'
      Compounding: 1
             Disc: [16x1 double]
            Rates: [16x1 double]
         EndTimes: [16x1 double]
       StartTimes: [16x1 double]
         EndDates: [16x1 double]
       StartDates: 736425
    ValuationDate: 736425
            Basis: 0
     EndMonthRule: 1

Define the swaption.

SwaptionSettle = '5-Apr-2016';
SwaptionExerciseDate = '5-Apr-2017';
SwapMaturity = '5-Apr-2022';
Reset = 1;
OptSpec = 'call';
TimeToExercise = yearfrac(SwaptionSettle,SwaptionExerciseDate);

Use swapbyzero to compute the forward swap rate.

LegRate = [NaN 0];  % To compute the forward swap rate, set the fixed rate to NaN.
[~, CurrentForwardValue] = swapbyzero(RateSpec,LegRate,SwaptionSettle,SwapMaturity,...
CurrentForwardValue = 6.6384e-04

Specify amount of shift in decimals for Shifted Black and Shifted SABR models.

Shift = 0.008;  % 0.8 percent shift

Load the market implied Shifted Black volatility data for swaptions.

MarketShiftedBlackVolatilities = [21.1; 15.3; 14.0; 14.6; 16.0; 17.7; 19.8; 23.9; 26.2]/100;
StrikeGrid = [-0.5; -0.25; -0.125; 0; 0.125; 0.25; 0.5; 1.0; 1.5]/100;
MarketStrikes = CurrentForwardValue + StrikeGrid;
ATMShiftedBlackVolatility = MarketShiftedBlackVolatilities(StrikeGrid==0);

Calibrate the Shifted SABR model parameters.

To better represent the market at-the-money volatility, the Alpha parameter value is implied by the market at-the-money volatility. This is similar to the "Method 2" in Calibrate the SABR Model. However, note the addition of Shift to CurrentForwardValue and the use of the 'Shift' parameter with blackvolbysabr. The Beta parameter is predetermined at 0.5.

Beta = 0.5;

This function solves the Shifted SABR at-the-money volatility equation as a polynomial of Alpha. Note the addition of Shift to CurrentForwardValue.

alpharoots = @(Rho,Nu) roots([...
    (1 - Beta)^2*TimeToExercise/24/(CurrentForwardValue + Shift)^(2 - 2*Beta) ...
    Rho*Beta*Nu*TimeToExercise/4/(CurrentForwardValue + Shift)^(1 - Beta) ...
    (1 + (2 - 3*Rho^2)*Nu^2*TimeToExercise/24) ...
    -ATMShiftedBlackVolatility*(CurrentForwardValue + Shift)^(1 - Beta)]);

This function converts at-the-money volatility into Alpha by picking the smallest positive real root.

atmVol2ShiftedSabrAlpha = @(Rho,Nu) min(real(arrayfun(@(x) ...
    x*(x>0) + realmax*(x<0 || abs(imag(x))>1e-6), alpharoots(Rho,Nu))));

Fit Rho and Nu (while converting at-the-money volatility into Alpha). Note the 'Shift' parameter of blackvolbysabr is set to the prespecified shift.

objFun = @(X) MarketShiftedBlackVolatilities - ...
    blackvolbysabr(atmVol2ShiftedSabrAlpha(X(1), X(2)), ...
    Beta, X(1), X(2), SwaptionSettle, SwaptionExerciseDate, CurrentForwardValue, ...
    MarketStrikes, 'Shift', Shift);

options = optimoptions('lsqnonlin','Display','none');
X = lsqnonlin(objFun, [0 0.5], [-1 0], [1 Inf], options);
Rho = X(1);
Nu = X(2);

Get the final Alpha from the calibrated parameters.

Alpha = atmVol2ShiftedSabrAlpha(Rho, Nu)
Alpha = 0.0133

Show the calibrated Shifted SABR parameters.

CalibratedPrameters = array2table([Shift Alpha Beta Rho Nu],...
    'VariableNames',{'Shift' 'Alpha' 'Beta' 'Rho' 'Nu'},...
    'RowNames',{'1Y into 5Y'})
CalibratedPrameters=1×5 table
                  Shift     Alpha      Beta      Rho        Nu   
                  _____    ________    ____    _______    _______

    1Y into 5Y    0.008    0.013345    0.5     0.46698    0.49816

Compute the swaption volatilities using the calibrated Shifted SABR model.

Use blackvolbysabr with the 'Shift' parameter.

Strikes = (-0.6:0.01:1.6)'/100; % Include negative strikes.
SABRShiftedBlackVolatilities = blackvolbysabr(Alpha, Beta, Rho, Nu, SwaptionSettle, ...
    SwaptionExerciseDate, CurrentForwardValue, Strikes, 'Shift', Shift);

plot(MarketStrikes, MarketShiftedBlackVolatilities, 'o', ...
    Strikes, SABRShiftedBlackVolatilities);
h = gca;
ylim([0.13 0.31])
legend('Market quotes','Shifted SABR', 'location', 'southeast');
title (['Shifted Black Volatility (',num2str(Shift*100),' percent shift)']);

Price the swaptions, including those with negative strikes.

Use swaptionbyblk with the 'Shift' parameter to compute swaption prices using the Shifted Black model.

SwaptionPrices = swaptionbyblk(RateSpec, OptSpec, Strikes, SwaptionSettle, SwaptionExerciseDate, ...
    SwapMaturity, SABRShiftedBlackVolatilities, 'Reset', Reset, 'Shift', Shift);
plot(Strikes, SwaptionPrices, 'r');
h = gca;
title ('Swaption Price');

Compute Shifted SABR Delta.

Use optsensbysabr with the 'Shift' parameter to compute Delta using the Shifted SABR model.

ShiftedSABRDelta = optsensbysabr(RateSpec, Alpha, Beta, Rho, Nu, SwaptionSettle, ...
SwaptionExerciseDate, CurrentForwardValue, Strikes, OptSpec, 'Shift', Shift);

ylim([-0.002 1.002]);
h = gca;
title ('Delta');

Compute the probability density.

The risk-neutral probability density of the terminal underlying asset prices can be approximated as the second derivative of swaption prices with respect to strike (Breeden and Litzenberger, 1978). As can be seen in the plot below, the computed probability density is positive for some negative rates above -0.8 percent (the lower bound determined by 'Shift').

NumGrids = length(Strikes);
ProbDensity = zeros(NumGrids-2,1);
dStrike = mean(diff(Strikes));

for k = 2:(NumGrids-1)
    ProbDensity(k-1) = (SwaptionPrices(k-1) - 2*SwaptionPrices(k) + SwaptionPrices(k+1))/dStrike^2;

ProbDensity = ProbDensity./sum(ProbDensity);
ProbStrikes = Strikes(2:end-1);

h = gca;
title ('Probability Density');


Hagan, P. S., Kumar, D., Lesniewski, A. S. and Woodward, D. E. "Managing Smile Risk." Wilmott Magazine. 2002.

Kienitz, J. Interest Rate Derivatives Explained. Vol. 1. Palgrave MacMillan, 2014.

Breeden, D. T. and Litzenberger, R. H. "Prices of State-Contingent Claims Implicit in Option Prices." Journal Business. Vol. 51. 1978.

See Also

| | | | | | | |

Related Examples

More About