Actual/Actual ISMA Year Fractions with and without Coupon Dates
Summary
The document explains why QuantLib’s Actual/Actual ISMA day counter can return different year fractions depending on whether coupon-period dates are supplied. In the bond example, the calculation date falls between the previous and next semiannual coupon dates. Supplying those dates yields a fraction based on the actual days within the coupon period; omitting them leads the convention to infer a rounded month count instead.
The example reports results of about 0.4508 with the coupon dates and 0.4167 without them, and notes that this difference can affect bond present values and yield-curve calculations. The response gives an intuitive account of the month-count behavior and points to the implementation and convention definition for details. It does not fully derive the adjustment formula, so users implementing or validating accruals should consult the formal convention and library documentation.
Key ideas
- Actual/Actual ISMA calculations can depend on explicit reference coupon dates.
- Without a coupon period, the day counter may infer a year fraction from a rounded month count.
- Providing the coupon dates can produce a different accrual fraction for the same dates.
- Differences in accrued time fractions can affect bond valuation and yield-curve calculations.
Tags
Full text
# Using DayCounter ActualActual.ISMA in QuantLib
# Using DayCounter ActualActual.ISMA in QuantLib
Suppose we have a semiannual coupon bond. The calculation date is 5/8 2017. The ex-coupon date is 4/20 2017 and next coupon date is 10/20 2017.
```
issue_date= Date(20,10,2001)
maturity_date=Date(20, 10, 2021)
tenor=Period(2)
calendar=China()
business_convention=Unadjusted
date_generation=DateGeneration.Backward
month_end=False
schedule=Schedule(issue_date,maturity_date,tenor,calendar,business_convention,business_convention,date_generation,month_end)
day_count= ActualActual(ActualActual.ISMA,schedule)
```
When I define the `day_count`, I specify the type and the coupon schedule. There are 165 days between 5/8 2017 and 10/20 2017, and 183 days in this period. This should be 0.4508(which is divided by frequency). Actually, I can get this by defining the coupon period:
```
day_count.yearFraction(calc_date,Date(20,10,2017),Date(20,4,2017),Date(20,10,2017))
Out[1]: 0.45081967213114754
```
However, when I directly enter the `calc_date`, it returns a strange result.
```
day_count.yearFraction(calc_date,Date(20,10,2017))
Out[2]: 0.4166666666666667
```
I think this will change the npv when I construct `FlatForward` yield curve and `FixedRateBond`.
## Answer by Phil-ZXX (score 1)
https://quant.stackexchange.com/a/40206
In your second example (when no period is specified), the ActualActual.ISMA DayCounter basically returns
```
RoundedNumberOfMonthsBetween(date1,date2) / 12 = 5 / 12 = 0.41666
```
whereas in the first one (when there is a specific period) some fancy adjustments are made based on the difference in days (20 - 8 + halfday = 12.5):
```
RoundedNumberOfMonthsBetween(date1,date2) / 12 + 12.5/365 ≈ 0.4508
```
I am not entirely familiar with the exact adjustment. But for more details have a look at
- https://github.com/lballabio/QuantLib/blob/master/ql/time/daycounters/actualactual.cpp#L44
- https://en.wikipedia.org/wiki/Day_count_convention#Actual/Actual_ICMAShown 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.