Skip to content
All library documents

Matching Date Generation Rules in QuantLib OIS Fair-Rate Calculations

Article Quant Q&A · Author: Lorienzo

Summary

The document investigates why a QuantLib overnight index swap does not reproduce the quoted rate used to build a curve through DatedOISRateHelper. Its example compares a swap starting on the evaluation date and ending on a date that falls after a weekend with the helper quote associated with that maturity. The observed fair rate differs, although alternatives using a one-year tenor or a different dated maturity return the expected rate.

The accepted explanation is that the helper’s internal swap uses forward date generation, while the separately created swap has a different schedule and is therefore not the same instrument. Matching the date generation rule makes the fair rate agree. The answer also notes that a later QuantLib version would allow specifying this rule through a date-based helper factory. This is a focused implementation diagnosis; it does not address other curve construction settings or establish behavior across versions beyond the stated update.

Key ideas

  • A DatedOISRateHelper builds an internal swap whose schedule conventions affect the curve quote.
  • The example’s separately constructed swap differs because its date generation rule does not match the helper’s.
  • Using forward date generation for the swap produces the expected fair rate in the described case.
  • A later QuantLib version was expected to expose the rule through a date-based helper factory.

Tags

Full text
# Question on QuantLib Python DatedOISRateHelper fairRate


# Question on QuantLib Python DatedOISRateHelper fairRate












I'm wondering if this is intended in DatedOISRateHelper. Referring to executable code below, 1Y OIS maturity date is 22nd Dec 2025 (21st and 22nd Dec fall on weekend). However when I try to price OIS that starts on 20th Dec 2024 and ends on 22nd Dec 2025, the fairRate() doesn't return input of 0.0396015. Shouldn't we able to price back fairRate 0.0396015 based on input to DatedOISRateHelper?

Note: I will be able to get correct fairRate if I use OISRateHelper with "1Y" as input; or DatedOISRateHelper with "20th Dec 2025" as input.

```
import QuantLib as ql

today = ql.Date(20, 12, 2024)
ql.Settings.instance().evaluationDate = today

maturity_dates = [
    ql.Date(27, 12, 2024), ql.Date(20, 1, 2025), ql.Date(20, 2, 2025), ql.Date(20, 3, 2025),
    ql.Date(22, 4, 2025), ql.Date(20, 5, 2025), ql.Date(20, 6, 2025), ql.Date(22, 9, 2025),
    ql.Date(22, 12, 2025), ql.Date(22, 6, 2026), ql.Date(21, 12, 2026),
]

rates = [
    0.0433, 0.04337, 0.04342, 0.043045, 0.0426125, 0.042335, 0.04184, 0.04086, 0.0396015, 0.038455, 0.0378795,
]

ois_helpers = [
    ql.DatedOISRateHelper(
        today,
        tenor,
        ql.QuoteHandle(ql.SimpleQuote(rate)),
        ql.Aonia(),
        paymentFrequency=ql.Annual,
    )
    for tenor, rate in zip(maturity_dates, rates)
]

ois_curve = ql.PiecewiseSplineCubicDiscount(0,ql.Australia(), ois_helpers, ql.Actual365Fixed())
discount_curve = ql.YieldTermStructureHandle(ois_curve)
swapEngine = ql.DiscountingSwapEngine(discount_curve)

schedule = ql.MakeSchedule(
    effectiveDate=today,
    terminationDate=ql.Date(22, 12, 2025),
    tenor=ql.Period("1Y"),
    calendar=ql.Australia(),
    convention=ql.ModifiedFollowing,
    terminalDateConvention=ql.ModifiedFollowing,
    rule=ql.DateGeneration.Forward,
)

ois_swap = ql.OvernightIndexedSwap(
    ql.OvernightIndexedSwap.Receiver,
    1_000_000,
    schedule,
    0.1,
    ql.Actual365Fixed(),
    ql.Aonia(discount_curve),
)
ois_swap.setPricingEngine(ql.DiscountingSwapEngine(discount_curve))

print(
    ois_swap.startDate(),
    ois_swap.maturityDate(),
    f"{ois_swap.fairRate():.9f}",
    ois_swap.fixedLegBPS(),
    discount_curve.discount(ois_swap.maturityDate()),
)
```
```

## Answer by Luigi Ballabio (score 3, accepted)

https://quant.stackexchange.com/a/81501

The swap inside the `DatedOISRateHelper` used to bootstrap the curve are currently instantiated with `rule=ql.DateGeneration.Forward`, which makes your `ois_swap` different from the quoted swap. If you use the same rule for `ois_swap`, you'll get the expected fair rate.

Starting from version 1.37, due for January 2025, you'll be able to specify the date generation rule as `Forward` when creating the helper. Note that, instead of the constructor of `DatedOISRateHelper` (which will be deprecated) you'll have to build the helpers by calling the static method `OISRateHelper.forDates`.

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.