A par swap coupon from discounted cashflows¶
A par swap has a fixed coupon that balances the discounted floating leg. We calculate that coupon for a five-year receive-fixed USD swap, compare it with the native fair-rate result and reprice the contract at the solved rate.
The trade starts on 24 February 2026 with USD 1 million notional. Fixed payments are semiannual, floating payments quarterly, dates unadjusted and accrual Actual/360. A single SOFR curve supplies projection and discounting. For this spot-starting setup, the floating leg telescopes to
Here \(A\) is the annuity per unit notional, measured in years. With separate projection and discount curves, calculate the floating-leg sum explicitly. Setup.
Computational study. Canonical notebook · Companion files and setup. Download this notebook.
This page renders saved outputs; the documentation build does not execute it. Run the canonical notebook from its own directory with the checkout-built binding to reproduce the computation. Each study records its market inputs and numerical assumptions.
import pandas as pd
import quantsupport as qs
from market_data import load_market
market = load_market()
ref = market.quotes.reference_date
notional = 1_000_000
agreed_coupon = 0.04
fixed_period_months = 6
number_of_periods = 10
Solving and repricing the fixed coupon¶
We build a receive-fixed trade for each candidate coupon, keeping the dates, notional and conventions fixed. The payment schedule also gives an independent annuity calculation. Once the native pricer supplies its par coupon, we construct a new trade at that rate and check its value.
def receive_fixed_swap(fixed_rate):
instrument = qs.Swap(
identifier="USD-SWAP-5Y",
start_date=ref,
maturity_date=ref + "5Y",
notional=notional,
fixed_rate=fixed_rate,
currency=qs.Currency.USD,
market_index=qs.MarketIndex.SOFR,
day_counter=qs.DayCounter.Actual360,
fixed_leg_frequency=qs.Frequency.Semiannual,
floating_leg_frequency=qs.Frequency.Quarterly,
)
return qs.Trade(instrument, ref, qs.Side.LongReceive)
context = qs.PricingContext(
quotes=market.quotes, curves=market.curves, csa_policy=market.csa_policy
)
with context:
curve = context.curve(qs.MarketIndex.SOFR)
payment_dates = [
ref + qs.Period(fixed_period_months * period, qs.TimeUnit.Months)
for period in range(number_of_periods + 1)
]
fixed_periods = []
for start, end in zip(payment_dates, payment_dates[1:]):
accrual = qs.DayCounter.Actual360.year_fraction(start, end)
discount_factor = curve.discount_factor(end)
fixed_periods.append(
{
"payment_date": str(end),
"accrual": accrual,
"discount_factor": discount_factor,
}
)
fixed_schedule = pd.DataFrame(fixed_periods)
annuity = (fixed_schedule["accrual"] * fixed_schedule["discount_factor"]).sum()
floating_pv_per_notional = 1 - curve.discount_factor(ref + "5Y")
independently_solved_rate = floating_pv_per_notional / annuity
swap_result = context.evaluate(
receive_fixed_swap(agreed_coupon), [qs.Request.Value, qs.Request.FairRate(0)]
)
par_result = context.evaluate(
receive_fixed_swap(swap_result.fair_rate), [qs.Request.Value]
)
pd.Series(
{
"fixed_annuity_years": annuity,
"native_par_rate": swap_result.fair_rate,
"independent_par_rate": independently_solved_rate,
"original_pv_usd": swap_result.price,
"independent_original_pv_usd": notional
* (agreed_coupon * annuity - floating_pv_per_notional),
"pv_at_par_usd": par_result.price,
}
)
fixed_annuity_years 4.524195e+00
native_par_rate 4.036802e-02
independent_par_rate 4.036800e-02
original_pv_usd -1.664991e+03
independent_original_pv_usd -1.664892e+03
pv_at_par_usd 5.366019e-11
dtype: float64
print(
f"Par coupon: {swap_result.fair_rate:.6%}; PV at par: USD {par_result.price:.3e}."
)
print(f"One coupon bp changes fixed-leg PV by USD {notional * annuity * 1e-4:.2f}.")
fixed_schedule
Par coupon: 4.036802%; PV at par: USD 5.366e-11.
One coupon bp changes fixed-leg PV by USD 452.42.
| payment_date | accrual | discount_factor | |
|---|---|---|---|
| 0 | 2026-08-24 | 0.502778 | 0.976544 |
| 1 | 2027-02-24 | 0.511111 | 0.953257 |
| 2 | 2027-08-24 | 0.502778 | 0.933651 |
| 3 | 2028-02-24 | 0.511111 | 0.914227 |
| 4 | 2028-08-24 | 0.505556 | 0.897578 |
| 5 | 2029-02-24 | 0.511111 | 0.881127 |
| 6 | 2029-08-24 | 0.502778 | 0.864875 |
| 7 | 2030-02-24 | 0.511111 | 0.848652 |
| 8 | 2030-08-24 | 0.502778 | 0.832992 |
| 9 | 2031-02-24 | 0.511111 | 0.817367 |
The annuity also measures exposure to the contractual coupon: at a fixed
market, increasing that coupon by one basis point changes PV by
notional × annuity × 1e-4. Market-quote risk additionally changes projected
floating coupons and discount factors. The
portfolio-risk study examines those
dependencies; currency conversion extends the
valuation to CLP payments under USD collateral.