QuantLib icon indicating copy to clipboard operation
QuantLib copied to clipboard

Unexpected behavior in forwardrateagreement

Open tleitch opened this issue 8 years ago • 5 comments

While looking for more general way to control curve build I looked to strip a curves forward rates to perturb them and rebuild the curve to get a tangent plane in an orthogonal basis (fra's). What I found was that even though there is a maturityDate provided, the only forward rate computed is the one corresponding to the IBOR index. So if you input a maturity of, say 6x12 mo and use a 3mo IBOR curve, you will get the 6x9 mo FRA. A work around is to use 6mo IBOR index, but this is an issue if you try to create a "generic" FRA to use as a basis and you would also need to account for any 3mo / 6mo basis curve if you were hedging off the 3mo.

At line 46 of forwardrateagreement.cpp we have:

    forwardRate_ = InterestRate(index->fixing(fixingDate),
                                index->dayCounter(),
                                Simple, Once);

Which has no dependency (in the call or prior to it) on maturityDate. Was this the authors intent?

tleitch avatar Oct 22 '16 16:10 tleitch

I guess that this was the intent, since by passing an IBOR index instance, the tenor is specified (and if this is the case, the maturity date shouldn't have been exposed as a constructor argument).

To calculate a basis for a given forward between the 3m and 6m curves, I think you'll need two instances of the 6m IBOR index; you can pass the 3m curve to one and the 6m curve to the other. Let me know if this works.

lballabio avatar Nov 10 '16 16:11 lballabio

If this is the correct behaviour, then the documentation is wrong. It states:

In fact, the FRA settles and expires on the valueDate, not on the (later) maturityDate. It follows that (maturityDate - valueDate) is the tenor/term of the underlying loan or deposit

But (maturityDate - valueDate) is not the tenor. It's completely unrelated to the tenor.

And yet it is used in various places:

  1. In calculating the cash value of the payoff for a defined strike rate (strike in the ForwardRateAgreement constructor)

  2. In calculating the NPV by compounding the fair forward rate and discounting rate (in ForwardRateAgreement::spotValue)

  3. In whatever it is that Forward::forwardValue is doing

  4. In whatever it is that Forward::impliedYield is doing

These methods therefore presumably return various shades of nonsense.

Can i suggest that either:

  1. The current behaviour is reclassified as a bug, and fixed so that the specified maturity date is used (perhaps adding a second constructor which takes the maturity date from the index tenor)

  2. The documentation is updated, and an assertion is added to the constructor to reject any maturity date which does not correspond to the index tenor

To me, the first option seems preferable, as it provides a small but useful capability which is currently absent from QuantLib.

I would be happy to submit a PR with the changes. Particularly if the change is for the first option!

tomwhoiscontrary avatar Mar 14 '19 18:03 tomwhoiscontrary

Thanks for your patience. Yes, I agree. I think we should deprecate the current constructor taking both a maturity and an index, and add a couple of other constructors that provide consistent information. One should take the value and maturity date but not the index (it will probably need some additional information, such as the day-count convention, that it currently takes implicitly from the index). The other should take the index, but not the maturity date (which, as you say, will be taken from the index).

lballabio avatar Apr 30 '19 14:04 lballabio

This is a great idea. Would allow users much more flexibility in controlling the front end of the curve, using instruments such as 'tomorrows FRA,' which fixes T+1, values T+3, and matures according to the index specifications. Basically, would need the constructor to have either a fixing or value date, and an index. If Tom can't get around to it (sounds like he might have a pull request ready to go already?), I'll take a stab at adding the new constructor at the minimum.

mdelmedico avatar May 08 '19 04:05 mdelmedico

@mdelmedico I haven't had a chance to work on this, i'm afraid, so go ahead!

tomwhoiscontrary avatar May 08 '19 09:05 tomwhoiscontrary

Hi @lballabio is this topic still actual? I saw that since September 2019 several deprecated members have been removed from class ForwardRateAgreement but if I am not wrong there is still some work to be done on the constructors. If the topic is still open I can try to work on it.

jakeheke75 avatar Jan 27 '23 07:01 jakeheke75

Sure, please go ahead.

lballabio avatar Jan 27 '23 08:01 lballabio

The more i think about this, the less sure about anything i am. In particular, the less sure i am that the current behaviour is wrong!

It might be worth thinking about the symmetry between FRAs and single-period swaps. It is possible to construct a five-month single-period swap on a six-month IBOR index. The fixing will be a normal six-month index fixing, based on a notional deposit of six months term, but the cashflow will be given by that rate compounded over five months. At least, according to QuantLib - would actual market practice be to use a rate interpolated between the three- and six-month fixings? Anyway, isn't this what the current implementation does?

For the actual ForwardRateAgreement class, perhaps the safest thing is just to remove the explicit maturity date, and always use value date plus index tenor. If we had MakeForwardRateAgreement, maybe we could keep the current behaviour, exposed via a withCustomCompoundingPeriod method which would make it really explicit what is going on. But i think it's too error-prone to be a constructor.

Now, @tleitch's original problem (which i have also had) was trying to extract clean forward rates from a curve and then (perhaps after some fiddling) use them to build a new curve. FRAs were the tool chosen to do this. But i wonder if a better solution is to put aside FRAs and provide a better tool. If we had something like a ZeroRateFictionalInstrument and a ZeroRateFictionalInstrumentRateHelper, which had arbitrary start and end dates, we could use those without having to reconcile that flexibility with actual market practice for a real instrument. Does that make any sense?

tomwhoiscontrary avatar Feb 13 '23 17:02 tomwhoiscontrary

@mdelmedico Isn't "tomorrow's FRA" just a normal FRA whose fixing date is tomorrow? So the maturity date is the value date plus the index tenor; there's no weird custom maturity date.

tomwhoiscontrary avatar Feb 13 '23 17:02 tomwhoiscontrary

That’s correct Tom. The whole reason I brought it up is I think I’m trying to do something similar by using explicit FRAs to control the front end of the curve.

For example, the way the curve is interpolated between today’s cash fixing and the next point (or two I guess if you are using tomorrows FRA and then say a future point like H23), you end up with this funky wobbly shape because of the interpolation scheme starting from node 0. Think of a curve where the first two points are extremely upward sloping but the first derivative of node 0 is locked to zero. In this case, you will have a very flat term structure for the interpolation results for the first few days until the curvature can kick in. Furthermore the interpolation will overshoot in the area near the front IMM contract which means you will then have an aggressive dip to compensate before the second IMM contract. The net result is that you’ve simply mismarked a whole strip of fixings.

Ideally we would be able to control the node 0 derivative in a more direct way. This is also the reason so many old school systems had to “pull out” the front IMM contract from the curve build a few days before it expired - the curve couldn’t converge with that funky front slope (or more specifically the lack thereof).

There’s probably a better way to do this but so far the only way I’ve found to get around it is to explicitly control the FRAs in a tighter fashion (so not in constant maturity space, but rather at explicit fixing/value dates). Hence that type of constructor using a fixing or value date (and inferring the maturity from the index) seems to allow us those extra degrees of freedom.

-Mike

On Mon, Feb 13, 2023 at 11:17 Tom Anderson @.***> wrote:

@mdelmedico https://github.com/mdelmedico Isn't "tomorrow's FRA" just a normal FRA whose fixing date is tomorrow? So the maturity date is the value date plus the index tenor; there's no weird custom maturity date.

— Reply to this email directly, view it on GitHub https://github.com/lballabio/QuantLib/issues/154#issuecomment-1428337008, or unsubscribe https://github.com/notifications/unsubscribe-auth/AH64OZREOAQMPXF26RJOVXLWXJUBXANCNFSM4CTXUJXQ . You are receiving this because you were mentioned.Message ID: @.***>

mdelmedico avatar Feb 14 '23 04:02 mdelmedico

@mdelmedico This sounds like a very familiar problem. We have been struggling with getting the front of the curve right for Euribor - the crazy wiggles mean that if we build with spot-starting instruments, we get bad prices for IMM-starting instruments, and vice versa. Meanwhile, we can feed the same market data into another library which uses a different curve construction method, and get something smooth which gives reasonable prices; the root of the difference seem to be that it fits a very different shape in the span between the deposit and the first instrument, which lets everything later on line up smoothly.

I don't think we've tried sticking in additional synthetic instruments at the front yet. In your case, could you do it with DepositRateHelpers?

tomwhoiscontrary avatar Feb 14 '23 14:02 tomwhoiscontrary

@mdelmedico @tomwhoiscontrary not sure if this is related to what you discuss above

https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3640517

In any case it might be worth checking out these extensions which allow to use the very short end of the curve

[0, maturity of first cash instrument representing the fixing]

to smooth longer-term forwards.

pcaspers avatar Feb 14 '23 14:02 pcaspers

@pcaspers That's really interesting, thanks! So the components of the solution were (1) interpolation in the SimpleZeroYield domain (2) global rather than iterative bootstrap, (3) extra pillar dates at the start dates of the serial FRAs, and (4) an additional error term based on the linearity of FRA rates in the region between the FRAs and the swaps.

The last point in particular is subtle. You aren't just working out some synthetic FRA rates and adding the synthetic FRAs as helpers . Firstly, you are adding pillar dates before the real FRAs, not after. But more importantly, additionalErrors judges the implied quotes of the intermediate synthetic FRAs against an interpolation between the implied quotes for the first and last ones, so the absolute rates aren't anchored anywhere in particular, but the second derivative is constrained to be zero!

The other library we use has at least one and a half of these features - a global optimiser, and pillar dates at the FRA start dates rather than the end. My gut feeling is that the latter are the crucial thing, but they are not really possible without the former.

tomwhoiscontrary avatar Feb 14 '23 18:02 tomwhoiscontrary

@tomwhoiscontrary that's a good summary! The interpolation in SimpleZeroYield is obviously not important for the method as such, it was just added to mimic what Bloomberg is doing.

pcaspers avatar Feb 16 '23 18:02 pcaspers

@tomwhoiscontrary I don't think DepositRateHelpers allow you to specify a start date for the deposit, but they do allow for a tenor input. The easiest way I can think to trick the curve into taking explicitly marked non-standard FRAs is to back out the required zero rates at the FRA effective and maturity dates, then use ZeroCouponBond objects to feed the information into the curve that way. It's the same idea (I think - if were talking about some external fitting/smoothing algorithm to generate synthetic FRAs to then feed into the curve on a 2nd pass bootstrap) as what @pcaspers was suggesting, but might allow for some more freedom / user control for the curve construction process. Apologies in advance if I totally misinterpreted the paper, as I only skimmed it quickly.

mdelmedico avatar Mar 01 '23 20:03 mdelmedico