Interest Rate Swap Valuation and Applications › Swap Valuation as a Portfolio of FRAs
Quantitative FinanceAll chapters 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 for a period of length starting at is:
where:
- : accrual period length
- : notional principal
- : contracted forward rate
- : realized floating rate at time
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, . Its expectation interpretation uses the payment-date forward measure, associated with the bond maturing at , rather than an unqualified physical forecast. For the stated end-of-period payoff, the present value is:
where:
- : present value of the FRA
- : simple-accrual forward rate observed today for the period starting at , with the same accrual fraction as the payoff
- : discount factor to the payment date
- : start date of the forward period
- : accrual period length
- : notional principal
- : contracted forward rate
This formula tells us that the FRA has positive value when the contracted rate exceeds the market forward rate , 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 payment dates can be decomposed into forward rate agreements, each corresponding to one payment exchange. The value of the entire swap is the sum of these FRA values:
where:
- : total value of the swap
- : total number of payment dates
- : day count fraction for period
- : notional principal
- : fixed rate
- : forward rate for period ()
- : discount factor for payment at time
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:
Solving for :
where:
- : par swap rate
- : number of payment periods
- : forward rate for period
- : day count fraction
- : discount factor
- : present value of the expected floating leg payments per unit of notional
- : annuity factor for payments of 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 . 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 , with .
The example below takes each accrual fraction to equal the difference between its maturity times in years, so the semiannual schedule uses . 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.
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)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


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.