Valuation of Interest Rate Derivatives › Caps and Floors
Quantitative FinanceAll chapters Valuation of Interest Rate Derivatives › Caps and FloorsOne section · Sections in this chapter3 / 13 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
A cap is a portfolio of interest rate call options, each called a caplet, that provides you with payments whenever a reference rate exceeds a predetermined strike rate. A floor is the corresponding portfolio of put options, called floorlets, that pays when the reference rate falls below the strike. Understanding how these instruments work requires us to first examine the building blocks, namely individual caplets and floorlets, before assembling them into complete cap and floor structures.
Caplet and Floorlet Mechanics
To understand how caplets work, consider that you are a borrower with floating-rate debt who worries about rising interest rates. Each quarter, your interest payment resets based on market rates. If rates spike unexpectedly, you face a sudden increase in interest expense. A caplet provides insurance against exactly this scenario: it pays you whenever the market rate exceeds a predetermined ceiling.
Consider a caplet that settles at time based on the interest rate observed at time . The timing distinction matters here: the rate is determined, or "fixed," at , but the actual payment occurs at , typically three or six months later. This structure mirrors how floating-rate loans work, where the rate for each period is set at the beginning but interest is paid at the end. If the reference rate (typically a LIBOR or SOFR rate) exceeds the strike rate , you receive a payment. The payment occurs at and equals:
where:
- : notional principal
- : day count fraction between and
- : reference interest rate (e.g., LIBOR or SOFR) observed at time
- : strike rate
Notice how the payoff is structured. The term ensures the payment is never negative: when rates are below the strike, the caplet simply expires worthless, and you owe nothing. When rates exceed the strike, you receive the difference. The notional principal and day count fraction convert this rate difference into an actual dollar amount, following the same conventions used in the underlying floating-rate loan.
The caplet payoff looks exactly like a call option on an interest rate. Just as a stock call option pays the excess of the stock price over the strike, a caplet pays the excess of the interest rate over the strike rate. This allows us to adapt option pricing theory to interest rates.
The floorlet payoff follows the same structure but uses a put option:
where:
- : notional principal
- : day count fraction
- : strike rate
- : reference interest rate
A floorlet protects against falling rates rather than rising rates. Consider that you have made fixed-rate loans funded by floating-rate deposits. If rates fall, you continue receiving fixed payments from borrowers but pay less on deposits, which is favorable. However, if rates rise, the opposite occurs. A floorlet provides the mirror-image protection to a cap, paying you when rates fall below the strike level.
A cap consists of multiple caplets covering consecutive periods. For example, a 3-year cap on quarterly rates would contain 12 caplets, one for each quarter. The first caplet typically starts at the first reset date (often 3 or 6 months from inception), which means the first fixing is already known at inception and the corresponding caplet has no optionality. This first caplet is often called the "stub" period, and market conventions vary on whether it is included in the quoted cap price.


Black's Model for Caplet Pricing
To value these payments, we use Black's model, an extension of the Black-Scholes framework.
Black's model treats the forward rate for each period as the underlying asset. Rather than modeling how interest rates evolve continuously over time, Black's approach takes the forward rate as given and asks: what is the fair price for an option on this forward rate?
To make this approach work, Black's model assumes the forward rate for each period follows a lognormal distribution under a specific probability measure, known as the forward measure associated with that period's payment date. The lognormal assumption means that forward rates are always positive and that percentage changes in rates are normally distributed. While this assumption has limitations, particularly when rates are near zero, it provides tractable closed-form solutions that form the foundation of market practice.
Under Black's model, the price of a caplet paying at time based on the rate set at is:
where:
- : notional principal
- : day count fraction
- : today's discount factor to time
- : forward rate from to
- : strike rate
- : cumulative standard normal distribution function
- : volatility of the forward rate
- : time to rate fixing
- : measures how many standard deviations the forward rate is above the strike, adjusted for time and volatility
- : a risk-adjusted measure accounting for volatility over the time to fixing
- : expected value of the forward rate, conditional on the option being in-the-money
- : strike rate weighted by the probability of exercise
Let's carefully unpack each component of this formula to build intuition for why it takes this form.
The term outside the brackets converts the rate-based payoff into a present value. The notional and day count fraction translate a rate difference into a cash amount, while the discount factor brings this future cash payment back to today's dollars. Notice that we discount to the payment date , not the fixing date , because that is when cash changes hands.
Inside the brackets, we find the familiar Black-Scholes structure adapted to forward rates. The term represents the expected payoff from the forward rate component, weighted by the probability that the option finishes in the money (after a specific risk adjustment). The term represents what we expect to "give up" by paying the strike, again weighted by exercise probability. The difference between these two terms gives the option's expected payoff under the forward measure.
The formula closely resembles the Black-Scholes formula from Chapter 6, with key differences. The underlying is a forward rate rather than a stock price, and the discount factor appears outside the main expression rather than being embedded through a risk-free rate term. The time to expiration is , the rate-setting date, not , the payment date. This distinction is critical: the option's uncertainty resolves when the rate is fixed, even though the payment comes later.
The parameters and measure how far the forward rate sits from the strike in standardized units. When equals , the caplet is at-the-money, and and depend only on volatility and time. When exceeds , the forward rate is above the strike, making the caplet in-the-money and increasing both and . The volatility parameter captures how uncertain we are about where the forward rate will settle by the fixing date. Higher volatility means more dispersion, which increases option value because you benefit from upside while being protected from downside.
For floorlets, the pricing formula uses the put option version:
where:
- : notional principal
- : day count fraction
- : discount factor to time
- : forward rate
- : strike rate
- : volatility of the forward rate
- : probabilities associated with the put option calculation
The floorlet formula mirrors the caplet formula with the roles reversed. Here represents the probability of exercise (rates falling below the strike), and the terms are arranged so that the payoff is positive when exceeds . The symmetry between the formulas reflects the relationship between call and put options.
Cap and Floor Valuation
With the caplet pricing formula in hand, valuing a complete cap becomes straightforward. Because each caplet pays independently based on the rate for its specific period, there is no path dependence or interaction between caplets. The total cap value is simply the sum of its parts.
The price of a complete cap equals the sum of its constituent caplet prices:
where:
- : total number of periods in the cap
- : price of the -th caplet
This additive structure reflects the fact that each caplet is a separate option that either pays off or expires worthless independently of the others. A three-year quarterly cap contains twelve such options, and you pay upfront for the entire portfolio of protection.
In practice, we often quote caps using a single implied volatility for all caplets, called a flat volatility. This doesn't mean the market believes all forward rates have the same volatility. Instead, it's a quoting convention that simplifies communication. When you quote "20% vol on a 3-year cap," you mean that plugging 20% into Black's formula for every caplet reproduces the quoted cap price. More sophisticated analysis uses spot volatilities, where each caplet has its own volatility parameter calibrated to market prices. The spot volatility curve typically shows higher volatilities for shorter-dated caplets and lower volatilities for longer-dated ones, which reflects the mean-reverting nature of interest rates.
import numpy as np
from scipy.stats import norm
def black_caplet_price(
forward_rate,
strike,
volatility,
time_to_expiry,
discount_factor,
day_count_fraction,
notional=1.0,
):
"""
Price a caplet using Black's model.
Parameters:
- forward_rate: Forward rate for the caplet period
- strike: Strike rate (as decimal, e.g., 0.05 for 5%)
- volatility: Implied volatility of the forward rate
- time_to_expiry: Time to rate fixing (in years)
- discount_factor: Discount factor to payment date
- day_count_fraction: Year fraction for the caplet period
- notional: Notional principal
"""
if time_to_expiry <= 0:
# Expired caplet, return intrinsic value
return (
notional
* day_count_fraction
* discount_factor
* max(forward_rate - strike, 0)
)
d1 = (
np.log(forward_rate / strike) + 0.5 * volatility**2 * time_to_expiry
) / (volatility * np.sqrt(time_to_expiry))
d2 = d1 - volatility * np.sqrt(time_to_expiry)
price = (
notional
* day_count_fraction
* discount_factor
* (forward_rate * norm.cdf(d1) - strike * norm.cdf(d2))
)
return price
def black_floorlet_price(
forward_rate,
strike,
volatility,
time_to_expiry,
discount_factor,
day_count_fraction,
notional=1.0,
):
"""
Price a floorlet using Black's model.
"""
if time_to_expiry <= 0:
return (
notional
* day_count_fraction
* discount_factor
* max(strike - forward_rate, 0)
)
d1 = (
np.log(forward_rate / strike) + 0.5 * volatility**2 * time_to_expiry
) / (volatility * np.sqrt(time_to_expiry))
d2 = d1 - volatility * np.sqrt(time_to_expiry)
price = (
notional
* day_count_fraction
* discount_factor
* (strike * norm.cdf(-d2) - forward_rate * norm.cdf(-d1))
)
return priceLet's price a 2-year quarterly cap with a 5% strike. We'll assume a flat yield curve at 4% for simplicity:
# Market data setup
strike = 0.05 # 5% strike rate
notional = 1_000_000 # $1 million notional
flat_vol = 0.20 # 20% implied volatility
flat_rate = 0.04 # 4% flat yield curve
# Generate quarterly periods for 2 years (8 periods)
# Payment dates at 0.25, 0.5, 0.75, ..., 2.0 years
payment_dates = np.arange(0.25, 2.25, 0.25)
day_count_fractions = np.full(len(payment_dates), 0.25)
# Forward rates (in a flat curve, forward = spot)
forward_rates = np.full(len(payment_dates), flat_rate)
# Discount factors
discount_factors = np.exp(-flat_rate * payment_dates)
# Time to expiry for each caplet (rate fixing is at start of each period)
times_to_expiry = payment_dates - 0.25
# Price each caplet
caplet_prices = []
for i in range(len(payment_dates)):
price = black_caplet_price(
forward_rate=forward_rates[i],
strike=strike,
volatility=flat_vol,
time_to_expiry=times_to_expiry[i],
discount_factor=discount_factors[i],
day_count_fraction=day_count_fractions[i],
notional=notional,
)
caplet_prices.append(price)
caplet_prices = np.array(caplet_prices)
cap_price = caplet_prices.sum()2-Year Quarterly Cap Valuation ================================================== Strike Rate: 5.00% Implied Volatility: 20.00% Notional: $1,000,000 Caplet Breakdown: -------------------------------------------------- Period Expiry Forward Price ($) -------------------------------------------------- 1 0.00 4.00% 0.00 2 0.25 4.00% 4.89 3 0.50 4.00% 37.50 4 0.75 4.00% 86.61 5 1.00 4.00% 141.01 6 1.25 4.00% 196.15 7 1.50 4.00% 250.17 8 1.75 4.00% 302.28 -------------------------------------------------- Total Cap Price: $1,018.61
The first caplet has zero value because its fixing occurs at inception (time 0), and with the forward rate at 4% below the 5% strike, it's out of the money with no time for rates to move. Subsequent caplets have progressively higher values due to longer time to expiration, giving more opportunity for rates to rise above the strike. This pattern illustrates a fundamental principle of option pricing: time has value because it provides opportunity for favorable movements in the underlying.

Cap-Floor Parity
A fundamental relationship connects caps, floors, and swaps. This relationship, known as cap-floor parity, provides a consistency check for pricing.
Recall from Chapter 12 that a payer swap involves paying fixed and receiving floating. If we decompose this:
- Buying a cap with strike gives us the positive part of
- Selling a floor with strike gives us the negative part of
The combination yields exactly for each period. To see why this works, consider what happens in each possible state of the world. When the floating rate exceeds the strike, the cap pays us the difference while the floor expires worthless. When the floating rate falls below the strike, the cap expires worthless but we owe the floor buyer the difference. In either case, our net position equals the floating rate minus the strike.
We can see this mathematically by decomposing the payoff across the two possible states for the reference rate :
where:
- : reference interest rate observed at time
- : strike rate
Regardless of rate movements, a long cap and short floor deliver the floating rate minus the strike. This is precisely the payoff of receiving floating and paying fixed in a swap.
The right-hand side represents the floating minus fixed cashflow of a payer swap. Summing these values gives us cap-floor parity:
where:
- : price of the cap with strike
- : price of the floor with strike
- : value of a payer swap with fixed rate
When equals the current swap rate, the payer swap has zero value (it's at-the-money), so the cap and floor have equal prices. This at-the-money volatility is often the benchmark for quoting interest rate option prices. The relationship also provides a powerful arbitrage constraint: if cap and floor prices diverge from parity, you can profit by buying the underpriced combination and selling the overpriced one.
# Verify cap-floor parity
floorlet_prices = []
for i in range(len(payment_dates)):
price = black_floorlet_price(
forward_rate=forward_rates[i],
strike=strike,
volatility=flat_vol,
time_to_expiry=times_to_expiry[i],
discount_factor=discount_factors[i],
day_count_fraction=day_count_fractions[i],
notional=notional,
)
floorlet_prices.append(price)
floor_price = np.sum(floorlet_prices)
# Calculate swap value (receive float, pay fixed at strike)
# Swap value = sum of (forward - strike) * dcf * df
swap_value = sum(
notional
* day_count_fractions[i]
* discount_factors[i]
* (forward_rates[i] - strike)
for i in range(len(payment_dates))
)Cap-Floor Parity Verification ================================================== Cap Price: $1,018.61 Floor Price: $20,143.58 Cap - Floor: $-19,124.97 Swap Value: $-19,124.97 Parity Error: $0.0000

