Skip to content
All library documents

Setting the Underlying Period When Pricing a 3x6 FRA in QuantLib

Article Quant Q&A · Author: ql.user2511

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.