Finding a Vanilla Swap’s Fixed and Fair Rates in QuantLib
Summary
The document clarifies two different rate queries for a vanilla interest-rate swap built in QuantLib. The fixed rate is the coupon already assigned to the swap when it is created. The fair rate is calculated from the swap’s market value and represents the fixed coupon that would make the present values of the fixed and floating legs equal under the supplied curve and conventions.
The example constructs a curve, prices a swap with a chosen fixed coupon, and shows how to query both values. A coupon chosen arbitrarily need not equal the fair rate, so the resulting net present value need not be zero. This distinction helps explain why a hardcoded coupon is not automatically a market forward rate or a curve-derived par rate. The answer addresses rate retrieval and interpretation; it does not provide a separate derivation of DV01 or discuss curve construction choices in depth.
Key ideas
- The swap’s fixed rate is the coupon supplied when the instrument is created.
- The fair rate is the coupon that equates the present values of the fixed and floating legs.
- A swap with a fixed coupon different from its fair rate will generally have nonzero net present value.
- The fair rate depends on the swap terms and the curves used for pricing.
Tags
Full text
# Calculate Fixed Rate on Vanilla Swap in Quantlib
# Calculate Fixed Rate on Vanilla Swap in Quantlib
I am trying to calculate dv01 on the vanilla swap using quantlib but not able to understand how to calculate the fixed_rate. In all the examples it's a hardcoded value which is not right. Any suggestions on how to get the fixed_Rate using the curve, maturity and the effective date? In the below example its 0.05 but should be really a forward rate?
```
from QuantLib import *
# global data
calendar = TARGET()
todaysDate = Date(16, April, 2021)
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(20, April, 2021)
# market quotes
deposits = {
(1, Months): 0.04289,
(3, Months): 0.04289,
(6, Months): 0.04345,
(9, Months): 0.04401,
}
swaps = {
(1, Years): 0.04506,
(2, Years): 0.04881,
(3, Years): 0.05262,
(4, Years): 0.05575,
(5, Years): 0.05817,
(7, Years): 0.06212,
(10, Years): 0.06639,
(15, Years): 0.07074,
(20, Years): 0.07303,
(30, Years): 0.0741}
# convert them to Quote objects
for n, unit in deposits.keys():
deposits[(n, unit)] = SimpleQuote(deposits[(n, unit)])
for n, unit in swaps.keys():
swaps[(n, unit)] = SimpleQuote(swaps[(n, unit)])
# build rate helpers
dayCounter = Actual360()
settlementDays = 2
depositHelpers = [DepositRateHelper(QuoteHandle(deposits[(n, unit)]),
Period(n, unit), settlementDays,
calendar, Following,
False, dayCounter)
for n, unit in [(1, Months), (3, Months),
(6, Months), (9, Months)]]
fixedLegFrequency = EveryFourthWeek
fixedLegTenor = Period(28, Days)
fixedLegAdjustment = Following
fixedLegDayCounter = Actual360()
floatingLegTenor = Period(28, Days)
floatingLegAdjustment = Following
swapHelpers = [SwapRateHelper(QuoteHandle(swaps[(n, unit)]),
Period(n, unit), calendar,
fixedLegFrequency, fixedLegAdjustment,
fixedLegDayCounter, Euribor6M())
for n, unit in swaps.keys()]
# term structure handles
discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()
# term-structure construction
helpers = depositHelpers + swapHelpers
depoSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())
swapEngine = DiscountingSwapEngine(discountTermStructure)
# 5Y Swap
nominal = 10000000
maturity = Date(10, June, 2026)
fixedRate = 0.05
spread = 0.0
index = Euribor6M(forecastTermStructure)
fixedSchedule = Schedule(settlementDate, maturity,
fixedLegTenor, calendar,
fixedLegAdjustment, fixedLegAdjustment,
DateGeneration.Forward, False)
floatingSchedule = Schedule(settlementDate, maturity,
floatingLegTenor, calendar,
floatingLegAdjustment, floatingLegAdjustment,
DateGeneration.Forward, False)
swap = VanillaSwap(VanillaSwap.Receiver, nominal,
fixedSchedule, fixedRate, fixedLegDayCounter,
floatingSchedule, index, spread,
Actual360())
swap.setPricingEngine(swapEngine)
discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)
print('NPV')
print(swap.NPV())
print('Rate')
print(swap.fairRate())
shift = 0.0001
temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_p = swap.NPV()
temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(-shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(-shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_m = swap.NPV()
dv01 = (P_m - P_p) / 2.0
print('Swap DV01')
print(dv01)
```
## Answer by David Duarte (score 1)
https://quant.stackexchange.com/a/63416
I'm not sure what you are asking, but once you build the swap object, you can query the fixed rate that is defined for that swap:
```
swap.fixedRate()
```
Or you can query what is the fair rate for that swap, ie, the rate which would make the market value of the fixed leg equal to the market value of the floating leg:
```
swap.fairRate()
```
The example defines the fixed rate as 0.05, but as that is not the fair rate for that particular swap, the NPV will not be zero.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.