Simple Zero Curve Calibration (Deposit+Futures+Swap)

First of all congratulation on your library! It’s very well written and powerful.

My problem is about the csv files needed for calibration.
I’m trying to replicate a simple zero rate curve calibration using Deposit+Futures+Swap made on excel sheets, but Strata refuses to insert the Futures quotes.

Futures quotes are in the form 1-L.

My quotes.csv entries are in the form
2014-01-22,OG-Future,Ibor-USD-LIBOR-3M-Mar15,SettlementPrice,0.998452
and the respective calibration.csv entries
USD-Disc,2M,OG-Future,Ibor-USD-LIBOR-3M-Mar15,IFU,USD-LIBOR-3M-Quarterly-IMM,2M+3,

When trying to load the csv, Strata complains about not finding market data for futures.
Unable to find any example in Strata src about using futures for calibration, I honestly don’t know how to insert them nor understand where the problem lies.

Thanks, glad you like it!

The field name of the market data doesn’t match between the two files. In quotes.csv it is SettlementPrice and in calibration.csv it’s IFU. Try changing those fields to have the same value.

Regards,
Chris

Just to add to this, the unique key has three parts

  • Symbology - the naming scheme
  • Ticker - the name within the naming scheme
  • Field Name - the specific field, ‘MarketValue’, ‘SettlementPrice’ etc

All three need to match between the two files.

I think the problem is actually that the field name is missing from the calibrations.csv file. Try adding ‘SettlementPrice’ between the ticker and ‘IFU’ in the calibrations file.

Regards,
Chris

Thank you for the fast reply! You were right, the field name was missing due to distraction.
But the problem is still not resolved.

The entry for futures in quotes.csv
2005-04-12,OG-Future,Ibor-USD-LIBOR-3M-Jun08,SettlementPrice,0.944962
and in calibration.csv
USD-Disc,3M,OG-Future,Ibor-USD-LIBOR-3M-Jun08,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,3M+3,

The error thrown is the same:
Market data not found for identifier ‘QuoteId{standardId=OG-Future~Ibor-USD-LIBOR-3M-Mar08, fieldName=SettlementPrice, observableSource=None}’ of type ‘QuoteId’

The tickers in the CSV files are for Jun08. The ticker in the error message is for Mar08. Is there a Mar08 line in the quotes.csv file?

There was but then deleted from one of the csv during manual adjustments…

Sorry for bothering you, but a new error arises now: array of x-value must be sorted and unique.
The problem is that I don’t know how to tell Strata via csv about futures.
For example, if i have for the future Dec06

  • valuation date: 2005-04-12
  • settlement date: 2007-03-20
  • end date: 2007-06-20
    how the entry must look like? For now it is:
    USD-Disc,24M,OG-Future,Ibor-USD-LIBOR-3M-Dec06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,24M+3,

For completeness I paste here the csv:
USD-Disc,ON,OG-Ticker,USD-OIS-ON,MarketValue,DEP,USD-Deposit-T,1D,
USD-Disc,TN,OG-Ticker,USD-OIS-TN,MarketValue,DEP,USD-Deposit-T,2D,
USD-Disc,1W,OG-Ticker,USD-OIS-1W,MarketValue,DEP,USD-Deposit-T,1D,
USD-Disc,2W,OG-Ticker,USD-OIS-2W,MarketValue,DEP,USD-Deposit-T,1D,
USD-Disc,1M,OG-Ticker,USD-OIS-1M,MarketValue,DEP,USD-Deposit-T,1M,
USD-Disc,2M,OG-Ticker,USD-OIS-2M,MarketValue,DEP,USD-Deposit-T,2M,
USD-Disc,3M,OG-Ticker,USD-OIS-3M,MarketValue,DEP,USD-Deposit-T,3M,
USD-Disc,3M,OG-Future,Ibor-USD-LIBOR-3M-Mar05,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,3M+3,
USD-Disc,6M,OG-Future,Ibor-USD-LIBOR-3M-Jun05,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,6M+3,
USD-Disc,9M,OG-Future,Ibor-USD-LIBOR-3M-Sep05,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,9M+3,
USD-Disc,12M,OG-Future,Ibor-USD-LIBOR-3M-Dec05,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,12M+3,
USD-Disc,15M,OG-Future,Ibor-USD-LIBOR-3M-Mar06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,15M+3,
USD-Disc,18M,OG-Future,Ibor-USD-LIBOR-3M-Jun06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,18M+3,
USD-Disc,21M,OG-Future,Ibor-USD-LIBOR-3M-Sep06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,21M+3,
USD-Disc,24M,OG-Future,Ibor-USD-LIBOR-3M-Dec06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,24M+3,
USD-Disc,2Y,OG-Ticker,USD-IRS3M-2Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,2Y,
USD-Disc,3Y,OG-Ticker,USD-IRS3M-3Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,3Y,
USD-Disc,4Y,OG-Ticker,USD-IRS3M-4Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,4Y,
USD-Disc,5Y,OG-Ticker,USD-IRS3M-5Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,5Y,
USD-Disc,7Y,OG-Ticker,USD-IRS3M-7Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,7Y,
USD-Disc,10Y,OG-Ticker,USD-IRS3M-10Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,10Y,
USD-Disc,12Y,OG-Ticker,USD-IRS3M-12Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,12Y,
USD-Disc,15Y,OG-Ticker,USD-IRS3M-15Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,15Y,
USD-Disc,20Y,OG-Ticker,USD-IRS3M-20Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,20Y,
USD-Disc,25Y,OG-Ticker,USD-IRS3M-25Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,25Y,
USD-Disc,30Y,OG-Ticker,USD-IRS3M-30Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,30Y,

OK, this is harder than it should be for you, we’ll have to look to make it simpler.

When we load the file, each line gets resolved to a specific date. The problem is that the 3 month future is resolving to a date before the 3 month OIS. Or that the 24 month future is resolving to a date after the 2 year swap.

While it is not ideal, right now you will have to reorder those lines until the order is correct. Clearly we need to add some sorting as otherwise futures like this are really tricky to get right.

ie. this might fix it:

USD-Disc,21M,OG-Future,Ibor-USD-LIBOR-3M-Sep06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-IMM,21M+3,
USD-Disc,2Y,OG-Ticker,USD-IRS3M-2Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,2Y,
USD-Disc,24M,OG-Future,Ibor-USD-LIBOR-3M-Dec06,SettlementPrice,IFU,USD-LIBOR-3M-Quarterly-  IMM,24M+3,
USD-Disc,3Y,OG-Ticker,USD-IRS3M-3Y,MarketValue,IRS,USD-FIXED-6M-LIBOR-3M,3Y,

but since the problem might be with the order of the 3 month entries, or the 24 month entries, or it could be a problem with both, and there is no way to tell :cry: you’ll have to try the three combinations until it works.

Thanks a lot for the clarification.

I tried inverting last deposit with first future, last future with first swap and both, but the error still remains.
I also tried moving the 2Y swap up by 2 rows (maybe Strata is translating the 21M+3 future as a 24M trade) but with no luck.

EDIT: via debug, I found that the x array error is always generated in the 15th entry of the csv file. Both in case it is the first swap or the last future.
Deleting both the last future and first swap, the error generated changes in “Unable to find index curve: USD-LIBOR-3M”, which is unusual because that label is not present in any csv file. I only have the curve “USD-Disc” in the group. Maybe it is impossible for Strata to calibrate the zero rate discount curve alone?

Glad you found which Future/Swap combination is causing the problem. We need to apply some sorting at our end to avoid this problem.

The new error “Unable to find index curve: USD-LIBOR-3M” is occurring as there needs to be a forward curve defined for the USD-LIBOR-3M index in order to price the swaps. Without that curve, the swap cannot be priced, and the calibration cannot happen. You are also going to need a forward curve for the USD-FED-FUND overnight index.

I’m assuming that what you want to do is calibrate a single curve for use both as a discount curve and a forward curve. To do this, you need something like the following files:

calibration.csv
(as you have defined it)

groups.csv
Group Name,Curve Type,Reference,Curve Name
USD-DSCON-LIBOR3M,Discount,USD,USD-Disc
USD-DSCON-LIBOR3M,Forward,USD-FED-FUND,USD-Disc
USD-DSCON-LIBOR3M,Forward,USD-LIBOR-3M,USD-Disc

settings.csv
Curve Name,Value Type,Day Count,Interpolator,Left Extrapolator,Right Extrapolator
USD-Disc,Zero,Act/365F,Linear,Flat,Flat

Note how the groups.csv file defines three entries all with the same group name “USD-DSCON-LIBOR3M”. There is one entry for each of the three curves we need - USD discount curve, USD-FED-FUND index forward curve and USD-LIBOR-3M index forward curve. And that all three point at the same curve name “USD-Disc” but use the “Curve Type” and “Reference” fields to specify whether they are discount or forward curves.

Your explanation is really enlightening!
Now it runs without problem and prints a set of discount factors.

Still remains the problem between futures and swaps. I resolved deleting the 2Y swap, but it can not be the solution.
Using Eclipse debug, i found that the 24M+3 future has an yearfraction of 2.99, obviously wrong.

OK, so it looks like the calibration definition is probably wrong.

The string “3M+3” means that the code will take the 3rd future starting from a point 3 months after the valuation date. You probably want something like “7D+1” for the 3 month future, “7D+2” for the 6 month future and so on.

I didn’t know the meaning of time strings for futures. Thanks a lot. Now the picture is almost complete.

Only one thing remaining. Repeating the process for an EUR discount curve (and using Eclipse’s debug) another x array error appears. This time is on the first 2 entries: ON and TN deposit.
It seems they have the same yearfraction (0.019178082191780823, obviously wrong), but in the parameters metadata the tenor period is correctly stored at 1 day and 2 days respectively.

The first lines of the csv are
EUR-Disc,ON,OG-Ticker,EUR-ON,MarketValue,DEP,EUR-Deposit,1D,
EUR-Disc,TN,OG-Ticker,EUR-TN,MarketValue,DEP,EUR-Deposit,2D,
EUR-Disc,1W,OG-Ticker,EUR-1W,MarketValue,DEP,EUR-Deposit,7D,
EUR-Disc,2W,OG-Ticker,EUR-2W,MarketValue,DEP,EUR-Deposit,14D,

The deposit code adds calendar days, not business days. No doubt 1D and 2D are interacting with a holiday or weekend and resulting in the same date.

Honestly it seems worse than expected. The calibration entries are these ones:

EUR-Disc,ON,OG-Ticker,EUR-ON,MarketValue,DEP,EUR-Deposit,1D,
EUR-Disc,TN,OG-Ticker,EUR-TN,MarketValue,DEP,EUR-Deposit,2D,

and the valuation date is set to 2008-3-18. Looking at the parameters array in debug mode, the corresponding parameter metadata “period” is correct, but “date” is 2008-3-25 for both, clearly wrong since they are overnight and tomorrow night. How can I tell Strata the correct expiration date?

EDIT: I found that ON and TN have unique Deposit conventions. Sorry for bothering, but it could be useful to have a little manual for building a correct csv.

Agreed, we need a lot more docs on those file formats. Have you got your code working now?

Yes, thank you for the support.
Now the calibration seems to work fine. There are some difference at the 4th/5th decimal for periods over 1Y and I’m looking for the cause.

As a side note, I’m trying to display the calibrated curve for standard dates (such as ON, 1W, 1Y and so on) but I can’t find a direct method for calculating an adjusted YearFraction.
For now I’m doing something like this (1Y in Act/365, VAL_DATE=2008-3-18):

LocalDate current = AdjustableDate.of(
----VAL_DATE.plus(Period.ofYears(1).minusDays(1)),
----BusinessDayAdjustment.of(
--------BusinessDayConventions.FOLLOWING,
--------HolidayCalendarIds.EUTA
----)
).adjusted(refData);

double yearFraction = DF.relativeYearFraction(current);

Is there a more direct approach? Something like

yearFraction = YF(VAL_DATE, “1Y”, “Act/365”, BusinessDayConvention, refData);

A BusinessDayAdjustment has methods on it. So, your code would be something like this:

BusinessDayAdjustment bda = ...
yf = bda.adjust(valDate.plusYears(1)), refData);

(which is what the code in AdjustableDate.adjusted actually does)

On the deposit conventions, I’m looking to see if I can make a change in that area based on your feedback. thanks

New names for deposit conventions
https://github.com/OpenGamma/Strata/pull/1118

Again on this topic, I did different calibrations with different data and the resulting curve from Strata is very different from the real curve (something like E-4 or E-3), especially from the futures section.