lballabio / QuantLib

The QuantLib C++ library
http://quantlib.org
Other
5.26k stars 1.78k forks source link

Pass coupon pricer to the SwapRateHelper constructor for timing/convexity adjustments #1817

Open azarxa opened 11 months ago

azarxa commented 11 months ago

Quantlib allows for timing adjustments using the BlackIborCouponPricer class. However doing so returns non-zero NPVs even for spot starting vanilla swaps priced at fair (market input) rate. A vanilla swap at fair rate should PV to zero in all cases. The swap helpers in the curve construction need to incorporate the information of timing adjustments via addition of the coupon pricer used to compute them.

azarxa commented 11 months ago

SwapRateHelper also does not appear to take in a separate payment calendar & business day convention. This is relevant when bootstrapping a curve with swaps which need to have accrual days which are unmodified and can be holidays, but payment days are next business day.

quantinsights commented 11 months ago

Hi @lballabio, @azarxa - I am interested to contribute to Quantlib. Do you think, this is a good first issue?

lballabio commented 11 months ago

Hello @quantophile — yes, it should be.

lballabio commented 11 months ago

SwapRateHelper also does not appear to take in a separate payment calendar & business day convention. This is relevant when bootstrapping a curve with swaps which need to have accrual days which are unmodified and can be holidays, but payment days are next business day.

This should be already covered by passing Unadjusted as convention, isn't it? The accrual schedule will be on holidays and the payment days will be rolled to the next business day according to the passed calendar.

azarxa commented 11 months ago

SwapRateHelper also does not appear to take in a separate payment calendar & business day convention. This is relevant when bootstrapping a curve with swaps which need to have accrual days which are unmodified and can be holidays, but payment days are next business day.

This should be already covered by passing Unadjusted as convention, isn't it? The accrual schedule will be on holidays and the payment days will be rolled to the next business day according to the passed calendar.

I don't believe so. When building swaps using the Swap class with constituent IborLeg/FixedLegs: the schedule class used to build these legs takes in a schedule calendar/bdc, while the IborLeg/FixedLeg classes take in the payment calendar/bdc. In SwapRateHelper there's only a single calendar/bdc option and it seems to be used for both accruals & payments - so there's no way to distinguish them to reproduce swaps with bespoke schedule & payment dates in the bootstrapper. For example using Unadjusted can make the float payment dates fall on a holiday as well - which is incorrect. Building swaps using the Swap class is the only way I know to implement timing/convexity adjustments. Can you verify in case I'm mistaken in either of these points pls? Thanks.

arjanssuri commented 9 months ago

Hi, I just wanted to clarify if this issue is still open and if I could take a stab at pr? @lballabio , @azarxa

lballabio commented 9 months ago

Hello — yes, it's still open.

arjanssuri commented 9 months ago

How can I recreate the issue locally? @azarxa

azarxa commented 8 months ago

Create a swap using ql.Swap(ql.FixedRateLeg,ql.IborLeg) class where the ql.IborLeg has a ql.BlackIborCouponPricer with timing adjustment applied to it. Then value this swap off a curve constructed using SwapRateHelpers. Then there will be a discrepancy between the constructed and helper swap.