gh-2172 fix bond yield over partial coupon periods - #10
Merged
pcaspers merged 1 commit intoAug 22, 2026
Merged
Conversation
Use the right compounding over short first and final periods, and make duration and convexity match the price they come from. Adds tests for long first coupons, quasi-periods, and late redemption.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This builds on your
yield_overhaulbranch and picks up lballabiogh-2172.The problem
Both hybrid conventions are positional.
SimpleThenCompoundeddiscounts thefirst interval simply and compounds the rest.
CompoundedThenSimplecompoundsup to the last flow and discounts the final interval simply. When a bond
settled inside a partial period, neither rule landed on the interval the
convention names, so the yield came back wrong.
Duration and convexity had a related problem. They were not derivatives of the
price function that priced the bond, so a bump-and-reprice did not tie out to
the analytic numbers. They now come off the same stepwise discount factors as
the price.
How I checked it
Yields go against something independent, not against the code:
Sensitivities go against central finite differences of the dirty price at 1bp.
The late-redemption bond is the one that earns its keep. Moving the redemption
three days past the final coupon leaves a genuinely short terminal interval,
where simple and compounded actually part ways: modified duration is 0.249076
under STC and 0.248319 under CTS. Without that gap the sensitivity tests would
pass on a broken CTS implementation.
Full suite is green.
Two things I left alone
bps(leg, InterestRate)still discounts through aFlatForwardcurve, so itdisagrees with npv, duration and convexity under both hybrid conventions.
Fixing it changes public behaviour, so I would rather you make that call.
CashFlows::npvand the newcashFlowResultsshare the convention helpers butkeep separate loops. Merging them puts derivative work on the yield solver's
hot path, which seemed a bad trade.