Skip to end of metadata
Go to start of metadata

How yields curves are specified

Yield curves are specified using two structures: a yield curve definition and a yield curve specification builder configuration. The yield curve specification builder configuration is a data structure that specifies a set of market instruments (securities) that can be used as nodal points for the construction of a yield curve. It is intended to be fairly exhaustive and provides a great deal of overlap across the asset classes that it supports. The intention is that this structure then becomes a 'menu' that the creator of a yield curve definition can choose from, making it much easier to quickly specify and change curve definitions, than if the instrument codes of the underlying instruments had to be entered by hand each time.

Dynamic

Because some common constituents of yield curves are specified relative to fixed dates, curve definitions can often change over time. The biggest example of this is Interest Rate Futures. Because they are specified with a fixed expiry, as time moves forward over days, weeks and months, the original futures the user wanted move towards the start of the yield curve and eventually expire. In practice, the user typically has to remove futures from their curve definitions as they approach the short end of the curve (where there are shorter dated instruments such as cash, deposit or libor rates), and add new futures to the end of the middle section of the curve. To reduce the amount of manual work in this kind of management, each point in the yield curve specification builder configuration is capable of dynamically producing an Identifier based on the curve date, and the tenor offset of the nodal point into the curve. This means that the Identifiers produced vary over time.

Below is an example of a yield curve specification builder configuration containing mock identifiers to give you an idea:

Tenor LIBOR DEPOSIT SWAP FUTURES FRA TENOR SWAP OIS
1D USDLIBOR1D USDDEPOSIT1D          
2D   USDDEPOSIT2D          
3D   USDDEPOSIT3D          
7D USDLIBOR7D USDDEPOSIT7D          
14D USDLIBOR14D USDDEPOSIT14D          
21D   USDDEPOSIT21D          
1M USDLIBOR1M USDDEPOSIT1M USDSWAP1M     USDTENORSWAP1M USDOIS1M
2M USDLIBOR2M USDDEPOSIT2M USDSWAP2M       USDOIS2M
3M USDLIBOR3M USDDEPOSIT3M USDSWAP3M   USDFRA3M6M USDTENORSWAP3M USDOIS3M
4M USDLIBOR4M USDDEPOSIT4M USDSWAP4M       USDOIS4M
5M USDLIBOR5M USDDEPOSIT5M USDSWAP5M       USDOIS5M
6M USDLIBOR6M USDDEPOSIT6M USDSWAP6M   USDFRA6M9M USDTENORSWAP6M USDOIS6M
7M USDLIBOR7M USDDEPOSIT7M USDSWAP7M        
8M USDLIBOR8M USDDEPOSIT8M USDSWAP8M        
9M USDLIBOR9M USDDEPOSIT9M USDSWAP9M   USDFRA9M12M USDTENORSWAP9M USDOIS9M
10M USDLIBOR10M USDDEPOSIT10M USDSWAP10M        
11M USDLIBOR11M USDDEPOSIT11M USDSWAP11M        
12M USDLIBOR12M USDDEPOSIT12M   prefix: ED USDFRA12M15M    
1Y   USDDEPOSIT1Y USDSWAP1Y     USDTENORSWAP1Y USDOIS1Y
15M         USDFRA15M18M    
18M       prefix: ED USDFRA18M21M    
21M         USDFRA21M24M    
24M       prefix: ED USDFRA24M27M    
2Y   USDDEPOSIT2Y USDSWAP2Y prefix: ED   USDTENORSWAP2Y USDOIS2Y
36M       prefix: ED      
3Y   USDDEPOSIT3Y USDSWAP3Y prefix: ED   USDTENORSWAP3Y USDOIS3Y
4Y   USDDEPOSIT4Y USDSWAP4Y     USDTENORSWAP4Y USDOIS4Y
5Y   USDDEPOSIT5Y USDSWAP5Y     USDTENORSWAP5Y USDOIS5Y
6Y     USDSWAP6Y     USDTENORSWAP6Y  
7Y     USDSWAP7Y     USDTENORSWAP7Y  
8Y     USDSWAP8Y     USDTENORSWAP8Y  
9Y     USDSWAP9Y     USDTENORSWAP9Y  
10Y     USDSWAP10Y     USDTENORSWAP10Y USDOIS10Y
11Y     USDSWAP11Y        
12Y     USDSWAP12Y     USDTENORSWAP12Y  
13Y     USDSWAP13Y        
14Y     USDSWAP14Y        
15Y     USDSWAP15Y     USDTENORSWAP15Y  
16Y     USDSWAP16Y        
17Y     USDSWAP17Y        
18Y     USDSWAP18Y        
19Y     USDSWAP19Y        
20Y     USDSWAP20Y     USDTENORSWAP20Y USDOIS20Y
21Y     USDSWAP21Y        
22Y     USDSWAP22Y        
23Y     USDSWAP23Y        
24Y     USDSWAP24Y        
25Y     USDSWAP25Y     USDTENORSWAP25Y  
26Y     USDSWAP26Y        
27Y     USDSWAP27Y        
28Y     USDSWAP28Y        
29Y     USDSWAP29Y        
30Y     USDSWAP30Y     USDTENORSWAP30Y USDOIS30Y
35Y     USDSWAP35Y        
40Y     USDSWAP40Y        
45Y     USDSWAP45Y        
50Y     USDSWAP50Y        
60Y     USDSWAP60Y        

Each point on that matrix actually has a CurveInstrumentProvider object backing it. The simplest implementations of this interface just return a hard-coded identifier, but more complex ones are available, that will, for example, generate identifiers based on a provided curve date and tenor or a curve date, tenor and number of futures. This last function is used to calculate the identifier of a future offset from a specific point. I can therefore set up a CurveInstrumentProvider that will calculate the 'nth' future on or after, say, one year from the curve date. Where does the information to drive the CurveInstrumentProviders come from? The YieldCurveDefinition.

The Yield Curve Definition

This object is much simpler, it will typically consist of something like

Tenor Instrument Type Number of futures Convention Name
1D LIBOR   DEFAULT
7D LIBOR   DEFAULT
14D LIBOR   DEFAULT
1M LIBOR   DEFAULT
2M LIBOR   DEFAULT
3M LIBOR   DEFAULT
6M LIBOR   DEFAULT
9M LIBOR   DEFAULT
12M LIBOR   DEFAULT
1Y FUTURE 1 DEFAULT
1Y FUTURE 2 DEFAULT
1Y FUTURE 3 DEFAULT
2Y SWAP   DEFAULT
3Y SWAP   DEFAULT
4Y SWAP   DEFAULT
5Y SWAP   DEFAULT
7Y SWAP   DEFAULT
10Y SWAP   DEFAULT
12Y SWAP   DEFAULT
15Y SWAP   DEFAULT
20Y SWAP   DEFAULT
25Y SWAP   DEFAULT
30Y SWAP   DEFAULT

So, each row (nodal point) in the curve definition is used to look up a CurveInstrumentProvider. For many of these, this will likely be an instance of a class that just returns the hard-coded identifier within, which would typically be determined during system installation, but for the futures, a different class is called that computes the appropriate code. For example, if the curve date was 1/1/2011, then the future code generator for the above would return an identifier like 'EDH2' - the January 2012 future for the (1Y, FUTURE, 1, DEFAULT) row because it's the 1st quarterly IR future after one year. The next row (1Y, FUTURE, 2, DEFAULT) would return an identifier like 'EDM2' - the March 2012 future because it's the 2nd quarterly IR future after one year.

So a good question is, why don't we just exclude the number and assume a sequential sequence. The reason is that this configuration allows you to skip futures that aren't liquid enough, or whose value you don't trust - it's perfectly possible to use e.g. the 2nd and 4th futures after 18 months, for example, which gives maximum flexibility.

So, what is the 'Convention Name' column for? It's the name of the Yield Curve Specification Builder Configuration to use for constructing that nodal point. This means you can source yield curve nodes even when there are multiple possible choices available for a given data provider, or you want to source data from multiple different data providers. For example, you could have one yield curve specification builder configuration that produced Bloomberg ticker identifiers, and another that produced Thompson Reuters RICs, and configure the short end from one config and the long end of the curve from the other. While theoretically they could be mixed into a single specification matrix, that would require the specification matrix to be rebuild if that was ever to change.

How to set up the configurations for your own data source

A good starting point is to look at the curve set up for the swap view in OG-Examples. You should start by looking at the SECONDARY configurations and curve definitions that are used by the OG-Examples project. These are built using code in SecondaryCurveDefinitionAndSpecifications, and are editable via the web user interface. Currently though, it's probably easier to modify/augment that code than to hand edit the JSON format available in the current configuration editor. At the time of writing, a proper GUI for editing curve definitions and curve specification builder configurations is under development. Depending on your underlying data source and what you want to achieve, you may have to write new CurveInstrumentProviders (especially if you want IR futures in your curve), but it's unlikely you'll need to just get started. The simplest CurveInstrumentProvider is the StaticCurveInstrumentProvider, which just returns the Identifier given to it. The SyntheticIdentifierCurveInstrumentProvider generates the synthetic identifiers used by the OpenGamma demo system, so it probably won't be useful for you. For an example of how to build a future code generator, see the BloombergFutureCurveInstrumentProvider. Note if you write a new CurveInstrumentProvider you'll also need to add a fudge builder for it, see e.g. BloombergFutureCurveInstrumentProviderBuilder for an example.

The curve definitions you populate into the configuration system (from YieldCurveConfigPopulator, which is driven from a 'depends-on' attribute in OG-Financial/config/com/opengamma/financial/demoMasters.xml spring file (around line 77 at the time of writing) are iterated over in DemoCurveFunctionConfiguration, and an instance of MarketInstrumentImpliedYieldCurveFunction and it's helper functions YieldCurveMarketDataFunction and YieldCurveInterpolatingFunction, which collect input data, and interpolate the output respectively.

Conventions

Because the curve construction process involved the synthesis and pricing of implied market instruments, we also need to be able to access market conventions. These are currently stored in InMemoryConventionBundleMaster (which is long overdue a refactor and have the conventions put into a database). You will need to make sure you add your identifiers, for e.g. the three month Libor rate into the identifier bundles constructed in that class. Conventions are sometimes looked up using the simple scheme, which uses a descriptive String such as 'USD LIBOR 3m' - this allows you to specify rates in e.g. swap legs without tying you to a specific identifier scheme.

You might find some places where there are special temporary special cases to deal with the fact the SECONDARY curves don't use Bloomberg tickers, but generally we've tried to make the system as neutral as possible, and you should expect such code fragments to go away over time.

An example of such a special case is that the SECONDARY curve functions are added to the function repository at a lower priority than the standard curve functions we use in production, which means that if you have both 'primary' (AKA SINGLE, FUNDING & FORWARD) curves, value specifications (columns) that don't specify a specific curve will be provided with curves by the functions initialised with the 'primary' definitions rather than the SECONDARY curve definitions, or worst, a non-deterministic mixture of primary and secondary curves (which is what happens if two functions provide the same unconstrained value within the engine).

Data requirements

In addition to the nodal points you've generated/specified in your curve, you'll likely also need time series of some of the indices, such as the aforementioned USD LIBOR 3m, but also probably USD LIBOR 6m and USD LIBOR 12m. Obviously you'll need the equivalent for any non-USD currencies you're supporting with other curves. These time series are used to get the correct Libor rates for swaps, cash and so on when cash flows are calculated.

View Definition

Use the example swap view definition generated by the examples to see how to set up a curve. Note that currently you'll need to specify 'FundingCurve' and 'ForwardCurve' with your curve names even if they're the same as what you're setting the 'Curve' property. We'd recommend setting these in the default properties section to start with and keep your portfolio requirements free of extra curve properties.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.