OpenSourceRisk / Engine

Open Source Risk Engine
http://www.opensourcerisk.org
Other
484 stars 217 forks source link

Tenor basis yield segment regression in release 12 #243

Closed noonediesalone closed 3 months ago

noonediesalone commented 3 months ago

Hi,

In release 12 we're getting exception empty Handle cannot be dereferenced when building a tenor basis swap. It's from here TenorBasisSwapHelper::setTermStructure when setDiscountRelinkableHandle_ is false and discountHandle_ is empty. Example test case is for !payIndexON && recIndexON which leaves the variable false.

Attaching replication case for convenience: ISSUE_TENORBASIS.zip

Use ore_r12.xml to replicate. Conventions and curve config XML is slightly changed, so for previous version please use ore_r11.xml.

Regards, Laurentiu.

noonediesalone commented 3 months ago

This can be worked around by setting a discount curve in the yield curve definition, e.g. <DiscountCurve>EUR-ESTR</DiscountCurve> on definition of curve which only has TenorBasis segment.

pcaspers commented 3 months ago

This is case 2 in (see tenorbasisswap.cpp)

       /* depending on the given curves we proceed as outlined in the following table

       x = curve is given
       . = curve is missing

       Case | PAY | REC  | Discount | Action
       =========================================
         0  |  .  |   .  |    .     | throw exception
         1  |  .  |   .  |    x     | throw exception
         2  |  .  |   x  |    .     | imply PAY = Discount
         3  |  .  |   x  |    x     | imply PAY
         4  |  x  |   .  |    .     | imply REC = Discount
         5  |  x  |   .  |    x     | imply REC
         6  |  x  |   x  |    .     | imply Discount
         7  |  x  |   x  |    x     | throw exception

        Overnight(ON) vs. IBOR CASE:
        Case 2 from above:
            if REC (given) is ON, REC = Discount = OIS, imply PAY only
            else : PAY (missing) is ON, imply PAY = Discount = OIS (as before)

        Case 4 from above:
            if PAY (given) is ON, PAY = Discount = OIS , imply REC only
            else : REC (missing) is ON, then imply REC = Discount = OIS (as before)

        */

I.e. the expected behavior is that the overnight curve (EUR-ESTER in your example) is used as the discounting curve.

This was not implemented correctly, I'll submit a fix to our internal dev branch.

The workaround is as you mention, i.e. specify the DiscountCurve explicitly in the curve config and set it to the overnight curve. Is that workaround sufficient for you or do you think we should patch the release with a fix for this?

noonediesalone commented 3 months ago

Hi Peter, thank you for comments, the workaround looks good, no immediate patch is needed.

noonediesalone commented 3 months ago

I'm reopening this issue because PAR Sensitivity fails with TBS quotes and there is no real workaround, so probably this needs to be patched. Have done a quick fix here https://github.com/OpenSourceRisk/Engine/commit/2d434299fcaf1a489c5518ada3b9a0c429b87fdb but needs to be integrated from a bigger picture.

In the same spirit, here is the replication package: ISSUE_PAR_SENSI_TENORBASIS.zip

Running ore_r12.xml throws with null ptr access Boost assertion failed: px != 0 while ore_r11.xml works. And with the patch both give same results (only that in release 12 is much faster 😄 ).

pcaspers commented 3 months ago

Thanks - your patch looks fine, we'll run some checks on our side and probably release a patch for both issues soon.

pcaspers commented 3 months ago

We pushed the fixes to master. Would you be able to check if everything works from your point of view? We will then do a point release next week.

noonediesalone commented 3 months ago

Thank you again. Both test cases work fine now. Curve built with or without setting discount on yield curve is the same, as expected.