Instrument Pricing Analytics — Zero Coupon Curves

Umer Nalla
LSEG Developer Community
21 min readMay 24, 2021

In one of my earlier articles on Instrument Pricing Analytics — Volatility Surfaces and Curves, I mentioned I would deliver a follow up article on Zero Coupon Curves — another of the related IPA content sets.

Zero Coupon Curves, like other pricing data (Volatility Surfaces, Inflation Curves), are used to model risk factors and can be used to power risk management or valuation systems.

As with the previous article I think the best way to highlight this content is via some code and a few graphs — so let me dive straight into the code….

NOTE: As some of the actual JSON input requests and output responses are very long, I have heavily truncated some of them in the code sections below. The full inputs and outputs are included in the Jupyter Notebook file on GitHub.

Initialisation

First thing I need to do is import my libraries and then run my scripts to define my helper functions. As you will note I am importing the Refinitiv Data Platform library which will be my main interface to the Platform — as well as few commonly used Python libraries.

import json
import refinitiv.dataplatform as rdp
import configparser as cp
from IPython.display import HTML
import matplotlib.pyplot as plt
import pandas as pd

%run "../plotting_helper.ipynb"

As the name would suggest, the plotting_helper contains the full plotting code. I won't share any of the plotting code snippets in this article - please refer to the actual file on GitHub (see link in right hand panel).

Connect to the Refinitiv Data Platform

I fetch my credentials from a configuration file and use them to open a Platform session — If I were a Desktop user of Eikon or Refinitiv Workspace, I could open a Desktop session instead.

config = cp.ConfigParser()
config.read("c:/Refinitiv/config.cfg")
session = rdp.open_platform_session(config['platform']['app_key'],
rdp.GrantPassword( username=config['platform']['user'],
password=config['platform']['password'] )
)
# OR for Eikon / Workspace account
#session = rdp.open_desktop_session(app_key=config['desktop']['app_key'])

Endpoint Interface

In my previous article I mentioned how the Refinitiv Data Platform library consists of different layers:

  1. Function: Highest level — single function call to get data
  2. Content: High level — Fuller response and Level 1 Streaming data too
  3. Delivery: For Level 2 Streaming data and data sets not supported by above Layers

Whilst there is some support for Instrument Pricing Analytics (IPA) data in the Function Layer, I will use the Delivery layer as it works for all IPA content on the platform.
Each unique content set on the Platform has its own Endpoint and we can use the Delivery Layers Endpoint interface to access that content.

Using the Endpoint interface to request IPA content is fairly straightforward

  1. Identify the required IPA Endpoint (URL)
  2. Use the Endpoint Interface to send a request to the Endpoint
  3. Decode the response and extract the IPA data

Identifying the Surfaces Endpoint

To ascertain the Endpoint, we can use the Refinitiv Data Platform’s API Playground — an interactive documentation site you can access once you have a valid Refinitiv Data Platform account.

So, firstly I can search for ‘curves’ to narrow down the list of Endpoints and then select the relevant Endpoint from the list. At the time of writing, there are 3 related Endpoints available and I will use all of them in this article.

I copy the required Endpoint URLs e.g. — /data/quantitative-analytics-curves-and-surfaces/v1/curves/zc-curves — to use with the Endpoint interface as follows:

Define our API Endpoints for the ZC Curve definitions and ZC Curves data

zcCurveDefinitions_endpoint = rdp.Endpoint(session, 
'https://api.refinitiv.com/data/quantitative-analytics-curves-and-surfaces/v1/curves/zc-curve-definitions')

zcCurve_endpoint = rdp.Endpoint(session,
'https://api.refinitiv.com/data/quantitative-analytics-curves-and-surfaces/v1/curves/zc-curves')

forward_zcCurve_endpoint = rdp.Endpoint(session,
"https://api.refinitiv.com/data/quantitative-analytics-curves-and-surfaces/v1/curves/forward-curves")

Querying Curve Definitions

Before we can request a ZC Curve we need to have an idea of what curves are actually available on the Refinitiv Data Platform.

Our interactions with the platform takes the form of JSON messages i.e. JSON requests and JSON responses.

We can use the Curve Definitions Endpoint to discover what is currently available by sending a JSON request.

For instance, if I want to discover the full list of what Refinitiv has available in terms of ZC Curves, I can send a request with a single parameter i.e. the Source:

request_body={
"universe": [
{
"source": "Refinitiv"
}
]
}

response = zcCurveDefinitions_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

pd.DataFrame(data=response.data.raw["data"][0]["curveDefinitions"]).sort_values(by='currency')
Curve Definitions from Refinitiv Source

I extract the Curve Definitions data from the JSON response and convert it to a Pandas Dataframe for easier viewing.
As you will note, the definition includes various properties including the Currency as well as available Tenors and Discounting Tenors.

At the time of writing, we have 61 Curves available from Refinitiv on the Data Platform.
It is also possible that in the future we could offer Curves from other non-Refinitiv Sources.

Filtering the list of Curve Definitions

You can restrict the list of curves returned by specifying a filter e.g. Currency:

request_body={
"universe": [
{
"source": "Refinitiv",
"currency": "USD"
}
]
}

response = zcCurveDefinitions_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

pd.DataFrame(data=response.data.raw["data"][0]["curveDefinitions"])
Curve Definitions for USD

Note that the source is optional at present, as Refinitiv is the only source available.

Multiple Curve Definitions for some Currencies

Some currencies have multiple curves e.g. JPY and EUR:

request_body={
"universe": [
{
"currency": "JPY"
}
]
}

response = zcCurveDefinitions_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

pd.DataFrame(data=response.data.raw["data"][0]["curveDefinitions"])
JPY Curves

You can refer to the curve properties to identify the differences e.g. a given currency may have curves based on different indices as well as Market Data Locations — as we see above with the ‘JPY TIBOR EMEA’ curve.

request_body={
"universe": [
{
"currency": "EUR"
}
]
}

response = zcCurveDefinitions_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

pd.DataFrame(data=response.data.raw["data"][0]["curveDefinitions"])

Requesting a curve by its ID

Once you have discovered the ID of a curve you can request it directly — for example the JPY TIBOR (EMEA) Swap ZC Curve — note that I have selected the 1M Discounting Tenor from the available ones:

request_body = {
"universe": [
{
"curveDefinition": {
"id": "a865716b-e437-4045-84b5-f6483d8b6a25",
"discountingTenor": "1M"
}
}]
}

response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

Detailed Response — curve points data — Definition + Parameters

Note how the JSON Response contains the Curve points data, which is preceded by the full definition and the default Parameters that were used to generate the curve.
If you wish to request user defined curves with some variations, you can extract these details from the response and tweak some of the parameters to form your own custom request.

print(json.dumps(response.data.raw, indent=2)){
"data": [
{
"curveParameters": {
"extrapolationMode": "None",
"interpolationMode": "CubicDiscount",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"JAP_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -6.9606,
"volatilityPercent": 0.142
},
"valuationDate": "2021-05-19",
"ignoreExistingDefinition": false
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "JPY",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "TIBOR",
"source": "Refinitiv",
"name": "JPY TIBOR (EMEA) Swap ZC Curve",
"marketDataLocation": "EMEA",
"id": "a865716b-e437-4045-84b5-f6483d8b6a25",
"discountingTenor": "1M",
"indexTenors": [
"1M",
"3M",
"6M"
]
},
"curves": {
"1M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 0.9999981666700277,
"endDate": "2021-05-21",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "2D"
},
{
"discountFactor": 0.9999917500562983,
"endDate": "2021-05-28",
"ratePercent": 0.03346384092193233,
"startDate": "2021-05-19",
"tenor": "1W",
"instruments": [
{
"instrumentCode": "ZTIJPY1WD="
}
]
},
],
"isDiscountCurve": true
},
.....
Truncated
..... "3M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 0.9999981666700277,
"endDate": "2021-05-21",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "2D"
},

],
"isDiscountCurve": false
.....
Truncated
.....
},
"6M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 0.9999981666700277,
"endDate": "2021-05-21",
"ratePercent": 0.033463900578256656,
"startDate": "2021-05-19",
"tenor": "2D"
},
],
"isDiscountCurve": false
}
}
}
]
}

Plot the data

I can then use the curve points to generate my curve plot

plot_zc_curves(response.data.raw['data'][0], ['3M'])

Getting our Curve points into a Dataframe

pd.DataFrame(response.data.raw['data'][0]["curves"]["3M"]["curvePoints"])

Note the final column, which shows the Instrument that was used for the bootstrapping when generating the individual curve points

Requesting Curve using Parameters

As an alternative to using the Curve ID, I can also request a curve using Curve Parameters and Definition values.
Some of the key Parameters here are:

  • Valuation Date
  • InterpolationMode e.g. CubicSpline, CubicDiscount, Linear etc
  • Day Count Basis e.g.
  • Actual, AFD, ISDA, 360, 365…
  • 30_360, 30_360_US, 30_360_German…
  • 30_365, 30_365_US, 30_365_German…

One thing to be aware of here is that if we had more than one EUR curve, I would need to specify sufficient Definition parameters to uniquely identify the curve I want.
So, for example if we had two ‘EURIBOR’ based curves, I would need to specify the full name as well (or other unique definition parameter) — but as we currently only have one, I can just specify the indexName as I have done below.

request_body={
"universe": [
{
"curveParameters": {
"valuationDate":"2020-06-30",
"interpolationMode": "CubicSpline",
"priceSide": "Mid",
"interestCalculationMethod": "Dcb_Actual_Actual",
"extrapolationMode": "Linear"
},

"curveDefinition": {
"currency": "EUR",
"indexName":"EURIBOR",
"discountingTenor": "OIS",
"indexTenors":["6M"]
}
}],

"outputs":["Constituents"]
}

response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)
print(json.dumps(response.data.raw, indent=2))

Generates a response like:

{
"data": [
{
"curveParameters": {
"extrapolationMode": "Linear",
"interpolationMode": "CubicSpline",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"EMU_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -1.3584,
"volatilityPercent": 0.474
},
"valuationDate": "2020-06-30",
"ignoreExistingDefinition": false
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M",
"1Y"
],
"currency": "EUR",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "EURIBOR",
"source": "Refinitiv",
"name": "EUR EURIBOR Swap ZC Curve",
"id": "9d619112-9ab3-45c9-b83c-eb04cbec382e",
"discountingTenor": "OIS",
"indexTenors": [
"OIS",
"6M"
]
},
"curves": {
"OIS": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2020-06-30",
"ratePercent": -0.5222187504691722,
"startDate": "2020-06-30",
"tenor": "0D"
},
{
"discountFactor": 1.0000143057602073,
"endDate": "2020-07-01",
"ratePercent": -0.5222187504691722,
"startDate": "2020-06-30",
"tenor": "ON",
"instruments": [
{
"instrumentCode": "EUROND="
}
]
},
"isDiscountCurve": true
.....
Truncated
..... },
"6M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2020-06-30",
"ratePercent": -0.5222187504691722,
"startDate": "2020-06-30",
"tenor": "0D"
},
{
"discountFactor": 1.0000143057602073,
"endDate": "2020-07-01",
"ratePercent": -0.5222187504691722,
"startDate": "2020-06-30",
"tenor": "ON",
"instruments": [
{
"instrumentCode": "EUROND="
}
]
},
.....
Truncated
..... ],
"isDiscountCurve": false
}
},
"constituents": {
"interestRateInstruments": {
"EUR": {
"deposits": [
{
"fields": {
"bid": {
"value": -0.58
},
"ask": {
"value": -0.45
}
},
"instrumentDefinition": {
"instrumentCode": "EUROND=",
"template": "EUR",
"tenor": "ON"
},
"basis": [
"1M",
"3M",
"6M",
"1Y",
"OIS"
]
},
{
"fields": {
"bid": {
"value": -0.55
},
"ask": {
"value": -0.4
}
},
"instrumentDefinition": {
"instrumentCode": "EURTND=",
"template": "EUR",
"tenor": "TN"
},
"basis": [
"1M",
"3M",
"6M",
"1Y",
"OIS"
]
},
{
"fields": {
"bid": {
"value": -0.225
},
"ask": {
"value": -0.225
}
},
"instrumentDefinition": {
"instrumentCode": "EURIBOR1YD=",
"template": "EUR",
"tenor": "1Y"
},
"basis": [
"1Y"
]
}
],
"fras": [
{
"fields": {
"bid": {
"value": -0.52
},
"ask": {
"value": -0.5
}
},
"instrumentDefinition": {
"instrumentCode": "EUR0X1F=SMKR",
"template": "EURFRA",
"tenor": "0X1"
},
"basis": [
"1M"
]
},
{
"fields": {
"bid": {
"value": -0.432
},
"ask": {
"value": -0.412
}
},
"instrumentDefinition": {
"instrumentCode": "EUR0X3F=SMKR",
"template": "EURFRA",
"tenor": "0X3"
},
"basis": [
"3M"
]
},
.....
Truncated
.....
],
"futures": [
{
"fields": {
"bid": {
"value": 100.455
},
"ask": {
"value": 100.46
}
},
"instrumentDefinition": {
"instrumentCode": "FEIcm1",
"template": "FEI"
},
"basis": [
"3M"
]
},
{
"fields": {
"bid": {
"value": 100.46
},
"ask": {
"value": 100.465
}
},
"instrumentDefinition": {
"instrumentCode": "FEIcm2",
"template": "FEI"
},
"basis": [
"3M"
]
},
.....
Truncated
..... ],
"interestRateSwaps": [
{
"fields": {
"bid": {
"value": -0.481
},
"ask": {
"value": -0.473
}
},
"instrumentDefinition": {
"instrumentCode": "EURAB3E2Y=TWEB",
"template": "EUR_AB3E",
"tenor": "2Y"
},
"basis": [
"3M"
]
},
{
"fields": {
"bid": {
"value": -0.476
},
"ask": {
"value": -0.468
}
},
"instrumentDefinition": {
"instrumentCode": "EURAB3E3Y=TWEB",
"template": "EUR_AB3E",
"tenor": "3Y"
},
"basis": [
"3M"
]
},
.....
Truncated
..... ],
"overnightIndexSwaps": [
{
"fields": {
"bid": {
"value": -0.511
},
"ask": {
"value": -0.411
}
},
"instrumentDefinition": {
"instrumentCode": "EUREONSW=ICAP",
"template": "OIS_EONIA",
"tenor": "SW"
},
"basis": [
"OIS"
]
},
{
"fields": {
"bid": {
"value": -0.511
},
"ask": {
"value": -0.411
}
},
"instrumentDefinition": {
"instrumentCode": "EUREON2W=ICAP",
"template": "OIS_EONIA",
"tenor": "2W"
},
"basis": [
"OIS"
]
},
.....
Truncated
..... ],
"tenorBasisSwaps": [
{
"fields": {
"bid": {
"value": 10.3
},
"ask": {
"value": 10.3
}
},
"instrumentDefinition": {
"instrumentCode": "EUR6E12E2Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "2Y"
},
"basis": [
"1Y"
]
},
{
"fields": {
"bid": {
"value": 9.5
},
"ask": {
"value": 9.5
}
},
"instrumentDefinition": {
"instrumentCode": "EUR6E12E3Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "3Y"
},
"basis": [
"1Y"
]
},
.....
Truncated
.....
"basis": [
"1M"
]
}
]
}
}
}
}
]
}

As you can see from the above response, it contains the following:

  1. The full set of Curve Parameters and Definition used to produce the curve
  2. Curve point data for each available Tenor
  3. List of Constituents

Plot the data

plot_zc_curves(response.data.raw['data'][0], ['6M'])

If a particular Currency e.g. SEK, has only one curve available, the indexName attribute can be omitted.
Likewise, there are several other parameters where you can override the default to control the results.

Specifying the curve output Tenors

Generating a forward curve built with the market date of Jan 30th, 2021

As well as the Index Tenor, we provide the Start Tenor and the Tenors we wish to generate the Forward Curve for and use the Forward Curves Endpoint we defined towards the start of the article.

request_body={
"universe":[
{
"curveDefinition": {
"currency": "JPY",
"indexName": "LIBOR",
"discountingTenor": "1M"
},

"curveParameters":{
"valuationDate":"2021-01-30"
},

"forwardCurveDefinitions": [
{
"indexTenor": "1M",
"forwardStartTenor":"2D",
"forwardCurveTenors": [
"0M","1M","2M","3M","4M","5M","6M","7M","8M","9M","10M","11M","12M","13M","14M","15M",
"16M","17M","18M","19M","20M","21M","22M","23M","24M","25M","26M","27M","28M","29M","30M",
"31M","32M","33M","34M","35M","36M","37M","38M","39M","40M","41M","42M","43M","44M","45M",
"46M","47M","48M","49M","50M","51M","52M","53M","54M","55M","56M","57M","58M","59M","60M","61M"]
}
]
}
]
}

response = forward_zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body)


print(json.dumps(response.data.raw, indent=2))

Provides a response as below:

{
"data": [
{
"curveParameters": {
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"JAP_FI"
],
"compoundingType": "Compounded",
"useConvexityAdjustment": true,
"useSteps": false,
"valuationDate": "2021-01-30",
"ignoreExistingDefinition": false
},
"curveDefinition": {
"availableTenors": [
"6M",
"OIS",
"3M",
"1M"
],
"currency": "JPY",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "JPY LIBOR Swap ZC Curve",
"id": "cbf84acf-5328-4efc-8d23-f476ac495d82",
"discountingTenor": "1M"
},
"forwardCurves": [
{
"curvePoints": [
{
"discountFactor": 1.000002876383664,
"endDate": "2021-02-03",
"ratePercent": -0.05262389411501145,
"startDate": "2021-02-01",
"tenor": "0M"
},
{
"discountFactor": 1.0000474669650439,
"endDate": "2021-03-03",
"ratePercent": -0.057733431373796495,
"startDate": "2021-02-01",
"tenor": "1M"
},
{
"discountFactor": 1.000106523884317,
"endDate": "2021-04-05",
"ratePercent": -0.06169389328620767,
"startDate": "2021-02-01",
"tenor": "2M"
},
.....
Truncated
.....
],
"forwardCurveTag": "2DForward",
"forwardStart": "2D",
"indexTenor": "1M"
}
]
}
]
}

Get our Curve points into a Dataframe

pd.DataFrame(response.data.raw['data'][0]['forwardCurves'][0]['curvePoints'])

Implied Foreign Currencies / Currency Adjusted ZC Curves

Here we are using the referenceCurveDefinition parameter to calculate a JPY curve currency adjusted for the USD using LIBOR i.e. integrate currency basis swap, starting with the USD Libor as the reference curve.

request_body={
"universe": [
{
"curveDefinition": {
"currency":"JPY",
"indexName":"LIBOR",
"discountingTenor": "6M",
"referenceCurveDefinition": {
"currency":"USD",
"indexName":"LIBOR",
"mainConstituentAssetClass":"Swap",
"discountingTenor": "6M",
}
}
}]
}

response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)
print(json.dumps(response.data.raw, indent=2))

Generates the following response payload:

{
"data": [
{
"curveParameters": {
"extrapolationMode": "None",
"interpolationMode": "CubicDiscount",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"JAP_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -6.9606,
"volatilityPercent": 0.142
},
"valuationDate": "2021-05-19",
"ignoreExistingDefinition": false,
"referenceCurveParameters": {
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": 1.295,
"volatilityPercent": 0.795
}
}
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "JPY",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "JPY LIBOR Swap ZC Curve",
"id": "cbf84acf-5328-4efc-8d23-f476ac495d82",
"discountingTenor": "6M",
"indexTenors": [
"6M"
],
"referenceCurveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "USD",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "USD LIBOR Swap ZC Curve",
"id": "1ef0692f-1cde-4b71-bad7-e39198633e0e",
"discountingTenor": "6M"
}
},
"curves": {
"6M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": -0.037043027411154394,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 1.0000050753402816,
"endDate": "2021-05-24",
"ratePercent": -0.037043027411154394,
"startDate": "2021-05-19",
"tenor": "5D"
},
{
"discountFactor": 1.0000224357858043,
"endDate": "2021-05-28",
"ratePercent": -0.09094717303220756,
"startDate": "2021-05-19",
"tenor": "1W"
},
.....
Truncated
.....
],
"isDiscountCurve": true
}
}
}
]
}
pd.DataFrame(response.data.raw['data'][0]['curves']['6M']['curvePoints'])

Alternative Discounting Tenor

Here we are requesting the GBP 6M LIBOR Curve by it’s ID, collateralized with the USD 6M LIBOR curve

request_body={
"universe": [
{
"curveDefinition": { #GBP 6M LIBOR.
"id": "69348bb7-d0b3-49b3-b2b2-782ab4ad29f8",
"discountingTenor":"6M",
"referenceCurveDefinition": { #USD 6M LIBOR.
"id": "1ef0692f-1cde-4b71-bad7-e39198633e0e",
"discountingTenor":"6M"
}
}
}],
"outputs": ["DetailedCurvePoint"]
}

response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)

print(json.dumps(response.data.raw, indent=2))
curves = response.data.raw['data'][0]["curves"]["6M"]["curvePoints"]

The resulting response payload is:

{
"data": [
{
"curveParameters": {
"extrapolationMode": "None",
"interpolationMode": "CubicDiscount",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"UKG_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -0.7192,
"volatilityPercent": 0.656
},
"valuationDate": "2021-05-19",
"ignoreExistingDefinition": false,
"referenceCurveParameters": {
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": 1.295,
"volatilityPercent": 0.795
}
}
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "GBP",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "GBP LIBOR Swap ZC Curve",
"id": "69348bb7-d0b3-49b3-b2b2-782ab4ad29f8",
"discountingTenor": "6M",
"indexTenors": [
"6M"
],
"referenceCurveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "USD",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "USD LIBOR Swap ZC Curve",
"id": "1ef0692f-1cde-4b71-bad7-e39198633e0e",
"discountingTenor": "6M"
}
},
"curves": {
"6M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": 0.09415395921494873,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 0.9999871083485532,
"endDate": "2021-05-24",
"ratePercent": 0.09415395921494873,
"startDate": "2021-05-19",
"tenor": "5D"
},
{
"discountFactor": 0.9999780472258979,
"endDate": "2021-05-28",
"ratePercent": 0.08907131717752481,
"startDate": "2021-05-19",
"tenor": "1W"
},
{
"discountFactor": 0.9999427709698175,
"endDate": "2021-06-21",
"ratePercent": 0.06332062619058831,
"startDate": "2021-05-19",
"tenor": "1M"
},
.....
Truncated
..... ],
"isDiscountCurve": true
}
}
}
]
}

Taking collateral currency into account

Similarly, we can use a Pivot Curve — so for example, instead of going directly from EUR to JPY, we are going via USD.

request_body={
"universe": [
{
"curveDefinition": {
"currency":"JPY",
"indexName":"LIBOR",
"discountingTenor": "OIS",
"pivotCurveDefinition":{
"currency":"USD",
"indexName":"LIBOR",
"mainConstituentAssetClass":"Swap",
"discountingTenor": "OIS"
},
"referenceCurveDefinition": {
"currency":"EUR",
"indexName":"ESTR",
"discountingTenor": "OIS"
}
}
}]
}

response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body
)
print(json.dumps(response.data.raw, indent=2))

Generates the following payload response:

{
"data": [
{
"curveParameters": {
"extrapolationMode": "None",
"interpolationMode": "CubicDiscount",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"JAP_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -6.9606,
"volatilityPercent": 0.142
},
"valuationDate": "2021-05-19",
"ignoreExistingDefinition": false,
"pivotCurveParameters": {
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"compoundingType": "Compounded",
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": 1.295,
"volatilityPercent": 0.795
}
},
"referenceCurveParameters": {
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -0.0614,
"volatilityPercent": 0.564
}
}
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M"
],
"currency": "JPY",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "JPY LIBOR Swap ZC Curve",
"id": "cbf84acf-5328-4efc-8d23-f476ac495d82",
"discountingTenor": "OIS",
"indexTenors": [
"OIS"
],
"pivotCurveDefinition": {
"availableTenors": [
"6M",
"3M",
"OIS",
"1M"
],
"currency": "USD",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "LIBOR",
"source": "Refinitiv",
"name": "USD LIBOR Swap ZC Curve",
"id": "1ef0692f-1cde-4b71-bad7-e39198633e0e",
"discountingTenor": "OIS"
},
"referenceCurveDefinition": {
"availableTenors": [
"OIS"
],
"currency": "EUR",
"mainConstituentAssetClass": "Swap",
"riskType": "InterestRate",
"indexName": "ESTR",
"source": "Refinitiv",
"name": "EUR ESTR Swap ZC Curve",
"id": "d734ef63-367c-4a4f-9cca-135796c9a3ed",
"discountingTenor": "OIS"
}
},
"curves": {
"OIS": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-05-19",
"ratePercent": -0.3184608466429206,
"startDate": "2021-05-19",
"tenor": "0D"
},
{
"discountFactor": 1.000043695339868,
"endDate": "2021-05-24",
"ratePercent": -0.3184608466429206,
"startDate": "2021-05-19",
"tenor": "5D"
},
{
"discountFactor": 1.0000611763252403,
"endDate": "2021-05-28",
"ratePercent": -0.24778889220563594,
"startDate": "2021-05-19",
"tenor": "1W"
},
{
"discountFactor": 1.0001605659935293,
"endDate": "2021-06-21",
"ratePercent": -0.17742388113686225,
"startDate": "2021-05-19",
"tenor": "1M"
},
.....
Truncated
..... ],
"isDiscountCurve": true
}
}
}
]
}
pd.DataFrame(response.data.raw['data'][0]["curves"]["OIS"]["curvePoints"])

User defined ZC Curves

So far I have requested Refinitiv defined Curves and how you can use parameters to customise the generated output.
However, one of the other great features of the Zero Coupons APIs is that you can define your own ZC Curves by specifying your own constituents.
You will have noted that when I requested a Refinitiv defined curve, the response included the constituents used to generate the curve. So, if required you could take one of our existing curves and modify the constituents and parameter to generate your own custom curve.

user_defined_zc_request_body = {
"universe": [
{
"curveParameters": {
"ignoreExistingDefinition": True,
"valuationDate": "2021-02-23"
},
"curveDefinition": {
"currency": "EUR",
"discountingTenor": "OIS"
},
"constituents": {
"interestRateInstruments": {
"EUR": {
"deposits": [
{
"instrumentDefinition": {
"instrumentCode": "EUROND=",
"template": "EUR",
"tenor": "ON"
},
"basis": [
"6M",
"1Y",
"3M",
"OIS",
"1M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EURTND=",
"template": "EUR",
"tenor": "TN"
},
"basis": [
"6M",
"1Y",
"3M",
"OIS",
"1M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EURIBOR1YD=",
"template": "EUR",
"tenor": "1Y"
},
"basis": [
"1Y"
]
}
],
"fras": [
{
"instrumentDefinition": {
"instrumentCode": "EUR4X10F=SMKR",
"template": "EURFRA",
"tenor": "4X10"
},
"basis": [
"6M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EUR0X1F=SMKR",
"template": "EURFRA",
"tenor": "0X1"
},
"basis": [
"1M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EUR3X9F=SMKR",
"template": "EURFRA",
"tenor": "3X9"
},
"basis": [
"6M"
]
},
.....
Truncated
.....
],
"futures": [
{
"basis": [
"3M"
],
"instrumentDefinition": {
"instrumentCode": "FEIcm8",
"template": "FEI"
}
},
{
"basis": [
"3M"
],
"instrumentDefinition": {
"instrumentCode": "FEIcm1",
"template": "FEI"
}
},
{
"basis": [
"3M"
],
"instrumentDefinition": {
"instrumentCode": "FEIcm7",
"template": "FEI"
}
},
.....
Truncated
.....
],
"interestRateSwaps": [
{
"instrumentDefinition": {
"instrumentCode": "EURAB3E14Y=TWEB",
"template": "EUR_AB3E",
"tenor": "14Y"
},
"basis": [
"3M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EURAB6E8Y=TWEB",
"template": "EUR_AB6E",
"tenor": "8Y"
},
"basis": [
"6M"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EURAB3E3Y=TWEB",
"template": "EUR_AB3E",
"tenor": "3Y"
},
"basis": [
"3M"
]
},
.....
Truncated
.....
],
"overnightIndexSwaps": [
{
"instrumentDefinition": {
"instrumentCode": "EUREON11Y=ICAP",
"template": "OIS_EONIA",
"tenor": "11Y"
},
"basis": [
"OIS"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EUREON9M=ICAP",
"template": "OIS_EONIA",
"tenor": "9M"
},
"basis": [
"OIS"
]
},

],
"tenorBasisSwaps": [
{
"instrumentDefinition": {
"instrumentCode": "EUR6E12E5Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "5Y"
},
"basis": [
"1Y"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EUR6E12E12Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "12Y"
},
"basis": [
"1Y"
]
},
{
"instrumentDefinition": {
"instrumentCode": "EUR1E3E2Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:4 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:12 PDELAY:0",
"tenor": "2Y"
},
"basis": [
"1M"
]
},
.....
Truncated
.....
{
"instrumentDefinition": {
"instrumentCode": "EUR1E3E3Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:4 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:12 PDELAY:0",
"tenor": "3Y"
},
"basis": [
"1M"
]
}
]
}
}
}
}
],
"outputs": [
"DetailedCurvePoint",
"Constituents"
]
}


user_defined_zc_response = zcCurve_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = user_defined_zc_request_body
)

print(json.dumps(user_defined_zc_response.data.raw, indent=2))

Will generate the following custom curve response:

{
"data": [
{
"curveParameters": {
"extrapolationMode": "None",
"interpolationMode": "CubicDiscount",
"interestCalculationMethod": "Dcb_Actual_Actual",
"priceSide": "Mid",
"calendarAdjustment": "Calendar",
"calendars": [
"EMU_FI"
],
"compoundingType": "Compounded",
"useMultiDimensionalSolver": true,
"useConvexityAdjustment": true,
"useSteps": false,
"convexityAdjustment": {
"meanReversionPercent": -1.6963,
"volatilityPercent": 0.443
},
"valuationDate": "2021-02-23",
"ignoreExistingDefinition": true
},
"curveDefinition": {
"availableTenors": [
"OIS",
"1M",
"3M",
"6M",
"1Y"
],
"currency": "EUR",
"discountingTenor": "OIS",
"indexTenors": [
"OIS",
"1M",
"3M",
"6M",
"1Y"
]
},
"curves": {
"OIS": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-02-23",
"ratePercent": -0.5576104873114995,
"startDate": "2021-02-23",
"tenor": "0D"
},
{
"discountFactor": 1.0000152780111917,
"endDate": "2021-02-24",
"ratePercent": -0.5576104873114995,
"startDate": "2021-02-23",
"tenor": "ON",
"instruments": [
{
"instrumentCode": "EUROND=",
"value": -0.55
}
]
},
.....
Truncated
.....
],
"isDiscountCurve": true
},
"1M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-02-23",
"ratePercent": -0.5576104873114995,
"startDate": "2021-02-23",
"tenor": "0D"
},
{
"discountFactor": 1.0000152780111917,
"endDate": "2021-02-24",
"ratePercent": -0.5576104873114995,
"startDate": "2021-02-23",
"tenor": "ON",
"instruments": [
{
"instrumentCode": "EUROND=",
"value": -0.55
}
]
},
.....
Truncated
.....
],
"isDiscountCurve": false
},
"3M": {
"curvePoints": [
{
"discountFactor": 1.0,
"endDate": "2021-02-23",
"ratePercent": -0.5576104873114995,
"startDate": "2021-02-23",
"tenor": "0D"
},
.....
Truncated
..... ],
"isDiscountCurve": false
}
},
"constituents": {
"interestRateInstruments": {
"EUR": {
"deposits": [
{
"fields": {
"bid": {
"value": -0.6
},
"ask": {
"value": -0.5
}
},
"instrumentDefinition": {
"instrumentCode": "EUROND=",
"template": "EUR",
"tenor": "ON"
},
"basis": [
"6M",
"1Y",
"3M",
"OIS",
"1M"
]
},
{
"fields": {
"bid": {
"value": -0.6
},
"ask": {
"value": -0.5
}
},
"instrumentDefinition": {
"instrumentCode": "EURTND=",
"template": "EUR",
"tenor": "TN"
},
"basis": [
"6M",
"1Y",
"3M",
"OIS",
"1M"
]
},
.....
Truncated
..... ],
"fras": [
{
"fields": {
"bid": {
"value": -0.501
},
"ask": {
"value": -0.481
}
},
"instrumentDefinition": {
"instrumentCode": "EUR4X10F=SMKR",
"template": "EURFRA",
"tenor": "4X10"
},
"basis": [
"6M"
]
},
{
"fields": {
"bid": {
"value": -0.56
},
"ask": {
"value": -0.54
}
},
"instrumentDefinition": {
"instrumentCode": "EUR0X1F=SMKR",
"template": "EURFRA",
"tenor": "0X1"
},
"basis": [
"1M"
]
},
.....
Truncated
.....
],
"futures": [
{
"fields": {
"bid": {
"value": 100.505
},
"ask": {
"value": 100.51
}
},
"instrumentDefinition": {
"instrumentCode": "FEIcm8",
"template": "FEI"
},
"basis": [
"3M"
]
},
{
"fields": {
"bid": {
"value": 100.53
},
"ask": {
"value": 100.535
}
},
"instrumentDefinition": {
"instrumentCode": "FEIcm1",
"template": "FEI"
},
"basis": [
"3M"
]
},
.....
Truncated
.....
],
"interestRateSwaps": [
{
"fields": {
"bid": {
"value": 0.166
},
"ask": {
"value": 0.172
}
},
"instrumentDefinition": {
"instrumentCode": "EURAB3E14Y=TWEB",
"template": "EUR_AB3E",
"tenor": "14Y"
},
"basis": [
"3M"
]
},
{
"fields": {
"bid": {
"value": -0.136
},
"ask": {
"value": -0.131
}
},
"instrumentDefinition": {
"instrumentCode": "EURAB6E8Y=TWEB",
"template": "EUR_AB6E",
"tenor": "8Y"
},
"basis": [
"6M"
]
},
.....
Truncated
.....
],
"overnightIndexSwaps": [
{
"fields": {
"bid": {
"value": -0.019
},
"ask": {
"value": 0.031
}
},
"instrumentDefinition": {
"instrumentCode": "EUREON11Y=ICAP",
"template": "OIS_EONIA",
"tenor": "11Y"
},
"basis": [
"OIS"
]
},
{
"fields": {
"bid": {
"value": -0.509
},
"ask": {
"value": -0.459
}
},
"instrumentDefinition": {
"instrumentCode": "EUREON9M=ICAP",
"template": "OIS_EONIA",
"tenor": "9M"
},
"basis": [
"OIS"
]
},
.....
Truncated
.....
],
"tenorBasisSwaps": [
{
"fields": {
"bid": {
"value": 5.8
},
"ask": {
"value": 5.8
}
},
"instrumentDefinition": {
"instrumentCode": "EUR6E12E5Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "5Y"
},
"basis": [
"1Y"
]
},
.....
Truncated
.....
"instrumentDefinition": {
"instrumentCode": "EUR6E12E15Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:1 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:2 PDELAY:0",
"tenor": "15Y"
},
"basis": [
"1Y"
]
},
{
"fields": {
"bid": {
"value": 2.2
},
"ask": {
"value": 2.2
}
},
"instrumentDefinition": {
"instrumentCode": "EUR1E3E3Y=ICAP",
"template": "LBOTH CROSS:EUR CLDR:EMU SETTLE:2WD LRECEIVED LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:4 PDELAY:0 LPAID LTYPE:FLOAT CUR:EUR CFADJ:Y CCM:MMA0 DMC:M EMC:S FRQ:12 PDELAY:0",
"tenor": "3Y"
},
"basis": [
"1M"
]
}
]
}
}
}
}
]
}
curves = user_defined_zc_response.data.raw['data'][0]["curves"]["3M"]["curvePoints"]
pd.DataFrame(data=curves)

Financial Contracts API

Whilst the main focus of this article is Zero Coupon, I felt it would be remiss of me to not to briefly mention the related IPA Financial Contracts API — which may also of be some interest.

As with the ZC Curves API, we need to know the endpoint URL:

financial_contract_endpoint = rdp.Endpoint(session, 
'https://api.refinitiv.com/data/quantitative-analytics/v1/financial-contracts')

Interest Rate swap examples

With the above ZC examples, I showed how you could request a particular curve and use the data in your own application.
However, by using the Financial Contracts API, you can describe an instrument and the apppropriate curves will be fetched behind the scenes.
So, for example, if I want to request a vanilla AUD Interest Rate Swap based on the BBSW index, I need to:

request_body = {

"fields" : ["InstrumentTag","MarketValueInDealCcy","DirtyPricePercent","FixedRatePercent",\
"DiscountCurveName","ForwardCurveName","ErrorCode","ErrorMessage"],

"universe" : [
{
"instrumentType":"Swap",
"instrumentDefinition": {
"instrumentTag":"IRS-EUR EURIBOR 6M - 5Y",
"startDate":"2020-07-29",
"tenor":"5Y",
"legs":[
{
"direction":"Paid",
"interestType":"Fixed",
"notionalCcy":"EUR",
"interestPaymentFrequency":"Annual",
"interestCalculationMethod":"Dcb_Actual_365",
},
{
"direction":"Received",
"interestType":"Float",
"interestPaymentFrequency":"SemiAnnual",
"interestCalculationMethod":"Dcb_Actual_365",
"notionalCcy":"EUR",
"indexName":"EURIBOR",
"indexTenor":"6M",
}]
}
}],

"pricingParameters": {
"valuationDate": "2020-7-27T00:00:00Z",
},

"outputs" : ["Data","Headers"],

}

response = financial_contract_endpoint.send_request(
method = rdp.Endpoint.RequestMethod.POST,
body_parameters = request_body)

print(json.dumps(response.data.raw, indent=2))
{
"headers": [
{
"type": "String",
"name": "InstrumentTag"
},
{
"type": "Float",
"name": "MarketValueInDealCcy"
},
{
"type": "Float",
"name": "DirtyPricePercent"
},
{
"type": "Float",
"name": "FixedRatePercent"
},
{
"type": "String",
"name": "DiscountCurveName"
},
{
"type": "String",
"name": "ForwardCurveName"
},
{
"type": "String",
"name": "ErrorCode"
},
{
"type": "String",
"name": "ErrorMessage"
}
],
"data": [
[
"IRS-EUR EURIBOR 6M - 5Y",
-18956.4458024112,
-1.89564458024112,
-0.374483171441853,
"EUR - Swap vs 6M Euribor",
null,
"",
""
],
[
"IRS-EUR EURIBOR 6M - 5Y",
-18956.4458024112,
-1.89564458024112,
null,
"EUR - Swap vs 6M Euribor",
"EUR - Swap vs 6M Euribor",
"",
""
]
]
}
pd.DataFrame(data=response.data.raw['data'], columns=[h['name'] for h in response.data.raw['headers']])

As you will note from the 5th & 6th columns, the response provided details of the underlying curves used to calculate the requested Interest Rate Swap.

Closing

I hope the above has provided a useful insight into the power of the Zero Coupon Curve APIs that form part of the broader Instrument Pricing Analytics APIs umbrella.

References

Discover our new upcoming Refinitiv Data Platform Library — Part 1 of my RDP Library Introduction article

API Playground — Interactive Documentation for Refinitiv Data Platform APIs.

Refinitiv Data Platform APIs — our existing REST-based interface to the cloud Platform.

Q&A Forum for the Refinitiv Data Platform APIs

The full Source Code (including the complete JSON Request and Response payloads) is available as a Jupyter Notebook file on GitHub.

Originally published at https://developers.refinitiv.com.

--

--