lballabio / QuantLib

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

LatestRelevantDate for OISRateHelper and SwapRateHelper should likely depend on the presence/absence of an exogenous discount curve. #1970

Closed sdacek closed 5 days ago

sdacek commented 4 months ago

For a Fixed-Floating swap, the potential latest relevant dates for a given curve are the latest date needed to project a fixing and the the latest payment date of either leg of the swap. However, which date is chosen should probably depend on what curves are being implied from the swap and its quote. If the swap is being used to only imply the projection curve (i.e. there is a separate discount curve), then the latestRelevantDate of this swap to the implied termstructure is the last date needed to project a fixing, as the payment dates discount factors are covered by the exogenous discount curve. When the implied curve is being used both as the discounting curve and the projection curve, then the maximum of both potential dates is the latestRelevantDate.

latestRelevantDate for SwapRateHelper is currently defined as

   ext::shared_ptr<IborCoupon> lastCoupon =
              ext::dynamic_pointer_cast<IborCoupon>(swap_->floatingLeg().back());
          latestRelevantDate_ = std::max(maturityDate_, lastCoupon->fixingEndDate());

which I believe assumes an exogenous discount curve (or zero payment delay with swap periods aligning to fixing periods), since the leg payment dates are not taken into account.

On the other hand, latestRelevantDate for OISRateHelper is currently defined as

      Date lastPaymentDate = std::max(swap_->overnightLeg().back()->date(),
                                        swap_->fixedLeg().back()->date());
        latestRelevantDate_ = std::max(maturityDate_, lastPaymentDate);

which I believe implies that the discounting curve is the same as the projection curve.

Should we consider updating the logic on both ratehelpers to be

if (hasExogenousDiscountCuve) {
    latestRelevantDate_ = latestProjectionDate;
} else {
    latestRelevantDate_ = lastPaymentDate; // assuming this is greater than the latestProjectionDate
}

where latestProjectionDate is the latest date needed to project a fixing and latestPaymentDate is the latest payment date of either leg?

The current implementation also always takes the maximum of these dates with the swap MaturityDate_. I am not sure if this is necessary as it does not directly factor into either of the above cases, but can be preserved.

Another option is to value the swap using a fictitious termstructure object and track what the latest date requested of the curve was. This approach saves any ratehelper specific logic at the expense of an extra valuation for each ratehelper.

Please let me know your thoughts, happy to send over a pr

boring-cyborg[bot] commented 4 months ago

Thanks for posting! It might take a while before we look at your issue, so don't worry if there seems to be no feedback. We'll get to it.

github-actions[bot] commented 2 months ago

This issue was automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment, or this will be closed in two weeks.

lballabio commented 2 months ago

Thanks! Yes, this could be a refinement. I think the current logic is a tradeoff: it has simpler logic but sometimes can place the node a few days after the real last relevant date.

github-actions[bot] commented 2 weeks ago

This issue was automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment, or this will be closed in two weeks.

github-actions[bot] commented 5 days ago

This issue was automatically closed because it has been stalled for two weeks with no further activity.