Main Content


Price floors using Black option pricing model



[FloorPrice,Floorlets] = floorbyblk(RateSpec,Strike,Settle,Maturity,Volatility) price floors using the Black option pricing model. floorbyblk computes prices of vanilla floors and amortizing floors.


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


[FloorPrice,Floorlets] = floorbyblk(___,Name,Value) adds optional name-value pair arguments.


collapse all

This example shows how to price a floor using the Black option pricing model. Consider an investor who gets into a contract that floors the interest rate on a $100,000 loan at 6% 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 floor price.

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

% calculate the RateSpec
RateSpec = intenvset('ValuationDate', ValuationDate, ...
'StartDates', ValuationDate,'EndDates', EndDates, ...
'Rates', Rates,'Compounding', Compounding,'Basis', Basis);

Settle = datetime(2009,1,1); % floor starts in a year
Maturity = datetime(2009,4,1);
Volatility = 0.20;
FloorRate = 0.06;
FloorReset = 4;

FloorPrice = floorbyblk(RateSpec, FloorRate, Settle, Maturity, Volatility,...
'Reset',FloorReset,'ValuationDate',ValuationDate,'Principal', Principal,...
'Basis', Basis)
FloorPrice = 37.4864

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 Floor instruments.

Maturity = [datetime(2018,3,15) ; datetime(2020,3,15)];
Strike = [.04;.05];
BlackVol = .2;

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

[Price, Floorlets] = floorbyblk(OISCurve, Strike, Settle, Maturity, BlackVol)
Price = 2×1


Floorlets = 2×7

    3.6783    3.0706    1.8275    0.7280    0.6764       NaN       NaN
    4.6753    4.0587    2.7921    1.4763    1.3442    1.4130    1.1462

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

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


FloorletsLC = 2×7

    3.2385    2.5338    1.2895    0.5889    0.4017       NaN       NaN
    4.2355    3.5219    2.2286    1.2751    0.9169    1.1698    0.9706

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 floor instrument.

Settle = datetime(2011,11,15);
Maturity = datetime(2015,11,15);
Strike = 0.05;
Reset = 2;
Principal ={{datetime(2012,11,15) 100;datetime(2013,11,15) 70;datetime(2014,11,15) 40;datetime(2015,11,15) 10}};

Price the amortizing floor.

Volatility = 0.20;
Price = floorbyblk(RateSpec, Strike, Settle, Maturity, Volatility,...
'Reset',Reset,'Principal', Principal)
Price = 1.9315

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 floor with a negative strike using the Shifted Black model.

Settle = datetime(2016,6,1); % Floor starts in 3 months.
Maturity = datetime(2016,9,1);
ShiftedBlackVolatility = 0.31;
FloorRate = -0.001;  % -0.1 percent strike.
FloorReset = 4;
Principal = 100000;
Shift = 0.01; % 1 percent shift.

FloorPrice = floorbyblk(RateSpec,FloorRate,Settle,Maturity,ShiftedBlackVolatility,...
FloorPrice = 31.2099

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 floor is exercised, specified as a NINST-by-1 vector of decimal values.

Data Types: double

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

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

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

To support existing code, floorbyblk 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, floorbyblk internally converts it into a vector. floorbyblk assumes that the volatilities specified in the Volatility input are flat volatilities, which are applied equally to each of the floorlets.

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: [FloorPrice,Floorlets] = floorbyblk(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 of notional principal amounts, 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 floor.

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 floor, returned as a NINST-by-1 vector.

Floorlets, returned as a NINST-by-NCF array of floorlets, padded with NaNs.

More About

collapse all


A floor is a contract that includes a guarantee setting the minimum interest rate to be received by the holder, based on an otherwise floating interest rate.

The payoff for a floor is:


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 floorlets).

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