Short-Rate Interest Rate Models › Pricing Interest Rate Derivatives

Michael BrenndoerferDecember 6, 20255 min read
Quantitative FinanceAll chapters
Part 7 of 15Interest Rate Models and Derivatives
Chapter 38Short-Rate Interest Rate Models › Pricing Interest Rate Derivatives
Reading section 8 of 13 · Pricing Interest Rate Derivatives · 5 minSection 8 of 13 · 5 min

Book contents

Section 8 of 13 · 5 min read

Short-Rate Interest Rate Models › Pricing Interest Rate DerivativesOne section · Sections in this chapter8 / 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

Short-rate models enable pricing of various interest rate derivatives. Let's implement a simple example: pricing a zero-coupon bond option.

European Bond Options

Under the Vasicek model, European options on zero-coupon bonds have closed-form solutions. These formulas resemble the famous Black-Scholes formula for stock options, but with modifications appropriate for the interest rate setting. A call option on a T2T_2-maturity bond, expiring at time T1<T2T_1 < T_2, gives the holder the right to purchase the bond at the strike price KK. The value of this option is:

C=P(0,T2)N(d1)−K⋅P(0,T1)N(d2)C = P(0, T_2)N(d_1) - K \cdot P(0, T_1)N(d_2)

Each term in this pricing formula has a clear interpretation:

  • CC value of the European call option
  • P(0,Ti)P(0, T_i): price of zero-coupon bond maturing at TiT_i
  • KK: strike price
  • N(⋅)N(\cdot): cumulative standard normal distribution function
  • d1,d2d_1, d_2: standardized limits for the integration
  • σP\sigma_P: volatility of the forward bond price

The first term P(0,T2)N(d1)P(0, T_2)N(d_1) represents the expected present value of receiving the bond, weighted by the probability (under an appropriate measure) that the option will be exercised. The second term K⋅P(0,T1)N(d2)K \cdot P(0, T_1)N(d_2) represents the expected present value of paying the strike price, again weighted by the exercise probability under the risk-neutral measure.

The parameters d1d_1 and d2d_2 measure how far the current forward price is from the strike, scaled by volatility:

d1=ln⁡(P(0,T2)/(K⋅P(0,T1)))σP+σP2d2=d1−σP\begin{aligned} d_1 &= \frac{\ln(P(0, T_2) / (K \cdot P(0, T_1)))}{\sigma_P} + \frac{\sigma_P}{2} \\ d_2 &= d_1 - \sigma_P \end{aligned}

The numerator of the first term in d1d_1 compares the forward price of the underlying bond (which equals P(0,T2)/P(0,T1)P(0, T_2)/P(0, T_1) in a no-arbitrage setting) to the strike price KK:

  • d1,d2d_1, d_2 standardized integration limits
  • P(0,Ti)P(0, T_i): zero-coupon bond prices
  • KK: strike price
  • σP\sigma_P: volatility of the forward bond price

The volatility term σP\sigma_P measures how much uncertainty there is about the bond price at the option's expiration. In the Vasicek model, this volatility can be computed analytically:

σP=σB(T1,T2)1−e−2κT12κ\sigma_P = \sigma B(T_1, T_2) \sqrt{\frac{1 - e^{-2\kappa T_1}}{2\kappa}}

This expression combines several factors that contribute to bond price uncertainty:

  • σ\sigma volatility of the short rate
  • B(T1,T2)=(1−e−κ(T2−T1))/κB(T_1, T_2) = (1 - e^{-\kappa(T_2 - T_1)})/\kappa: Vasicek bond coefficient
  • T1T_1: option expiration time
  • T2T_2: bond maturity time
  • κ\kappa: mean reversion speed

The factor σ\sigma is the underlying volatility of the short rate. The factor B(T1,T2)B(T_1, T_2) translates short-rate volatility into bond price volatility for a bond maturing at T2T_2, as of the option expiration at T1T_1. The square-root term accounts for the accumulation of uncertainty from now until the option expiration, adjusted for mean reversion. Stronger mean reversion (larger κ\kappa) reduces uncertainty because the rate is pulled back toward θ\theta more quickly.

In[22]:
Code
from scipy.stats import norm


def vasicek_bond_option(r0, kappa, theta, sigma, T1, T2, K, option_type="call"):
    """
    Price a European option on a zero-coupon bond under Vasicek model.

    Parameters:
    -----------
    r0 : float
        Current short rate
    kappa, theta, sigma : float
        Vasicek parameters
    T1 : float
        Option expiration time
    T2 : float
        Bond maturity time (T2 > T1)
    K : float
        Strike price
    option_type : str
        'call' or 'put'

    Returns:
    --------
    float : Option price
    """
    # Bond prices
    P_T1 = vasicek_bond_price(r0, 0, T1, kappa, theta, sigma)
    P_T2 = vasicek_bond_price(r0, 0, T2, kappa, theta, sigma)

    # B function for forward bond
    B_T1_T2 = (1 - np.exp(-kappa * (T2 - T1))) / kappa

    # Bond price volatility
    sigma_P = (
        sigma * B_T1_T2 * np.sqrt((1 - np.exp(-2 * kappa * T1)) / (2 * kappa))
    )

    # d1 and d2
    d1 = (np.log(P_T2 / (K * P_T1)) / sigma_P) + 0.5 * sigma_P
    d2 = d1 - sigma_P

    if option_type == "call":
        price = P_T2 * norm.cdf(d1) - K * P_T1 * norm.cdf(d2)
    else:
        price = K * P_T1 * norm.cdf(-d2) - P_T2 * norm.cdf(-d1)

    return price
In[23]:
Code
# Example: Price a 1-year call option on a 5-year zero-coupon bond
T1 = 1.0  # Option expiration
T2 = 5.0  # Bond maturity

# The underlying bond price today
bond_price = vasicek_bond_price(r0, 0, T2, kappa, theta, sigma)

# Strike at-the-money forward
K_atm = vasicek_bond_price(r0, 0, T2, kappa, theta, sigma) / vasicek_bond_price(
    r0, 0, T1, kappa, theta, sigma
)

# Price options at different strikes
strikes = np.linspace(0.75, 0.95, 11)
call_prices = [
    vasicek_bond_option(r0, kappa, theta, sigma, T1, T2, K, "call")
    for K in strikes
]
put_prices = [
    vasicek_bond_option(r0, kappa, theta, sigma, T1, T2, K, "put")
    for K in strikes
]

# Calculate ATM prices for summary
atm_call = vasicek_bond_option(r0, kappa, theta, sigma, T1, T2, K_atm, "call")
atm_put = vasicek_bond_option(r0, kappa, theta, sigma, T1, T2, K_atm, "put")
current_bond_1y = vasicek_bond_price(r0, 0, T1, kappa, theta, sigma)
Out[24]:
Visualization
Line plot showing call and put option prices versus strike price for bond options.
European call and put option prices on a 5-year zero-coupon bond with 1-year expiration under the Vasicek model. Call values decrease and put values increase as the strike price rises, intersecting at the at-the-money forward strike marked by the dashed line.
Out[25]:
Console
Bond Option Pricing Summary:
----------------------------------------
Current 5-year bond price: 0.824426
Current 1-year bond price: 0.973999
ATM forward strike: 0.846434

ATM Call price: 0.009044
ATM Put price:  0.009044

The option prices follow familiar patterns: calls decrease as strike increases, puts increase as strike increases. The intersection near the ATM forward strike reflects put-call parity for bond options.