Interest Rate Swap Valuation and Applications › Swap Valuation as a Portfolio of FRAs

Michael BrenndoerferUpdated January 5, 20269 min read
Quantitative FinanceAll chapters
Part 4 of 15Swaps and Credit Derivatives
Chapter 21Interest Rate Swap Valuation and Applications › Swap Valuation as a Portfolio of FRAs
Reading section 4 of 17 · Swap Valuation as a Portfolio of FRAs · 9 minSection 4 of 17 · 9 min

Book contents

Section 4 of 17 · 9 min read

Interest Rate Swap Valuation and Applications › Swap Valuation as a Portfolio of FRAsOne section · Sections in this chapter4 / 17 ↓
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

An alternative and equally valid approach views a swap as a series of forward rate agreements. Rather than thinking of the swap as two bonds, we can decompose it into individual exchanges of fixed for floating payments at each payment date. Each payment exchange in the swap can be treated as a separate FRA. This perspective connects swap pricing directly to forward rates, which we discussed in the context of the term structure in Part II, Chapter 3.

The FRA approach offers different insights than the bond approach. While the bond view emphasizes the swap's relationship to fixed income securities, the FRA view highlights how each payment period contributes to the swap's total value. This decomposition is especially useful for analyzing where swap value comes from along the yield curve.

Forward Rate Agreement Review

Before applying this to swaps, let's review forward rate agreements and their valuation. A forward rate agreement is a contract to exchange a fixed interest payment for a floating payment at a future date, based on a rate determined at an earlier fixing date. The contract specifies a notional amount, a forward period, and a contracted rate against which the realized floating rate will be compared.

The payoff of a receive-fixed FRA settling at time T+δT+\delta for a period of length δ\delta starting at TT is:

FRA Payoff=δ⋅N⋅(K−LT)\text{FRA Payoff} = \delta \cdot N \cdot (K - L_T)

where:

  • δ\delta: accrual period length
  • NN: notional principal
  • KK: contracted forward rate
  • LTL_T: realized floating rate at time TT

The payoff is positive when the contracted rate exceeds the realized floating rate, meaning you receive the difference. Conversely, the payoff is negative when the floating rate exceeds the contracted rate.

To determine the present value before settlement, we use the simple-accrual forward rate implied by today's curve. In this single-curve model, F(0,T,T+δ)=[Z(0,T)/Z(0,T+δ)−1]/δF(0,T,T+\delta)=[Z(0,T)/Z(0,T+\delta)-1]/\delta. Its expectation interpretation uses the payment-date forward measure, associated with the bond maturing at T+δT+\delta, rather than an unqualified physical forecast. For the stated end-of-period payoff, the present value is:

VFRA=δ⋅N⋅(K−F(0,T,T+δ))⋅Z(0,T+δ)V_{\text{FRA}} = \delta \cdot N \cdot (K - F(0, T, T+\delta)) \cdot Z(0, T+\delta)

where:

  • VFRAV_{\text{FRA}}: present value of the FRA
  • F(0,T,T+δ)F(0, T, T+\delta): simple-accrual forward rate observed today for the period starting at TT, with the same accrual fraction as the payoff
  • Z(0,T+δ)Z(0, T+\delta): discount factor to the payment date
  • TT: start date of the forward period
  • δ\delta: accrual period length
  • NN: notional principal
  • KK: contracted forward rate

This formula tells us that the FRA has positive value when the contracted rate KK exceeds the market forward rate FF, and negative value when the market forward rate exceeds the contracted rate.

Decomposing the Swap

With the FRA valuation framework established, we can now view the entire swap as a portfolio of these individual contracts. A swap with nn payment dates can be decomposed into nn forward rate agreements, each corresponding to one payment exchange. The value of the entire swap is the sum of these FRA values:

Vswap=∑i=1nδi⋅N⋅(K−Fi)⋅Z(0,ti)V_{\text{swap}} = \sum_{i=1}^{n} \delta_i \cdot N \cdot (K - F_i) \cdot Z(0, t_i)

where:

  • VswapV_{\text{swap}}: total value of the swap
  • nn: total number of payment dates
  • δi\delta_i: day count fraction for period ii
  • NN: notional principal
  • KK: fixed rate
  • FiF_i: forward rate for period ii (F(0,ti−1,ti)F(0, t_{i-1}, t_i))
  • Z(0,ti)Z(0, t_i): discount factor for payment at time tit_i

For a par swap entered without an upfront premium, choose K so that the initial swap value is zero; an off-market coupon can instead require an upfront value adjustment. By setting the swap value to zero and solving for the fixed rate, we can derive the par swap rate. The derivation proceeds as follows:

0=∑i=1nδi⋅N⋅(K−Fi)⋅Z(0,ti)(set swap value to zero)0=N(K∑i=1nδiZ(0,ti)−∑i=1nδiFiZ(0,ti))(factor out N and separate terms)K∑i=1nδiZ(0,ti)=∑i=1nδiFiZ(0,ti)(divide by N and rearrange)\begin{aligned} 0 &= \sum_{i=1}^{n} \delta_i \cdot N \cdot (K - F_i) \cdot Z(0, t_i) && \text{(set swap value to zero)} \\ 0 &= N \left( K \sum_{i=1}^{n} \delta_i Z(0, t_i) - \sum_{i=1}^{n} \delta_i F_i Z(0, t_i) \right) && \text{(factor out } N \text{ and separate terms)} \\ K \sum_{i=1}^{n} \delta_i Z(0, t_i) &= \sum_{i=1}^{n} \delta_i F_i Z(0, t_i) && \text{(divide by } N \text{ and rearrange)} \end{aligned}

Solving for KK:

K=∑i=1nδi⋅Fi⋅Z(0,ti)∑i=1nδi⋅Z(0,ti)K = \frac{\sum_{i=1}^{n} \delta_i \cdot F_i \cdot Z(0, t_i)}{\sum_{i=1}^{n} \delta_i \cdot Z(0, t_i)}

where:

  • KK: par swap rate
  • nn: number of payment periods
  • FiF_i: forward rate for period ii
  • δi\delta_i: day count fraction
  • Z(0,ti)Z(0, t_i): discount factor
  • ∑i=1nδi⋅Fi⋅Z(0,ti)\sum_{i=1}^{n} \delta_i \cdot F_i \cdot Z(0, t_i): present value of the expected floating leg payments per unit of notional
  • ∑i=1nδi⋅Z(0,ti)\sum_{i=1}^{n} \delta_i \cdot Z(0, t_i): annuity factor for payments of δi\delta_i per unit notional, corresponding to a fixed annual rate of 1

The par swap rate is a weighted average of simple forward rates, with normalized weights proportional to δiZ(0,ti)\delta_i Z(0,t_i). For equal accrual fractions and declining discount factors, later periods receive lower weights. Neither that ordering nor a forecast of physical expected short-term rates follows without additional assumptions. In this single-curve model, the floating payments telescope because δiFiZ(0,ti)=Z(0,ti−1)−Z(0,ti)\delta_i F_i Z(0,t_i)=Z(0,t_{i-1})-Z(0,t_i), with Z(0,0)=1Z(0,0)=1.

The example below takes each accrual fraction to equal the difference between its maturity times in years, so the semiannual schedule uses δi=0.5\delta_i=0.5. For a contractual day-count convention, use that convention's accrual fraction in the simple-forward conversion and payment calculation; it need not equal the zero curve's time difference.

In[7]:
Code
def calculate_forward_rates(zero_rates, maturities):
    """
    Convert continuous zero rates to simple interval forward rates.
    Maturities are positive and strictly increasing, in years from today.
    This example's accrual fractions equal the maturity differences.
    """
    forward_rates = []

    for i in range(len(maturities)):
        t1 = 0.0 if i == 0 else maturities[i - 1]
        log_growth_start = 0.0 if i == 0 else zero_rates[i - 1] * t1
        t2 = maturities[i]
        # D(t1)/D(t2) - 1, divided by the period's simple accrual.
        f = np.expm1(zero_rates[i] * t2 - log_growth_start) / (t2 - t1)
        forward_rates.append(f)

    return np.array(forward_rates)


def value_swap_via_fra(
    notional, fixed_rate, forward_rates, discount_factors, payment_freq
):
    """Value aligned FRA periods using a common accrual fraction in years.

    payment_freq is the shared accrual fraction, not payments per year.
    Forward and discount arrays must be finite, nonempty, aligned 1D vectors;
    discount factors must be positive. Irregular accruals need a generalization.
    """
    forward_rates = np.asarray(forward_rates, dtype=float)
    discount_factors = np.asarray(discount_factors, dtype=float)
    if (
        forward_rates.ndim != 1
        or discount_factors.ndim != 1
        or forward_rates.size == 0
        or forward_rates.size != discount_factors.size
        or not np.all(np.isfinite(forward_rates))
        or not np.all(np.isfinite(discount_factors))
        or np.any(discount_factors <= 0)
    ):
        raise ValueError("Use nonempty aligned finite 1D arrays and positive discounts")
    scalars = np.asarray([notional, fixed_rate, payment_freq], dtype=float)
    if scalars.shape != (3,) or not np.all(np.isfinite(scalars)) or scalars[2] <= 0:
        raise ValueError(
            "Use finite scalar inputs and a positive common accrual fraction"
        )
    notional, fixed_rate, payment_freq = scalars
    total_value = 0

    for i, (fwd, disc) in enumerate(zip(forward_rates, discount_factors)):
        # Each FRA: delta * N * (K - F) * Z
        fra_value = payment_freq * notional * (fixed_rate - fwd) * disc
        total_value += fra_value

    return total_value


# Calculate forward rates
forward_rates = calculate_forward_rates(zero_rates, maturities)

# Value swap via FRA approach
swap_value_fra = value_swap_via_fra(
    notional, fixed_rate, forward_rates, discount_factors, payment_frequency
)

# Calculate individual FRA values for analysis
fra_values = []
for fwd, disc in zip(forward_rates, discount_factors):
    fra_values.append(payment_frequency * notional * (fixed_rate - fwd) * disc)
Out[8]:
Console
Forward Rates and FRA Decomposition
============================================================
Period      Forward Rate   Discount Factor      FRA Value
------------------------------------------------------------
0.0-0.5y         3.5308%         0.982652   $   72,185.42
0.5-1.0y         4.1423%         0.962713   $   41,285.29
1.0-1.5y         4.4488%         0.941765   $   25,957.06
1.5-2.0y         4.8581%         0.919431   $    6,525.04
2.0-2.5y         4.7557%         0.898077   $   10,971.79
2.5-3.0y         4.9605%         0.876341   $    1,729.98
------------------------------------------------------------
Total Swap Value:                             $  158,654.57

Verification - Bond approach value: $158,654.57
Out[9]:
Visualization
Six positive FRA value bars, generally falling, with the fifth bar higher than the fourth because the forward rate dips.
FRA value contribution by period for a receive-fixed swap using simple-accrual forward rates. Each bar is positive because the 5% fixed rate exceeds the corresponding forward rate. Both the rate gap and the discount factor determine the contribution; the fifth contribution rises when its forward rate dips.
Six simple forward-rate bars below the dashed 5% fixed-rate line, starting near 3.53%, dipping in the fifth period, and ending near 4.96%.
Comparison of the 5% fixed rate with simple-accrual forward rates converted from continuous zero rates. Forwards start near 3.53%, reach 4.86% in the fourth period, dip to 4.76% in the fifth, and end near 4.96%.

Both approaches yield the same swap value, confirming their equivalence. The FRA approach provides additional insight by breaking down the swap's value across individual payment periods. This decomposition reveals which parts of the yield curve contribute most to the swap's value and helps you understand the term structure exposure embedded in your positions.