QuantLib icon indicating copy to clipboard operation
QuantLib copied to clipboard

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

Open sdacek opened this issue 1 year ago • 3 comments

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

sdacek avatar May 14 '24 14:05 sdacek

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.

boring-cyborg[bot] avatar May 14 '24 14:05 boring-cyborg[bot]

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] avatar Jul 14 '24 02:07 github-actions[bot]

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.

lballabio avatar Jul 15 '24 13:07 lballabio

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] avatar Sep 14 '24 01:09 github-actions[bot]

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

github-actions[bot] avatar Sep 28 '24 02:09 github-actions[bot]