capvolstrip

Strip caplet volatilities from flat cap volatilities

Description

example

[CapletVols,CapletPaymentDates,CapStrikes] = capvolstrip(ZeroCurve,CapSettle,CapMaturity,CapVolatility) strips caplet volatilities from the flat cap volatilities by using the bootstrapping method. The function interpolates the cap volatilities on each caplet payment date before stripping the caplet volatilities.

example

[CapletVols,CapletPaymentDates,CapStrikes] = capvolstrip(___,Name,Value) specifies options using one or more name-value pair arguments in addition to the input arguments in the previous syntax.

Examples

collapse all

Compute the zero curve for discounting and projecting forward rates.

ValuationDate = datenum('23-Jun-2015');
ZeroRates = [0.01 0.09 0.30 0.70 1.07 1.71]/100;
CurveDates = datemnth(ValuationDate, [0.25 0.5 1 2 3 5]*12);
ZeroCurve = IRDataCurve('Zero',ValuationDate,CurveDates,ZeroRates)
ZeroCurve = 
			 Type: Zero
		   Settle: 736138 (23-Jun-2015)
	  Compounding: 2
			Basis: 0 (actual/actual)
	 InterpMethod: linear
			Dates: [6x1 double]
			 Data: [6x1 double]

Define the ATM cap volatility data.

CapSettle = datenum('25-Jun-2015');
CapMaturity = datenum({'27-Jun-2016';'26-Jun-2017';'25-Jun-2018'; ...
    '25-Jun-2019';'25-Jun-2020'});
CapVolatility = [0.29;0.38;0.42;0.40;0.38];

Strip caplet volatilities from ATM caps.

[CapletVols, CapletPaymentDates, ATMCapStrikes] = capvolstrip(ZeroCurve, ...
    CapSettle, CapMaturity, CapVolatility);

PaymentDates = cellstr(datestr(CapletPaymentDates));
format;
table(PaymentDates, CapletVols, ATMCapStrikes)
ans=9×3 table
     PaymentDates      CapletVols    ATMCapStrikes
    _______________    __________    _____________

    {'27-Jun-2016'}        0.29        0.0052014  
    {'27-Dec-2016'}     0.34657        0.0071594  
    {'26-Jun-2017'}     0.41404        0.0091175  
    {'26-Dec-2017'}     0.42114         0.010914  
    {'25-Jun-2018'}     0.45297         0.012698  
    {'26-Dec-2018'}     0.37257         0.014222  
    {'25-Jun-2019'}     0.36184         0.015731  
    {'26-Dec-2019'}      0.3498         0.017262  
    {'25-Jun-2020'}     0.33668         0.018774  

Compute the zero curve for discounting and projecting forward rates.

ValuationDate = datenum('17-Feb-2015');
ZeroRates = [0.02 0.07 0.25 0.70 1.10 1.62]/100;
CurveDates = datemnth(ValuationDate, [0.25 0.5 1 2 3 5]*12);
ZeroCurve = IRDataCurve('Zero',ValuationDate,CurveDates,ZeroRates)
ZeroCurve = 
			 Type: Zero
		   Settle: 736012 (17-Feb-2015)
	  Compounding: 2
			Basis: 0 (actual/actual)
	 InterpMethod: linear
			Dates: [6x1 double]
			 Data: [6x1 double]

Define the cap volatility data.

CapSettle = datenum('19-Feb-2015');
CapMaturity = datenum({'19-Feb-2016';'21-Feb-2017';'20-Feb-2018'; ...
    '19-Feb-2019';'19-Feb-2020'});
CapVolatility = [0.44;0.45;0.44;0.41;0.39];
CapStrike = 0.013;

Strip caplet volatilities from caps with the same strike.

[CapletVols, CapletPaymentDates, CapStrikes] = capvolstrip(ZeroCurve, ...
    CapSettle, CapMaturity, CapVolatility, 'Strike', CapStrike);

PaymentDates = cellstr(datestr(CapletPaymentDates));
format;
table(PaymentDates, CapletVols, CapStrikes)
ans=9×3 table
     PaymentDates      CapletVols    CapStrikes
    _______________    __________    __________

    {'19-Feb-2016'}        0.44        0.013   
    {'19-Aug-2016'}     0.44495        0.013   
    {'21-Feb-2017'}     0.45256        0.013   
    {'21-Aug-2017'}     0.43835        0.013   
    {'20-Feb-2018'}     0.42887        0.013   
    {'20-Aug-2018'}     0.38157        0.013   
    {'19-Feb-2019'}     0.35237        0.013   
    {'19-Aug-2019'}      0.3525        0.013   
    {'19-Feb-2020'}     0.33136        0.013   

Compute the zero curve for discounting and projecting forward rates.

ValuationDate = datenum('06-Mar-2015');
ZeroRates = [0.01 0.08 0.27 0.73 1.16 1.70]/100;
CurveDates = datemnth(ValuationDate, [0.25 0.5 1 2 3 5]*12);
ZeroCurve = IRDataCurve('Zero',ValuationDate,CurveDates,ZeroRates)
ZeroCurve = 
			 Type: Zero
		   Settle: 736029 (06-Mar-2015)
	  Compounding: 2
			Basis: 0 (actual/actual)
	 InterpMethod: linear
			Dates: [6x1 double]
			 Data: [6x1 double]

Define the cap volatility data.

CapSettle = datenum('06-Mar-2015');
CapMaturity = datenum({'07-Mar-2016';'06-Mar-2017';'06-Mar-2018'; ...
    '06-Mar-2019';'06-Mar-2020'});
CapVolatility = [0.43;0.44;0.44;0.43;0.41];
CapStrike = 0.011;

Specify quarterly and semiannual dates.

CapletDates = [cfdates(CapSettle, '06-Mar-2016', 4) ...
     cfdates('06-Mar-2016', '06-Mar-2020', 2)]';
CapletDates(~isbusday(CapletDates)) =  ...
    busdate(CapletDates(~isbusday(CapletDates)), 'modifiedfollow');

Strip caplet volatilities using specified CapletDates.

[CapletVols, CapletPaymentDates, CapStrikes] = capvolstrip(ZeroCurve, ...
    CapSettle, CapMaturity, CapVolatility, 'Strike', CapStrike, ...
    'CapletDates', CapletDates);

PaymentDates = cellstr(datestr(CapletPaymentDates));
format;
table(PaymentDates, CapletVols, CapStrikes)
ans=11×3 table
     PaymentDates      CapletVols    CapStrikes
    _______________    __________    __________

    {'08-Sep-2015'}        0.43        0.011   
    {'07-Dec-2015'}     0.42999        0.011   
    {'07-Mar-2016'}        0.43        0.011   
    {'06-Sep-2016'}     0.43538        0.011   
    {'06-Mar-2017'}     0.44396        0.011   
    {'06-Sep-2017'}     0.43999        0.011   
    {'06-Mar-2018'}     0.44001        0.011   
    {'06-Sep-2018'}     0.41934        0.011   
    {'06-Mar-2019'}     0.40985        0.011   
    {'06-Sep-2019'}     0.36818        0.011   
    {'06-Mar-2020'}     0.34657        0.011   

Compute the zero curve for discounting and projecting forward rates.

ValuationDate = datenum('1-Mar-2016');
ZeroRates = [-0.38 -0.25 -0.21 -0.12 0.01 0.2]/100;
CurveDates = datemnth(ValuationDate, [0.25 0.5 1 2 3 5]*12);
ZeroCurve = IRDataCurve('Zero',ValuationDate,CurveDates,ZeroRates)
ZeroCurve = 
			 Type: Zero
		   Settle: 736390 (01-Mar-2016)
	  Compounding: 2
			Basis: 0 (actual/actual)
	 InterpMethod: linear
			Dates: [6x1 double]
			 Data: [6x1 double]

Define the cap volatility (Shifted Black) data.

CapSettle = datenum('1-Mar-2016');
CapMaturity = datenum({'1-Mar-2017';'1-Mar-2018';'1-Mar-2019'; ...
    '2-Mar-2020';'1-Mar-2021'});
CapVolatility = [0.35;0.40;0.37;0.34;0.32]; % Shifted Black volatilities
Shift = 0.01; % 1 percent shift.
CapStrike = -0.001; % -0.1 percent strike.

Strip caplet volatilities from caps using the Shifted Black Model.

[CapletVols, CapletPaymentDates, CapStrikes] = capvolstrip(ZeroCurve, ...
CapSettle,CapMaturity,CapVolatility,'Strike',CapStrike,'Shift',Shift);

PaymentDates = string(datestr(CapletPaymentDates));
format;
table(PaymentDates,CapletVols,CapStrikes)
ans=9×3 table
    PaymentDates     CapletVols    CapStrikes
    _____________    __________    __________

    "01-Mar-2017"        0.35        -0.001  
    "01-Sep-2017"     0.39129        -0.001  
    "01-Mar-2018"      0.4335        -0.001  
    "04-Sep-2018"     0.35284        -0.001  
    "01-Mar-2019"      0.3255        -0.001  
    "03-Sep-2019"      0.3011        -0.001  
    "02-Mar-2020"     0.27266        -0.001  
    "01-Sep-2020"     0.27698        -0.001  
    "01-Mar-2021"     0.25697        -0.001  

Compute the zero curve for discounting and projecting forward rates.

ValuationDate = datenum('1-Jun-2018');
ZeroRates = [-0.38 -0.25 -0.21 -0.12 0.01 0.2]/100;
CurveDates = datemnth(ValuationDate, [0.25 0.5 1 2 3 5]*12);
ZeroCurve = IRDataCurve('Zero',ValuationDate,CurveDates,ZeroRates)
ZeroCurve = 
			 Type: Zero
		   Settle: 737212 (01-Jun-2018)
	  Compounding: 2
			Basis: 0 (actual/actual)
	 InterpMethod: linear
			Dates: [6x1 double]
			 Data: [6x1 double]

Define the normal cap volatility data.

CapSettle = datenum('1-Jun-2018');
CapMaturity = datenum({'3-Jun-2019';'1-Jun-2020';'1-Jun-2021'; ...
    '1-Jun-2022';'1-Jun-2023'});
CapVolatility = [0.0057;0.0059;0.0057;0.0053;0.0051]; % Normal volatilities
CapStrike = -0.002; % -0.2 percent strike.

Strip caplet volatilities from caps using the Normal (Bachelier) model.

[CapletVols, CapletPaymentDates, CapStrikes] = capvolstrip(ZeroCurve, ...
    CapSettle,CapMaturity,CapVolatility,'Strike',CapStrike,'Model','normal');

PaymentDates = string(datestr(CapletPaymentDates));
format;
table(PaymentDates,CapletVols,CapStrikes)
ans=9×3 table
    PaymentDates     CapletVols    CapStrikes
    _____________    __________    __________

    "03-Jun-2019"       0.0057       -0.002  
    "02-Dec-2019"    0.0058686       -0.002  
    "01-Jun-2020"    0.0060472       -0.002  
    "01-Dec-2020"    0.0055705       -0.002  
    "01-Jun-2021"    0.0053912       -0.002  
    "01-Dec-2021"    0.0047404       -0.002  
    "01-Jun-2022"     0.004357       -0.002  
    "01-Dec-2022"    0.0046481       -0.002  
    "01-Jun-2023"    0.0044477       -0.002  

Input Arguments

collapse all

Zero rate curve, specified using a RateSpec or IRDataCurve object containing the zero rate curve for discounting according to its day count convention. If you do not specify the optional argument ProjectionCurve, the function uses ZeroCurve to compute the underlying forward rates as well. The observation date of the ZeroCurve specifies the valuation date. For more information on creating a RateSpec, see intenvset. For more information on creating an IRDataCurve object, see IRDataCurve.

Data Types: struct

Common cap settle date, specified as a scalar serial date number or date character vector. The CapSettle date cannot be earlier than the ZeroCurve valuation date.

Data Types: double | char

Cap maturity dates, specified using serial date numbers or cell array of date character vectors as a NCap-by-1 vector.

Data Types: double | char | cell

Flat cap volatilities, specified as an NCap-by-1 vector of positive decimals.

Data Types: double

Name-Value Pair Arguments

Specify optional comma-separated pairs of Name,Value arguments. Name is the argument name and Value is the corresponding value. Name must appear inside quotes. You can specify several name and value pair arguments in any order as Name1,Value1,...,NameN,ValueN.

Example: [CapletVols,CapletPaymentDates,CapStrikes] = capvolstrip(ZeroCurve,CapSettle,CapMaturity,CapVolatility,'Strike',.2)

Cap strike rate, specified as the comma-separated pair consisting of 'Strike' and a scalar decimal value or an NCapletVols-by-1 vector. Use Strike as a scalar to specify a single strike that applies equally to all caps. Or, specify an NCapletVols-by-1 vector of strikes for the caps.

Data Types: double

Caplet reset and payment dates, specified as the comma-separated pair consisting of 'CapletDates' and an NCapletDates-by-1 vector using serial date numbers or a cell array of date character vectors.

Use CapletDates to manually specify all caplet reset and payment dates. For example, some date intervals may be quarterly, while others may be semiannual. All dates must be later than CapSettle and cannot be later than the last CapMaturity date. Dates are adjusted according to the BusDayConvention and Holidays inputs.

If CapletDates is not specified, the default is to automatically generate periodic caplet dates after CapSettle based on the last CapMaturity date as the reference date, using the following optional inputs: Reset, EndMonthRule, BusDayConvention, and Holidays.

Data Types: double | char | cell

Frequency of periodic payments per year within a cap, specified as the comma-separated pair consisting of 'Reset' and a positive scalar integer with values 1,2, 3, 4, 6, or 12.

Note

If you specify CapletDates, the function ignores the input for Reset.

Data Types: double

End-of-month rule flag for generating caplet dates, specified as the comma-separated pair consisting of 'EndMonthRule' and a scalar nonnegative integer [0, 1].

  • 0 = Ignore rule, meaning that a payment date is always the same numerical day of the month.

  • 1 = Set rule on, meaning that a payment date is always the last actual day of the month.

Data Types: logical

Business day conventions, specified as the comma-separated pair consisting of 'BusDayConvention' and a character vector. Use this argument to specify how the function treats non-business days, which are days on which businesses are not open (such as weekends and statutory holidays).

  • 'actual' — Non-business days are effectively ignored. Cash flows that fall on non-business days are assumed to be distributed on the actual date.

  • 'follow' — Cash flows that fall on a non-business day are assumed to be distributed on the following business day.

  • 'modifiedfollow' — Cash flows that fall on a non-business day are assumed to be distributed on the following business day. However, if the following business day is in a different month, the previous business day is adopted instead.

  • 'previous' — Cash flows that fall on a non-business day are assumed to be distributed on the previous business day.

  • 'modifiedprevious' — Cash flows that fall on a non-business day are assumed to be distributed on the previous business day. However, if the previous business day is in a different month, the following business day is adopted instead.

Data Types: char

Holidays used in computing business days, specified as the comma-separated pair consisting of 'Holidays' and NHolidays-by-1 vector of MATLAB date numbers.

Data Types: double

Rate curve for computing underlying forward rates, specified as the comma-separated pair consisting of 'ProjectionCurve' and a RateSpec object or IRDatCurve object. For more information on creating a RateSpec, see intenvset. For more information on creating an IRDataCurve object, see IRDataCurve.

Data Types: struct

Method for interpolating the cap volatilities on each caplet maturity date before stripping the caplet volatilities, specified as the comma-separated pair consisting of 'MaturityInterpMethod' and a character vector with values: 'linear', 'nearest', 'next', 'previous', 'spline', or 'pchip'.

  • 'linear' — Linear interpolation. The interpolated value at a query point is based on linear interpolation of the values at neighboring grid points in each respective dimension. This is the default interpolation method.

  • 'nearest' — Nearest neighbor interpolation. The interpolated value at a query point is the value at the nearest sample grid point.

  • 'next' — Next neighbor interpolation. The interpolated value at a query point is the value at the next sample grid point.

  • 'previous' — Previous neighbor interpolation. The interpolated value at a query point is the value at the previous sample grid point.

  • 'spline' — Spline interpolation using not-a-knot end conditions. The interpolated value at a query point is based on a cubic interpolation of the values at neighboring grid points in each respective dimension.

  • 'pchip' — Shape-preserving piecewise cubic interpolation. The interpolated value at a query point is based on a shape-preserving piecewise cubic interpolation of the values at neighboring grid points.

For more information on interpolation methods, see interp1.

Note

The function uses constant extrapolation to calculate volatilities falling outside the range of user-supplied data.

Data Types: char

Upper bound of implied volatility search interval, specified as the comma-separated pair consisting of 'Limit' and a positive scalar decimal.

Data Types: double

Implied volatility search termination tolerance, specified as the comma-separated pair consisting of 'Tolerance' and a positive numeric scalar.

Data Types: double

Flag to omit the first caplet payment in the caps, specified as the comma-separated pair consisting of 'OmitFirstCaplet' and a scalar logical.

If the caps are spot-starting, the first caplet payment is omitted. If the caps are forward-starting, the first caplet payment is included. Regardless of the status of the caps, if you set this logical to false, then the function includes the first caplet payment.

In general, “spot lag” is the delay between the fixing date and the effective date for LIBOR-like indices. "Spot lag" determines whether a cap is spot-starting or forward-starting (Corb, 2012). Caps are considered to be spot-starting if they settle within “spot lag” business days after the valuation date. Those that settle later are considered to be forward-starting. The first caplet is omitted if caps are spot-starting, while it is included if they are forward-starting (Tuckman, 2012).

Data Types: logical

Shift in decimals for the shifted SABR model (to be used with the Shifted Black model), specified as the comma-separated pair consisting of 'Shift' and a positive scalar decimal value. Set this parameter to a positive shift in decimals to add a positive shift to the forward rate and strike, which effectively sets a negative lower bound for the forward rate and strike. For example, a Shift value of 0.01 is equal to a 1% shift.

Data Types: double

Model used for the implied volatility calculation, specified as the comma-separated pair consisting of 'Model' and a scalar character vector or string scalar with one of the following values:

  • 'lognormal' - Implied Black (no shift) or Shifted Black volatility.

  • 'normal' - Implied Normal (Bachelier) volatility. If you specify 'normal', Shift must be zero.

The capvolstrip function supports three volatility types.

'Model' Value'Shift' ValueVolatility Type
'lognormal'Shift = 0Black
'lognormal'Shift > 0Shifted Black
'normal'Shift = 0Normal (Bachelier)

Data Types: char | string

Output Arguments

collapse all

Stripped caplet volatilities, returned as an NCapletVols-by-1 vector of decimals.

Note

capvolstrip can output NaNs for some caplet volatilities. You might encounter this output if no volatility matches the caplet price implied by the user-supplied cap data.

Payment dates (in date numbers), returned as an NCapletVols-by-1 vector of date numbers corresponding to CapletVols.

Cap strikes, returned as an NCapletVols-by-1 vector of strikes in decimals for caps maturing on the corresponding CapletPaymentDates. CapStrikes are the same as the strikes of the corresponding caplets that have been stripped.

Limitations

When bootstrapping the caplet volatilities from ATM caps, the function reuses the caplet volatilities stripped from the shorter maturity caps in the longer maturity caps without adjusting for the difference in strike. capvolstrip follows the simplified approach described in Gatarek, 2006.

More About

collapse all

Cap

A cap is a contract that includes a guarantee that sets the maximum interest rate to be paid by the holder, based on an otherwise floating interest rate.

The payoff for a cap is:

max(CurrentRateCapRate,0)

For more information, see Cap.

At-The-Money

A cap or floor is at-the-money (ATM) if its strike is equal to the forward swap rate.

The forward swap rate is the fixed rate of a swap that makes the present value of the floating leg equal to that of the fixed leg. In comparison, a caplet or floorlet is ATM if its strike is equal to the forward rate (not the forward swap rate). In general (except over a single period), the forward rate is not equal to the forward swap rate. So, to be precise, the individual caplets in an ATM cap have slightly different moneyness and are only approximately ATM (Alexander, 2003).

In addition, the swap rate changes with swap maturity. Similarly, the ATM cap strike also changes with cap maturity, so the ATM cap strikes are computed for each cap maturity before stripping the caplet volatilities. As a result, when stripping the caplet volatilities from the ATM caps with increasing maturities, the ATM strikes of consecutive caps are different.

References

[1] Alexander, C. "Common Correlation and Calibrating the Lognormal Forward Rate Model." Wilmott Magazine, 2003.

[2] Corb, H. Interest Rate Swaps and Other Derivatives. Columbia Business School Publishing, 2012.

[3] Gatarek, D., P. Bachert, and R. Maksymiuk. The LIBOR Market Model in Practice. Chichester, UK: Wiley, 2006.

[4] Tuckman, B., and Serrat, A. Fixed Income Securities: Tools for Today’s Markets. Hoboken, NJ: Wiley, 2012.

Introduced in R2016a