Main Content


Price caps using Black option pricing model



[CapPrice,Caplets] = capbyblk(RateSpec,Strike,Settle,Maturity,Volatility) price caps using the Black option pricing model. capbyblk computes prices of vanilla caps and amortizing caps.


Alternatively, you can use the Cap object to price cap instruments. For more information, see Get Started with Workflows Using Object-Based Framework for Pricing Financial Instruments.


[CapPrice,Caplets] = capbyblk(___,Name,Value) adds optional name-value pair arguments.


collapse all

Consider an investor who gets into a contract that caps the interest rate on a $100,000 loan at 8% quarterly compounded for 3 months, starting on January 1, 2009. Assuming that on January 1, 2008 the zero rate is 6.9394% continuously compounded and the volatility is 20%, use this data to compute the cap price. First, calculate the RateSpec:

ValuationDate = datetime(2008,1,1);
EndDates = datetime(2010,4,1);
Rates = 0.069394;
Compounding = -1; 
Basis = 1;

RateSpec = intenvset('ValuationDate', ValuationDate, ...
'StartDates', ValuationDate,'EndDates', EndDates, ...
'Rates', Rates,'Compounding', Compounding,'Basis', Basis)
RateSpec = struct with fields:
           FinObj: 'RateSpec'
      Compounding: -1
             Disc: 0.8554
            Rates: 0.0694
         EndTimes: 2.2500
       StartTimes: 0
         EndDates: 734229
       StartDates: 733408
    ValuationDate: 733408
            Basis: 1
     EndMonthRule: 1

Compute the price of the cap.

Settle = datetime(2009,1,1); % cap starts in a year
Maturity = datetime(2009,4,1);
Volatility = 0.20;
CapRate = 0.08;
CapReset = 4;

CapPrice = capbyblk(RateSpec,  CapRate, Settle, Maturity, Volatility,...
'Reset',CapReset,'ValuationDate',ValuationDate,'Principal', Principal,...
'Basis', Basis)
CapPrice = 51.6125

Define the OIS and Libor rates.

Settle = datetime(2013,3,15);
CurveDates = daysadd(Settle,360*[1/12 2/12 3/12 6/12 1 2 3 4 5 7 10],1);
OISRates = [.0018 .0019 .0021 .0023 .0031 .006  .011 .017 .021 .026 .03]';
LiborRates = [.0045 .0047 .005 .0055 .0075 .0109  .0162 .0216 .0262 .0309 .0348]';

Create an associated RateSpec for the OIS and Libor curves.

OISCurve = intenvset('Rates',OISRates,'StartDate',Settle,'EndDates',CurveDates,'Compounding',2,'Basis',1);
LiborCurve = intenvset('Rates',LiborRates,'StartDate',Settle,'EndDates',CurveDates,'Compounding',2,'Basis',1);

Define the Cap instruments.

Maturity = [ datetime(2018,3,15) ; datetime(2020,3,15)];
Strike = [0.04;0.05];
BlackVol = 0.2;

Price the cap instruments using the term structure OISCurve both for discounting the cash flows and generating future forward rates.

[Price, Caplets] = capbyblk(OISCurve, Strike, Settle, Maturity, BlackVol)
Price = 2×1


Caplets = 2×7

         0    0.0000    0.0033    0.2996    0.4443       NaN       NaN
         0    0.0000    0.0003    0.1134    0.2112    0.2292    0.4349

Price the cap instruments using the term structure LiborCurve to generate future forward rates. The term structure OISCurve is used for discounting the cash flows.

[PriceLC, CapletsLC] = capbyblk(OISCurve, Strike, Settle, Maturity, BlackVol,'ProjectionCurve',LiborCurve)
PriceLC = 2×1


CapletsLC = 2×7

         0    0.0000    0.0337    0.4250    0.8706       NaN       NaN
         0    0.0000    0.0052    0.1767    0.4849    0.3663    0.5998

Define the RateSpec.

Rates = [0.0358; 0.0421; 0.0473; 0.0527; 0.0543];
ValuationDate = datetime(2011,11,15);
StartDates = ValuationDate;
EndDates = [datetime(2012,11,15) ; datetime(2013,11,15) ; datetime(2014,11,15) ; datetime(2015,11,15) ; datetime(2016,11,15)];
Compounding = 1;
RateSpec = intenvset('ValuationDate', ValuationDate,'StartDates', StartDates,...
             'EndDates', EndDates,'Rates', Rates, 'Compounding', Compounding)
RateSpec = struct with fields:
           FinObj: 'RateSpec'
      Compounding: 1
             Disc: [5x1 double]
            Rates: [5x1 double]
         EndTimes: [5x1 double]
       StartTimes: [5x1 double]
         EndDates: [5x1 double]
       StartDates: 734822
    ValuationDate: 734822
            Basis: 0
     EndMonthRule: 1

Define the cap instruments.

Settle = datetime(2011,11,15);
Maturity = datetime(2015,11,15);
Strike = [0.03;0.035];
Reset = 1;
Principal ={{datetime(2012,11,15) 100;datetime(2013,11,15) 70;datetime(2014,11,15) 40;datetime(2015,11,15) 10}};

Price the amortizing caps.

Volatility = 0.10;  
Price = capbyblk (RateSpec, Strike, Settle, Maturity, Volatility,...
'Reset', Reset,'Principal', Principal)
Price = 2×1


Create the RateSpec.

ValuationDate = datetime(2016,3,1);
EndDates = [datetime(2017,3,1) ; datetime(2018,3,1) ; datetime(2019,3,1) ; datetime(2020,3,1) ; datetime(2021,3,1)];
Rates = [-0.21; -0.12; 0.01; 0.10; 0.20]/100;
Compounding = 1;
Basis = 1;

RateSpec = intenvset('ValuationDate',ValuationDate,'StartDates',ValuationDate, ...
RateSpec = struct with fields:
           FinObj: 'RateSpec'
      Compounding: 1
             Disc: [5x1 double]
            Rates: [5x1 double]
         EndTimes: [5x1 double]
       StartTimes: [5x1 double]
         EndDates: [5x1 double]
       StartDates: 736390
    ValuationDate: 736390
            Basis: 1
     EndMonthRule: 1

Price the cap with a negative strike using the Shifted Black model.

Settle = datetime(2016,6,1); % Cap starts in 3 months.
Maturity = datetime(2016,9,1);
ShiftedBlackVolatility = 0.31;
CapRate = -0.003;  % -0.3 percent strike.
CapReset = 4;
Principal = 100000;
Shift = 0.01; % 1 percent shift.

CapPrice = capbyblk(RateSpec,CapRate,Settle,Maturity,ShiftedBlackVolatility,...
CapPrice = 26.0733

Input Arguments

collapse all

Interest-rate term structure (annualized and continuously compounded), specified by the RateSpec obtained from intenvset. For information on the interest-rate specification, see intenvset.

Data Types: struct

Rate at which cap is exercised, specified as a NINST-by-1 vector of decimal values.

Data Types: double

Settlement date for the cap, specified as a NINST-by-1 vector using a datetime array, string array, or date character vectors.

To support existing code, capbyblk also accepts serial date numbers as inputs, but they are not recommended.

Maturity date for the cap, specified as a NINST-by-1 vector using a datetime array, string array, or date character vectors.

To support existing code, capbyblk also accepts serial date numbers as inputs, but they are not recommended.

Volatilities values, specified as a NINST-by-1 vector of numeric values.

The Volatility input is not intended for volatility surfaces or cubes. If you specify a matrix for the Volatility input, capbyblk internally converts it into a vector. capbyblk assumes that the volatilities specified in the Volatility input are flat volatilities, which are applied equally to each of the caplets.

Data Types: double

Name-Value Arguments

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Before R2021a, use commas to separate each name and value, and enclose Name in quotes.

Example: [CapPrice,Caplets] = capbyblk(RateSpec,Strike,Settle,Maturity,Volatility,'Reset',CapReset,'Principal',100000,'Basis',7)

Reset frequency payment per year, specified as a NINST-by-1 vector.

Data Types: double

Notional principal amount, specified as a NINST-by-1 vector or a NINST-by-1 cell array. When Principal is a NINST-by-1 cell array, each element is a NumDates-by-2 cell array, where the first column is dates and the second column is associated principal amount. The date indicates the last day that the principal value is valid.

Use Principal to pass a schedule to compute the price for an amortizing cap.

Data Types: double | cell

Day-count basis representing the basis used when annualizing the input forward rate, specified as a NINST-by-1 vector of integers.

  • 0 = actual/actual

  • 1 = 30/360 (SIA)

  • 2 = actual/360

  • 3 = actual/365

  • 4 = 30/360 (PSA)

  • 5 = 30/360 (ISDA)

  • 6 = 30/360 (European)

  • 7 = actual/365 (Japanese)

  • 8 = actual/actual (ICMA)

  • 9 = actual/360 (ICMA)

  • 10 = actual/365 (ICMA)

  • 11 = 30/360E (ICMA)

  • 12 = actual/365 (ISDA)

  • 13 = BUS/252

For more information, see Basis.

Data Types: double

The rate curve to be used in generating the future forward rates. This structure must be created using intenvset. Use this optional input if the forward curve is different from the discount curve.

Data Types: struct

Shift in decimals for the shifted Black model, specified using a scalar or NINST-by-1 vector of rate shifts in positive decimals. Set this parameter to a positive rate 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. For example, a Shift of 0.01 is equal to a 1% shift.

Data Types: double

Output Arguments

collapse all

Expected price of the cap, returned as a NINST-by-1 vector.

Caplets, returned as a NINST-by-NCF array of caplets, padded with NaNs.

More About

collapse all


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:


For more information, see Cap.

Shifted Black

The Shifted Black model is essentially the same as the Black’s model, except that it models the movements of (F + Shift) as the underlying asset, instead of F (which is the forward rate in the case of caplets).

This model allows negative rates, with a fixed negative lower bound defined by the amount of shift; that is, the zero lower bound of Black’s model has been shifted.


collapse all

Black Model

dF=σBlackFdwcall=eγT[FN(d1)KN(d2)]put=eγT[KN(d2)FN(d1)]d1=ln(FK)+(σB22)TσBT,   d2=d1σBTσB=σBlack

Where F is the forward value and K is the strike.

Shifted Black Model

dF=σShifted_Black(F+Shift)dwcall=eγT[(F+Shift)N(ds1)(K+Shift)N(ds2)]put=eγT[(K+Shift)N(ds2)(F+Shift)N(ds1)]ds1=ln(F+ShiftK+Shift)+(σsB22)TσsBT,   ds2=ds1σsBTσsB=σShifted_Black

Where F+Shift is the forward value and K+Shift is the strike for the shifted version.

Version History

Introduced in R2009a

expand all