Skip to content
All library documents

Actual/Actual ISMA Stub Coupons in Fixed-Rate Bonds

Article Quant Q&A · Author: Roshan Yadav

Summary

The document examines how Actual/Actual ISMA determines coupon amounts for a fixed-rate bond with a short or long stub period. Its example has a first coupon running from the issue date to a February payment date, followed by monthly coupons. The initial QuantLib setup reports a larger first payment; constructing the day counter with the schedule gives a smaller amount, which the accepted response attributes to the schedule information needed for the stub calculation.

A second explanation describes how a long front stub can be represented as a full regular coupon period plus a fractional period, with the fraction depending on the regular schedule and roll date. It also notes that some market conventions calculate the fractional part differently. The discussion is specific to the example and includes speculation about QuantLib's original result; it does not establish a general explanation for every implementation or bond convention.

Key ideas

  • Actual/Actual ISMA stub calculations can require the full coupon schedule as input.
  • A long front stub may be decomposed into a regular coupon period and a fractional period.
  • The fractional amount depends on the schedule's regular dates and roll convention.
  • Different market conventions may use different methods for calculating a stub fraction.

Tags

Full text
# Calculation of Cashflows Using ISMA Day Count in Fixed-Rate Bond


# Calculation of Cashflows Using ISMA Day Count in Fixed-Rate Bond












I'm working with a fixed-rate bond in QuantLib, and I have set the day count convention to ISMA, but I would like to understand how this specific day count convention is used in the calculation of the bond's first cashflow I have gone through the link https://www.isda.org/a/pIJEE/The-Actual-Actual-Day-Count-Fraction-1999.pdf still not able to understand how quantlib is calculating the first short period or long period cashflow. Here are the relevant code and cashflows:

```
issue_date = ql.Date(1, 1, 2021)
maturity_date = ql.Date(15, 1, 2022)
stubdate = ql.Date(28, 2, 2021)
coupon_rate = 8.40 / 100
face_value = 1000000
calendar = ql.NullCalendar()
day_count = ql.ActualActual(ql.ActualActual.ISMA)
compounding = ql.Simple
payfreq = ql.Monthly
payment_schedule = ql.Schedule(issue_date, maturity_date, ql.Period(payfreq), calendar, ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Forward, True, stubdate)
lst_pysch = list(payment_schedule)
lst_pysch.pop(0)
lst_pysch.insert(0, issue_date)
new_paysch = ql.Schedule(lst_pysch)

fixedrate_leg = ql.FixedRateLeg(
            schedule=new_paysch, dayCount=day_count, nominals=[face_value], couponRates=[coupon_rate])

bond = ql.Bond(0, calendar, 100.0, maturity_date, issue_date, fixedrate_leg)

[(a.date(), a.amount()) for a in fixedrate_leg]
```

Output:

```
[(Date(28, 2, 2021), 14000.000000000013),
 (Date(31, 3, 2021), 6999.999999999895),
 ...
 (Date(15, 1, 2022), 3452.054794520487)]
```

My specific question is, how is the first cashflow value of 14,000 calculated? I would like to understand the logic and calculations behind this particular cashflow.

Thank you for your help!

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

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

Calculate the schedule first, and then create the day counter as:

```
day_count = ql.ActualActual(ql.ActualActual.ISMA, payment_schedule)
```

this allows the act/act instance to have all the information it needs to perform the calculations so well detailed by @Attack68. After this change, the output of your code is:

```
[(Date(28,2,2021), 13774.193548387047),
 (Date(31,3,2021), 6999.999999999895),
 (Date(30,4,2021), 6999.999999999895),
 (Date(31,5,2021), 6999.999999999895),
 (Date(30,6,2021), 6999.999999999895),
 (Date(31,7,2021), 6999.999999999895),
 (Date(31,8,2021), 6999.999999999895),
 (Date(30,9,2021), 6999.999999999895),
 (Date(31,10,2021), 6999.999999999895),
 (Date(30,11,2021), 6999.999999999895),
 (Date(31,12,2021), 6999.999999999895),
 (Date(15,1,2022), 3387.0967741935765)]
```

## Answer by Attack68 (score 5)

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

I cannot speak for `Quantlib`, I do not believe that calculation is correct actually.

But I can tell you how this calculation is performed in `Rateslib`.

```
from rateslib import *

bond = FixedRateBond(
    effective=dt(2021, 1, 1),
    termination=dt(2022, 1, 15),
    front_stub=dt(2021, 2, 28),
    stub="LongFrontShortBack",
    roll=31,
    convention="ActActICMA",
    modifier="none",
    frequency="M",
    fixed_rate=8.4
)
curve = Curve({dt(2021, 1, 1): 1.0, dt(2022, 12, 31): 0.96})
bond.cashflows(curve)
```

In this case the first period is identified as a `Stub` under `ActActICMA` mode and the calculation proceeds as follows:

i) Subtract a regular period from 28-feb-21 to get to 31-Jan-21.

ii) The start is less than 31-Jan-21 so it must be a LongStub. Set `fraction=1.0`.

iii) Subtract another regular period from 31-Jan-21 to get to 31-Dec-20.

iv) 1-Jan-21 is after this date so we add the following amount to `fraction`:

$$ \frac{31/Jan/21 - 1/Jan/21}{31/Jan/21 - 31/Dec/21} = 0.967741935483871 $$

v) `fraction = 1.967741935483871` and `coupon=8.4% / 12 * fraction * 1mm = 13,774.19 `

### Other Factors

#### Roll day

I observed from your bond schedule that the roll was end-of-month (31) so this has been added to generate the schedule. If the roll was `28` this would change the above calculations. Nothing else about the bond needs to change except the `roll` and this will produce different cashflows in the front and back stubs.

```
other_bond = FixedRateBond(
    effective=dt(2021, 1, 1),
    termination=dt(2022, 1, 15),
    front_stub=dt(2021, 2, 28),
    stub="LONGFRONTSHORTBACK",
    roll=28,
    fixed_rate=8.4,
    frequency="M",
    convention="ActActICMA",
)
other_bond.cashflows(curve)
```

#### Calculation Mode Convention

Some conventions, such as Canadian Government Bonds work differently with ActActICMA. Under this calculation any identified Stub period adopts an Act365F calculation in the fractional part. `Rateslib` has a specifically named day count convention for these bonds: 'ActActICMA_stub365f':

```
another_bond = FixedRateBond(
    effective=dt(2021, 1, 1),
    termination=dt(2022, 1, 15),
    front_stub=dt(2021, 2, 28),
    stub="LONGFRONTSHORTBACK",
    roll=31,
    fixed_rate=8.4,
    frequency="M",
    convention="ActActICMA_stub365f",
)
another_bond.cashflows(curve)
```

In this latter case the fraction is assessed as: $$ fraction = 1.0 + \frac{31/Jan/21 - 1/Jan/21}{365} * 12 = 1.986301369.. $$ And the cashflow is calculated as: $$ 1mm * 8.4\% / 12 * fraction = 13,904.11 $$

### QuantLib Speculation

If you assert that `quantlib` is using something similar to the "ActActICMA_stub365f" calculation but is using an 'Act360' convention instead of 'ACT365f' convention then the first stub cashflow is actually very close to \$14,000.

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.