-2

I'm creating Canadian fixed rate bond objects and noticed that for bonds with a short first coupon, the first cashflow is wrong if using the ActualActual(ActualActual.Bond) day counter, but correct for the rest. This is because with a short stub, Canadian bonds calculate accrued using the Actual365Fixed(Actual365Fixed.Canadian) day counter. The problem is, Canadian bonds only use this for short coupon periods. Therefore, the rest of the cashflows would be incorrect using the Actual365Fixed(Actual365Fixed.Canadian) day counter.

Is there a day counter that accounts for this that I'm unaware of? This is a semi annual bond, with an issue date April 3rd, 2020 and maturity Sept. 1, 2025.

CashFlows with ActualActual(ActualActual.Bond) day counter: \
[(Date(1,9,2020), 0.20516304347826253),
 (Date(1,3,2021), 0.24999999999999467),
 (Date(1,9,2021), 0.24999999999999467),
 (Date(1,3,2022), 0.24999999999999467),
 (Date(1,9,2022), 0.24999999999999467),
 (Date(1,3,2023), 0.24999999999999467),
 (Date(1,9,2023), 0.24999999999999467),
 (Date(1,3,2024), 0.24999999999999467),
 (Date(1,9,2024), 0.24999999999999467),
 (Date(1,3,2025), 0.24999999999999467),
 (Date(1,9,2025), 0.24999999999999467),
 (Date(1,9,2025), 100.0)]

Cashflows with Actual365Fixed(Actual365Fixed.Canadian) day counter:\
[(Date(1,9,2020), 0.20684931506849136),
 (Date(1,3,2021), 0.24794520547946064),
 (Date(1,9,2021), 0.24999999999999467),
 (Date(1,3,2022), 0.24794520547946064),
 (Date(1,9,2022), 0.24999999999999467),
 (Date(1,3,2023), 0.24794520547946064),
 (Date(1,9,2023), 0.24999999999999467),
 (Date(1,3,2024), 0.24999999999999467),
 (Date(1,9,2024), 0.24999999999999467),
 (Date(1,3,2025), 0.24794520547946064),
 (Date(1,9,2025), 0.24999999999999467),
 (Date(1,9,2025), 100.0)]

Actual cashflows of a Canadian Fixed bond with a short first stub:\
[(Date(1,9,2020), 0.20684931506849136),
 (Date(1,3,2021), 0.24999999999999467),
 (Date(1,9,2021), 0.24999999999999467),
 (Date(1,3,2022), 0.24999999999999467),
 (Date(1,9,2022), 0.24999999999999467),
 (Date(1,3,2023), 0.24999999999999467),
 (Date(1,9,2023), 0.24999999999999467),
 (Date(1,3,2024), 0.24999999999999467),
 (Date(1,9,2024), 0.24999999999999467),
 (Date(1,3,2025), 0.24999999999999467),
 (Date(1,9,2025), 0.24999999999999467),
 (Date(1,9,2025), 100.0)]
Jacob
  • 13
  • 4
  • Please repeat [on topic]( https://stackoverflow.com/help/on-topic) and [how to ask]( https://stackoverflow.com/help/how-to-ask) from the [intro tour](https://stackoverflow.com/tour). If I understand the general flow of this, you want us to read off-site (not acceptable) images (not acceptable) of your code, understand the day-counting concept you need, and recommend an off-site package (off topic) that will solve your problem. Instead, explain the *functional* problem you have; make sure that your request is on topic. "Is there a package/function to do this?" is off-topic here. – Prune Jul 14 '20 at 17:20
  • The only reason links to images were in the question is because that's the only way to upload as a new user, they've since been deleted. As for the rest, I am not looking for an off-site package, but a day count object that takes into account the Canadian Bond conventions for short stubs. The pictures showed the differences in the cashflows when using the two different day counts. – Jacob Jul 14 '20 at 18:18

2 Answers2

2

There's no single day counter that does that, but you can build a correct bond with a bit of work. What you'll have to do is:

  • build a bond bond1 with act/365 Canadian day count, extract its coupons and keep the first, as in first = bond1.cashflows()[0];

  • build a bond bond2 with act/act day count, extract its coupons and discard the first and the redemption, as in rest = bond2.cashflows()[1:-1];

  • put the coupons together and build the final bond as an instance of the generic Bond class, as in:

    bond = ql.Bond(settlement_days, calendar, issue_date, [first]+rest)
    

    (the redemption will be re-added by the Bond constructor).

Of course, if you find yourself doing this a lot of times, you can write a function to do that. (Or, if you're comfortable with changing the underlying C++ library, you can create a specific bond subclass and export it to Python.)

Luigi Ballabio
  • 4,128
  • 21
  • 29
  • Thank you Luigi, I really appreciate the quick and clear response! I would like to create a day counter convention to address the Canadian bond conventions, as using the Bond class loses a lot of the functionality that comes with the FixedRateBond class (i.e. the periodicity). I wouldn't want to make this a local C++ fork however. Would you be open to accepting a new ActualActual convention for Canadian bonds? – Jacob Jul 15 '20 at 14:15
  • I'm open, but I'm not sure a day counter as such is going to be able to differentiate between short stubs and regular coupons. It's probably easier to add an optional argument to FixedRateBond taking a different day counter for the first coupon. – Luigi Ballabio Jul 15 '20 at 21:44
  • Thanks! And I agree, it's a more elegant solution. Will create a pull request when done. – Jacob Jul 16 '20 at 20:38
0

The way I did this was to define a new day count convention, call it "actacticma_stub365f" for want of a better name.

This convention behaves in the same way as "actacticma" except if the period is stub in which case it branches to work on a canadian act365f mode.

Attack68
  • 4,437
  • 1
  • 20
  • 40