Setting the Underlying Period When Pricing a 3x6 FRA in QuantLib
Summary
The document diagnoses a date-construction error in a QuantLib example for a three-by-six forward rate agreement. The intended contract begins three months after the valuation date and covers the following three-month interest period. The original code instead supplied the valuation date as the FRA start and a date three months later as maturity.
The accepted answer shows that the start date should be advanced three months from today, with the maturity advanced a further three months. It explains that the constructor dates represent the underlying LIBOR accrual period, not the time remaining until that period starts. Using a period that had already expired led QuantLib to return a zero net present value. The example is specific to the stated FRA setup; users still need appropriate calendars, conventions, curves, and index settings for their own contracts.
Key ideas
- A 3x6 FRA starts three months after the valuation date and ends six months after it.
- The FRA constructor’s start and maturity dates define the underlying LIBOR period.
- Using today and three months later as the contract dates describes a different period that may already be expired.
- Incorrect period dates can cause QuantLib to return a zero net present value.
Tags
Full text
# Pricing a Forward Rate Agreement using QuantLib Python
# Pricing a Forward Rate Agreement using QuantLib Python
Can someone please help with the pricing of the following forward rate agreement using QuantLib Python?
A 3x6 forward rate agreement, with a notional of $100,000, the FRA rate being 6%, The FRA settlement date is after 3 months (90 days) and the settlement is based on a 90-day USDLIBOR.
My valuation date is 30 June 2020.
This is my attempt:
```
import QuantLib as ql
startDate = ql.Date(30, 6, 2020)
ql.Settings.instance().evaluationDate = startDate
spotDates = [ql.Date(30, 6, 2020), ql.Date(31, 12, 2020), ql.Date(30, 6, 2021)]
spotRates = [0.05, 0.05, 0.05]
dayConvention = ql.Thirty360()
calendar = ql.UnitedStates()
maturityDate = calendar.advance(startDate, ql.Period('3M'))
compounding = ql.Simple
compoundingFrequency = ql.Annual
spotCurve = ql.ZeroCurve(spotDates, spotRates, dayConvention, calendar, ql.Linear(), compounding, compoundingFrequency)
spotCurve.enableExtrapolation()
spotCurveHandle = ql.YieldTermStructureHandle(spotCurve)
index = ql.USDLibor(ql.Period('3M'), spotCurveHandle)
index.addFixing(ql.Date(26, 6, 2020), 0.05)
notional = 100000
rate = 0.06
fra = ql.ForwardRateAgreement(startDate, maturityDate, ql.Position.Long, rate, notional, index, spotCurveHandle)
print('NPV:', fra.NPV())
```
And this is the answer that I get:
> NPV: 0.0
The answer that I'm getting is not correct.
## Answer by Luigi Ballabio (score 4, accepted)
https://quant.stackexchange.com/a/67807
For a 3x6 FRA, you probably want to write something like:
```
today = ql.Date(30, 6, 2020)
ql.Settings.instance().evaluationDate = today
startDate = calendar.advance(today, ql.Period('3M'))
maturityDate = calendar.advance(startDate, ql.Period('3M'))
```
That is, the start and maturity dates you pass to the FRA constructor should be the underlying period of the LIBOR.
What you were writing instead was a FRA over a period from today to three months hence, which the library considered as already expired.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.