Chapter 8 — Interest Rate Derivatives

"Interest rate derivatives are the largest market in the world."


After this chapter you will be able to:

  • Price Forward Rate Agreements and value plain-vanilla interest rate swaps from a discount curve, and compute the par swap rate analytically
  • Derive cap and floor prices using Black's formula in the forward measure, and construct a collar as a cost-neutral combination of the two
  • Price swaptions using Black's formula with the annuity as numeraire
  • Implement the Vasicek, CIR, and Hull-White short-rate models and understand the tradeoffs between tractability and realism
  • Explain the post-2008 multi-curve framework: why LIBOR projection curves and OIS discount curves must be kept separate

The global interest rate derivatives market has a notional outstanding of over \$500 trillion — roughly six times the world's annual economic output. Behind this seemingly abstract number are real economic activities: the 30-year fixed mortgage whose rate was locked by a bank using an interest rate swap; the pension fund that bought a cap to protect against a ceiling violation in floating-rate debt; the corporation that used a swaption to preserve flexibility in its debt refinancing schedule. Interest rate derivatives allow risk to be transferred between parties who have opposite needs, and they do so continuously and at enormous scale.

Unlike equity derivatives, where the underlying is a traded asset with a single price, interest rate derivatives face an immediate complication: there is no single "the interest rate." There are rates for overnight, 1-month, 3-month, 6-month, 1-year, 5-year, 10-year, and 30-year maturities — and they all move together but not perfectly. A position that is hedged against a parallel shift in rates may still lose money if the yield curve steepens or flattens. This multi-dimensional risk is the defining challenge of fixed income derivatives.

This chapter builds from the simplest interest rate derivative (the Forward Rate Agreement, a single-payment contract on one future rate) up to full interest rate swaps, caps and floors, and swaptions. In the second half, we develop short-rate models — Vasicek, CIR, and Hull-White — which drive the entire yield curve from a single stochastic factor, enabling closed-form pricing of the full zoo of vanilla derivatives.


8.1 Forward Rate Agreements

A Forward Rate Agreement (FRA) is a contract to exchange a fixed interest rate for a floating rate over a future period $[T_1, T_2]$.

At settlement date $T_1$, the payoff is:

$$\text{Payoff} = \frac{(R_{\text{floating}} - R_{\text{fixed}}) \cdot \tau \cdot N}{1 + R_{\text{floating}} \cdot \tau}$$

where $\tau = T_2 - T_1$ (year fraction), $N$ = notional, and the denominator discounts to $T_1$.

module Fra = struct
  type t = {
    notional   : float;
    fixed_rate : float;    (* the rate being paid/received *)
    start      : float;    (* T_1 in years *)
    tenor      : float;    (* length of the accrual period *)
    is_payer   : bool;     (* payer of fixed = borrower *)
    day_count  : day_count_convention;
  }

  (** Value of FRA at origination given discount curve *)
  let value { notional; fixed_rate; start; tenor; is_payer; _ } ~discount =
    let t2 = start +. tenor in
    let df1 = discount start in
    let df2 = discount t2 in
    (* Implied forward rate from curve *)
    let fwd_rate = (df1 /. df2 -. 1.0) /. tenor in
    let rate_diff = fwd_rate -. fixed_rate in
    let sign = if is_payer then -. 1.0 else 1.0 in
    sign *. notional *. rate_diff *. tenor *. df2

  (** DV01 of FRA: change in value for 1bp yield increase *)
  let dv01 fra ~discount =
    let dy = 0.0001 in
    let bump_discount t = exp (log (discount t) -. dy *. t) in
    value fra ~discount -. value fra ~discount:bump_discount

end

8.2 Interest Rate Swaps

An interest rate swap (IRS) is the most liquid derivative in the world. It exchanges a stream of fixed-rate payments for floating-rate payments (or vice versa) on a notional principal.

8.2.1 Plain Vanilla IRS

Fixed leg: pays $c \cdot \tau_i \cdot N$ at each coupon date $T_i$
Floating leg: pays $L_i \cdot \tau_i \cdot N$ where $L_i$ is the LIBOR/SOFR rate fixed at the start of period $i$

At inception, a fair swap has value = 0, which determines the par swap rate $S$:

$$S = \frac{1 - DF(T_n)}{\sum_{i=1}^n \tau_i \cdot DF(T_i)}$$

The floating leg value equals $N \cdot (1 - DF(T_n))$ when discounting at OIS rates (the floating leg prices at par minus the final discount factor).

module Swap = struct
  type t = {
    notional    : float;
    fixed_rate  : float;
    maturity    : float;
    frequency   : int;
    is_payer    : bool;     (* payer of fixed *)
    day_count   : day_count_convention;
  }

  (** Par swap rate: the fixed rate that makes the swap fair *)
  let par_rate { maturity; frequency; _ } ~discount =
    let m = float_of_int frequency in
    let n = int_of_float (Float.round (maturity *. m)) in
    let sum_dfs = ref 0.0 in
    for i = 1 to n do
      let ti = float_of_int i /. m in
      sum_dfs := !sum_dfs +. discount ti /. m
    done;
    let df_n = discount maturity in
    (1.0 -. df_n) /. !sum_dfs

  (** Present value of fixed leg *)
  let fixed_leg_pv { notional; fixed_rate; maturity; frequency; _ } ~discount =
    let m = float_of_int frequency in
    let n = int_of_float (Float.round (maturity *. m)) in
    let coupon = notional *. fixed_rate /. m in
    let sum = ref 0.0 in
    for i = 1 to n do
      let ti = float_of_int i /. m in
      sum := !sum +. coupon *. discount ti
    done;
    !sum

  (** Present value of floating leg (SOFR OIS: floating = 1 - DF(T_n)) *)
  let floating_leg_pv { notional; maturity; _ } ~discount =
    notional *. (1.0 -. discount maturity)

  (** Total swap NPV *)
  let npv swap ~discount =
    let fixed_pv   = fixed_leg_pv swap ~discount in
    let float_pv   = floating_leg_pv swap ~discount in
    let sign = if swap.is_payer then 1.0 else -. 1.0 in
    sign *. (float_pv -. fixed_pv)

  (** DV01: value change for 1bp parallel shift *)
  let dv01 swap ~discount =
    let dy = 0.0001 in
    let bump_curve t = discount t *. exp (-. dy *. t) in
    npv swap ~discount:(bump_curve) -. npv swap ~discount

  (** Annuity: PV of 1bp per period — used in swaption pricing *)
  let annuity { notional; maturity; frequency; _ } ~discount =
    let m = float_of_int frequency in
    let n = int_of_float (Float.round (maturity *. m)) in
    let sum = ref 0.0 in
    for i = 1 to n do
      let ti = float_of_int i /. m in
      sum := !sum +. discount ti /. m
    done;
    notional *. !sum

  (** Forward swap rate over [T_start, T_end] *)
  let forward_rate { maturity = _; frequency; _ } ~t_start ~t_end ~discount =
    let df_start = discount t_start in
    let df_end   = discount t_end in
    let m = float_of_int frequency in
    let n = int_of_float (Float.round ((t_end -. t_start) *. m)) in
    let sum_dfs = ref 0.0 in
    for i = 1 to n do
      let ti = t_start +. float_of_int i /. m in
      sum_dfs := !sum_dfs +. discount ti /. m
    done;
    (df_start -. df_end) /. !sum_dfs

end

8.2.2 Swap Risk Management

Bucketed DV01: Rather than a single DV01, risk is attributed to each tenor bucket on the curve.

(** Compute DV01 for each curve bucket — parallel shift at each maturity only *)
let bucketed_dv01 swap ~discount ~curve_tenors =
  Array.map (fun tenor ->
    let bump = 0.0001 in
    let bumped_discount t =
      if Float.abs (t -. tenor) < 0.01 then
        discount t *. exp (-. bump *. t)
      else
        discount t
    in
    let base_npv   = Swap.npv swap ~discount in
    let bumped_npv = Swap.npv swap ~discount:bumped_discount in
    (tenor, bumped_npv -. base_npv)
  ) curve_tenors

8.3 Overnight Index Swaps (OIS)

An OIS swaps a fixed rate for the daily compounded overnight rate (Fed Funds in USD, ESTR in EUR, SONIA in GBP). The floating leg compounds daily:

$$1 + L_{\text{OIS}} \cdot \tau = \prod_{i=1}^{n} (1 + r_i \cdot \delta_i)$$

module Ois = struct
  type t = {
    notional    : float;
    fixed_rate  : float;
    maturity    : float;   (* typically 1 week to 2 years *)
    is_payer    : bool;
  }

  (** OIS value — single period simplification *)
  let npv { notional; fixed_rate; maturity; is_payer } ~ois_disc ~proj_disc =
    (* Floating leg: notional * (1/DF_OIS(T) - 1) discounted at OIS *)
    let df_ois = ois_disc maturity in
    let df_proj = proj_disc maturity in
    let float_pv = notional *. (df_proj /. df_ois *. 1.0 /. df_ois -. 1.0)
                   *. df_ois in
    let fixed_pv = notional *. fixed_rate *. maturity *. df_ois in
    let sign = if is_payer then 1.0 else -. 1.0 in
    sign *. (float_pv -. fixed_pv)

end

8.4 Caps, Floors, and Collars

An interest rate cap is a portfolio of calls on the floating rate (caplets). Each caplet pays:

$$\max(L_{i} - K, 0) \cdot \tau \cdot N$$

Under the Black model (in the forward measure), each caplet has an analytic price:

$$\text{Caplet}(K, T_i) = N \cdot \tau_i \cdot DF(T_i) \cdot [f_i \cdot \Phi(d_1) - K \cdot \Phi(d_2)]$$

where $f_i$ is the forward LIBOR rate and:

$$d_1 = \frac{\ln(f_i/K) + \frac{1}{2}\sigma_i^2 T_i}{\sigma_i \sqrt{T_i}}, \quad d_2 = d_1 - \sigma_i \sqrt{T_i}$$

module Caplet = struct
  (** Black formula for a single caplet (call on LIBOR) *)
  let price ~notional ~tau ~strike ~forward_rate ~vol ~t_fix ~discount =
    if vol < 1e-10 then
      notional *. tau *. discount (t_fix +. tau) *.
        Float.max 0.0 (forward_rate -. strike)
    else begin
      let d1 = (log (forward_rate /. strike) +. 0.5 *. vol *. vol *. t_fix)
               /. (vol *. sqrt t_fix) in
      let d2 = d1 -. vol *. sqrt t_fix in
      let df = discount (t_fix +. tau) in
      notional *. tau *. df *.
        (forward_rate *. norm_cdf d1 -. strike *. norm_cdf d2)
    end

  (** Floorlet: put on LIBOR *)
  let floor_price ~notional ~tau ~strike ~forward_rate ~vol ~t_fix ~discount =
    if vol < 1e-10 then
      notional *. tau *. discount (t_fix +. tau) *.
        Float.max 0.0 (strike -. forward_rate)
    else begin
      let d1 = (log (forward_rate /. strike) +. 0.5 *. vol *. vol *. t_fix)
               /. (vol *. sqrt t_fix) in
      let d2 = d1 -. vol *. sqrt t_fix in
      let df = discount (t_fix +. tau) in
      notional *. tau *. df *.
        (strike *. norm_cdf (-. d2) -. forward_rate *. norm_cdf (-. d1))
    end
end

(** Cap price = sum of caplet prices *)
let cap_price ~notional ~strike ~maturity ~frequency ~flat_vol ~discount =
  let m = float_of_int frequency in
  let n = int_of_float (Float.round (maturity *. m)) in
  let sum = ref 0.0 in
  for i = 1 to n do
    let t_fix = float_of_int (i - 1) /. m in
    let tau   = 1.0 /. m in
    let df1   = discount t_fix in
    let df2   = discount (t_fix +. tau) in
    let fwd   = (df1 /. df2 -. 1.0) /. tau in
    let price = Caplet.price ~notional ~tau ~strike ~forward_rate:fwd
                  ~vol:flat_vol ~t_fix ~discount in
    sum := !sum +. price
  done;
  !sum

(** Floor price *)
let floor_price ~notional ~strike ~maturity ~frequency ~flat_vol ~discount =
  let m = float_of_int frequency in
  let n = int_of_float (Float.round (maturity *. m)) in
  let sum = ref 0.0 in
  for i = 1 to n do
    let t_fix = float_of_int (i - 1) /. m in
    let tau   = 1.0 /. m in
    let df1   = discount t_fix in
    let df2   = discount (t_fix +. tau) in
    let fwd   = (df1 /. df2 -. 1.0) /. tau in
    let price = Caplet.floor_price ~notional ~tau ~strike ~forward_rate:fwd
                  ~vol:flat_vol ~t_fix ~discount in
    sum := !sum +. price
  done;
  !sum

(** Collar = Long cap + Short floor (locks in a range) *)
let collar_price ~notional ~cap_strike ~floor_strike ~maturity ~frequency ~vol ~discount =
  let c = cap_price   ~notional ~strike:cap_strike   ~maturity ~frequency ~flat_vol:vol ~discount in
  let f = floor_price ~notional ~strike:floor_strike ~maturity ~frequency ~flat_vol:vol ~discount in
  c -. f   (* net cost of collar *)

8.5 Swaptions

A swaption is an option to enter an interest rate swap. A payer swaption gives the right to pay fixed (beneficial when rates rise); a receiver swaption gives the right to receive fixed.

Under the swap measure, the forward swap rate $S$ is a martingale with respect to the annuity numeraire. The Black swaption formula is:

$$V_{\text{payer}} = A(0) \cdot [S \cdot \Phi(d_1) - K \cdot \Phi(d_2)]$$

$$d_1 = \frac{\ln(S/K) + \frac{1}{2}\sigma^2 T}{\sigma\sqrt{T}}, \quad d_2 = d_1 - \sigma\sqrt{T}$$

where $A(0)$ is the annuity (PV of 1 per period).

module Swaption = struct
  type t = {
    swap        : Swap.t;
    expiry      : float;    (* option expiry in years *)
    is_payer    : bool;     (* payer swaption = call on swap rate *)
    vol         : float;    (* lognormal vol of swap rate *)
  }

  (** Black swaption formula *)
  let price { swap; expiry; is_payer; vol } ~discount =
    let ann  = Swap.annuity swap ~discount in
    let fwd_s = Swap.par_rate swap ~discount in
    let k    = swap.Swap.fixed_rate in
    if vol < 1e-10 then begin
      let intrinsic = if is_payer then Float.max 0.0 (fwd_s -. k)
                      else Float.max 0.0 (k -. fwd_s) in
      ann *. intrinsic
    end else begin
      let d1 = (log (fwd_s /. k) +. 0.5 *. vol *. vol *. expiry)
               /. (vol *. sqrt expiry) in
      let d2 = d1 -. vol *. sqrt expiry in
      if is_payer then
        ann *. (fwd_s *. norm_cdf d1 -. k *. norm_cdf d2)
      else
        ann *. (k *. norm_cdf (-. d2) -. fwd_s *. norm_cdf (-. d1))
    end

  (** Implied vol from swaption premium *)
  let implied_vol swaption ~market_price ~discount =
    let f vol = price { swaption with vol } ~discount -. market_price in
    brent ~f 0.0001 5.0
end

8.6 Short-Rate Models

Short-rate models describe the stochastic evolution of the instantaneous interest rate $r_t$. They are used to price interest rate derivatives with path-dependent features.

8.6.1 Vasicek Model

The Vasicek model (1977) describes mean-reverting interest rates:

$$dr_t = \kappa(\theta - r_t) dt + \sigma dW_t$$

where:

  • $\kappa$ = mean reversion speed
  • $\theta$ = long-run mean
  • $\sigma$ = volatility
  • $W_t$ = standard Brownian motion

The economic justification for mean reversion is straightforward: very high interest rates slow the economy and reduce inflation, eventually pulling rates down; very low rates stimulate borrowing and investment, pushing rates up. The speed of mean reversion $\kappa$ determines how quickly rates return to $\theta$ after a shock. The half-life of a rate deviation is $\ln(2)/\kappa$: with $\kappa = 0.1$, the half-life is about 7 years (slow reversion, appropriate for long-term macro cycles); with $\kappa = 0.5$, it is about 1.4 years. Typical calibrated values are $\kappa \approx 0.1$–$0.5$, $\theta \approx 4%$–$7%$, $\sigma \approx 1%$–$3%$.

The Vasicek model has two well-known limitations. First, it allows negative interest rates: since $r_t$ is Gaussian, it can become negative with positive probability. Before 2015 this was considered unrealistic; post-2015, many central banks set negative rates, making this less of a deficiency. Second, the assumption of constant $\kappa$, $\theta$, $\sigma$ means the model cannot fit an arbitrary initial yield curve — Hull-White (§8.6.2) fixes this by making $\theta(t)$ time-dependent.

The zero-coupon bond price has the affine closed form:

$$P(t, T) = A(t, T) \cdot e^{-B(t, T) \cdot r_t}$$

module Vasicek = struct
  type params = {
    kappa : float;   (* mean reversion speed *)
    theta : float;   (* long-run mean *)
    sigma : float;   (* volatility *)
    r0    : float;   (* initial rate *)
  }

  (** Zero-coupon bond price P(0, T) *)
  let zcb_price { kappa; theta; sigma; r0 } ~maturity =
    let tau = maturity in
    let b = (1.0 -. exp (-. kappa *. tau)) /. kappa in
    let a = exp (
      (b -. tau) *. (kappa *. kappa *. theta -. 0.5 *. sigma *. sigma)
      /. (kappa *. kappa)
      -. sigma *. sigma *. b *. b /. (4.0 *. kappa)
    ) in
    a *. exp (-. b *. r0)

  (** Yield (continuously compounded) for maturity T *)
  let yield params ~maturity =
    let p = zcb_price params ~maturity in
    -. log p /. maturity

  (** Simulate r path using Euler-Maruyama discretisation *)
  let simulate_path { kappa; theta; sigma; r0 } ~steps ~dt ~rng =
    let path = Array.make (steps + 1) r0 in
    for i = 1 to steps do
      let z  = Rng.normal rng in
      let r  = path.(i - 1) in
      let dr = kappa *. (theta -. r) *. dt +. sigma *. sqrt dt *. z in
      path.(i) <- r +. dr
    done;
    path

  (** Long-run (asymptotic) yield: y(∞) = θ - σ²/(2κ²) *)
  let long_run_yield { kappa; theta; sigma; _ } =
    theta -. sigma *. sigma /. (2.0 *. kappa *. kappa)

end

(** Cox-Ingersoll-Ross (CIR) model: r stays positive *)
module Cir = struct
  type params = {
    kappa : float;
    theta : float;
    sigma : float;
    r0    : float;
  }

  (**
      Affine ZCB formula for CIR.
      The Feller condition κθ > σ²/2 ensures r > 0.
  *)
  let zcb_price { kappa; theta; sigma; r0 } ~maturity =
    let h = sqrt (kappa *. kappa +. 2.0 *. sigma *. sigma) in
    let tau = maturity in
    let exp_ht = exp (h *. tau) in
    let b = 2.0 *. (exp_ht -. 1.0)
            /. ((h +. kappa) *. (exp_ht -. 1.0) +. 2.0 *. h) in
    let a = ( 2.0 *. h *. exp ((kappa +. h) *. tau /. 2.0)
             /. ((h +. kappa) *. (exp_ht -. 1.0) +. 2.0 *. h)
            ) ** (2.0 *. kappa *. theta /. sigma /. sigma) in
    a *. exp (-. b *. r0)

  let yield params ~maturity =
    let p = zcb_price params ~maturity in
    -. log p /. maturity
end

8.6.2 Hull-White Model

Hull-White extends Vasicek by making the long-run mean $\theta(t)$ time-dependent, enabling exact fit to the initial yield curve:

$$dr_t = [\theta(t) - \kappa r_t] dt + \sigma dW_t$$

The key feature: $\theta(t)$ is calibrated so that the model prices today's yield curve exactly.


8.7 Multi-Curve Framework

Before 2008, practitioners used a single yield curve for both projecting forward LIBOR rates and discounting cash flows. This was theoretically justified by the assumption that LIBOR represented a near risk-free rate. The 2008 financial crisis destroyed this assumption: LIBOR rates (which incorporate bank credit risk and liquidity risk) diverged sharply from overnight indexed swap (OIS) rates (which reflect the near risk-free overnight rate). At the peak of the crisis, the 3-month LIBOR–OIS spread exceeded 350 basis points. This spread — which had historically hovered near 10bp — revealed that embedded in every floating-rate cash flow was a significant bank credit risk premium.

The modern multi-curve framework separates the two functions of the yield curve. The discount curve (built from OIS rates, e.g., SOFR in USD, ESTR in EUR) is used to discount all cash flows to present value, regardless of their source. Separate projection curves are built for each tenor (3M, 6M, 1Y) and used only to project forward floating rates. A 5-year interest rate swap that pays 3-month SOFR would: (1) project each quarterly floating rate using the 3M SOFR forward curve, and (2) discount each resulting cash flow using the OIS discount curve. The two curves are bootstrapped simultaneously from market instruments (OIS swaps and basis swaps).

Post-2008, LIBOR and OIS (overnight) rates diverged significantly due to bank credit risk. This requires separate projection curves (LIBOR/SOFR) and discount curves (OIS) in a multi-curve setup.

type multi_curve = {
  ois_curve      : discount_curve;   (* for discounting all cash flows *)
  libor_3m_curve : discount_curve;   (* for projecting 3M floating rates *)
  libor_6m_curve : discount_curve;   (* for projecting 6M floating rates *)
}

(** Project forward LIBOR rate from projection curve *)
let project_libor curve ~t_start ~tau =
  let df1 = log_linear_df curve t_start in
  let df2 = log_linear_df curve (t_start +. tau) in
  (df1 /. df2 -. 1.0) /. tau

(** Discount using OIS curve regardless of floating tenor *)
let discount_with_ois { ois_curve; _ } t =
  log_linear_df ois_curve t

(** Swap NPV in multi-curve world *)
let multi_curve_swap_npv swap { ois_curve; libor_3m_curve; _ } =
  let disc = log_linear_df ois_curve in
  let tau = 0.25 in   (* 3M tenor *)
  let m  = float_of_int swap.Swap.frequency in
  let n  = int_of_float (Float.round (swap.Swap.maturity *. m)) in
  (* Floating leg: project from 3M curve, discount with OIS *)
  let float_pv = ref 0.0 in
  for i = 0 to n - 1 do
    let t_s = float_of_int i /. m in
    let fwd = project_libor libor_3m_curve ~t_start:t_s ~tau in
    float_pv := !float_pv +. swap.Swap.notional *. fwd *. tau *. disc (t_s +. tau)
  done;
  let fixed_pv = Swap.fixed_leg_pv swap ~discount:disc in
  let sign = if swap.Swap.is_payer then 1.0 else -. 1.0 in
  sign *. (!float_pv -. fixed_pv)

8.8 Chapter Summary

Interest rate derivatives form the largest derivatives market in the world precisely because interest rate risk is pervasive. Any institution that borrows, lends, or holds fixed income assets has interest rate exposure that it may wish to hedge, transform, or speculate on. The instruments in this chapter form a complete toolkit for doing so.

FRAs and swaps are the building blocks: they convert fixed cash flows to floating (or vice versa) over a specified period. The par swap rate is the fixed rate that makes the swap's net present value zero at inception, and it can be computed directly from the yield curve bootstrapped in Chapter 7. The DV01 of a swap is approximately its annuity factor times the notional, making it straightforward to compute interest rate sensitivity.

Caps and floors introduce optionality: they protect against rate moves above or below a specified level without eliminating the benefit from moves in the other direction. Pricing them requires a model for the distribution of the forward rate, and Black's formula in the forward measure is the market standard. Swaptions extend this to the entire swap rate, using the annuity factor as the natural numeraire.

Short-rate models solve the joint problem of modelling the entire yield curve dynamically. Vasicek's 1977 model introduced mean reversion as the central feature — rates pull toward a long-run equilibrium $\theta$ with strength $\kappa$ — giving a tractable Gaussian distribution for $r_t$ and closed-form bond prices. The CIR model made volatility proportional to $\sqrt{r_t}$, eliminating the possibility of negative rates while preserving affine structure. Hull-White extended both to match the initial yield curve exactly by making $\theta(t)$ time-dependent. Post-2008, the multi-curve framework replaced the pre-crisis single-curve approach, using overnight indexed swaps for discounting and separate projection curves for each LIBOR/SOFR tenor.


Exercises

8.1 For a 5-year, $10M notional receiver swap paying 4.5% fixed, compute: NPV, DV01, and bucketed DV01 at the 1y, 2y, 5y curve tenors.

8.2 Price a 3×6 FRA (starts in 3 months, covers 3–6 months) with a strike of 5.2% given a flat yield curve at 5%. What is the DV01?

8.3 Calibrate Vasicek model parameters (κ, θ, σ) to fit the yield curve: 1y=4.5%, 2y=4.8%, 5y=5.1%, 10y=5.3%. Use least-squares minimization.

8.4 Price a 1y × 5y payer swaption with 5.5% strike, 20% vol, given the bootstrapped SOFR curve from Chapter 7.


Next: Chapter 9 — Equity Markets and Instruments