QuantLib icon indicating copy to clipboard operation
QuantLib copied to clipboard

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

Open azarxa opened this issue 2 years ago • 9 comments

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 avatar Oct 24 '23 16:10 azarxa

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.

azarxa avatar Oct 25 '23 16:10 azarxa

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

quasar-chunawala avatar Nov 07 '23 06:11 quasar-chunawala

Hello @quantophile — yes, it should be.

lballabio avatar Nov 07 '23 08:11 lballabio

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.

lballabio avatar Nov 07 '23 08:11 lballabio

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.

azarxa avatar Nov 07 '23 09:11 azarxa

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

arjanssuri avatar Jan 02 '24 02:01 arjanssuri

Hello — yes, it's still open.

lballabio avatar Jan 04 '24 09:01 lballabio

How can I recreate the issue locally? @azarxa

arjanssuri avatar Jan 05 '24 00:01 arjanssuri

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.

azarxa avatar Jan 09 '24 18:01 azarxa