Fixed Income Value-at-Risk with Python

Ameya Abhyankar
4 min readMay 28, 2020

Risk management is an important function in any organization especially financial institutions and banks. Risk management as a process has multiple steps. A key step in this process is the risk measurement of the portfolio. There are various measures that are deployed by firms to monitor various types of risk. For instance, Duration measures the interest rate sensitivity of the portfolio, Beta is used to measure sensitivity of the asset to a broad market index etc. However, by far the most prevalent measure adopted by the industry is called Value at Risk (acronym “VaR”). The beauty of VaR as a measure is that it gives one single number that encapsulates the entire risk to which the portfolio is exposed to. In this post we will discuss a model for fast calculation for VaR of a Fixed income portfolio by using Python. We will compute the 99% 1 day VaR of the portfolio.

For this post we will use hypothetical market data set comprising of interest rates for the last 1 year. We will consider only specific tenor points on the interest rate curve as inputs. We will refer to each of these tenor points as interest rate risk factors.

Next input are hypothetical PV01 values for the portfolio for the respective tenor points. The tenor points exactly match with those tenors as used for the interest rate risk factor time series. We will refer to these as pv01 risk factors.

The above two sample input files can be found in my account repository on Github on this link:

You may use the actual risk factors from your portfolio and follow the similar input file format for using this model.

We will use these two risk factors to estimate the VaR of the portfolio over the next 1 day horizon. The methodology used is explained below along with the Python code for the same.

In the below section we will walk through the Python code used for implementation of this model.

· We begin with reading in the input files in Python after importing the required libraries in the code.

import numpy as np
import pandas as pd
data_rates = pd.read_csv("F:\\ FI_MarketData.csv")
data_pv01 = pd.read_csv("F:\\ PV01-InputData.csv")

· In this step we will move the input data into pandas DataFrame. Subsequently we will do the necessary pre-processing on the data to make it useful for the further process. We process the interest rate risk factor time series for computation of returns that will be done in the next step. We also store pv01 risk factor data and today’s End of the Day rates into other pandas DataFrames.

df_data = pd.DataFrame(data=data_rates)
df_data = df_data.drop(df_data.columns[0],axis=1)
df_data = df_data.astype(float)
df_PV01 = pd.DataFrame(data_pv01)
df_PV01 = df_PV01 * -1
df_PV01 = df_PV01.astype(float)
df_rates_today = df_data.iloc[-1,:]

· We compute the daily returns using the interest rate risk factor time series.

df = pd.DataFrame()
df = df_data.pct_change()
df = df.drop(df.index[0])

· Now, we weigh the above daily returns time series with the End of the Day rates for today and also by the respective portfolio pv01 risk factor for the respective tenor points. We do this for the entire returns series using the below code.

df[‘3m’] = df[‘3m’] * df_rates_today.iloc[0] * df_PV01.iloc[0,1]
df[‘6m’] = df[‘6m’] * df_rates_today.iloc[1] * df_PV01.iloc[1,1]
df[‘1y’] = df[‘1y’] * df_rates_today.iloc[2] * df_PV01.iloc[2,1]
df[‘2y’] = df[‘2y’] * df_rates_today.iloc[3] * df_PV01.iloc[3,1]
df[‘3y’] = df[‘3y’] * df_rates_today.iloc[4] * df_PV01.iloc[4,1]
df[‘4y’] = df[‘4y’] * df_rates_today.iloc[5] * df_PV01.iloc[5,1]
df[‘5y’] = df[‘5y’] * df_rates_today.iloc[6] * df_PV01.iloc[6,1]
df[‘7y’] = df[‘7y’] * df_rates_today.iloc[7] * df_PV01.iloc[7,1]
df[‘10y’] = df[‘10y’] * df_rates_today.iloc[8] * df_PV01.iloc[8,1]

· Next we sum the individual rows in the resulting DataFrame and store it a new column. We will subsequently sort this new column in the descending order. We need to sort in the descending order because we are looking for the 2nd worst observation from this time series. We are assuming that we compute the 99% 1-day VaR therefore we will be looking for the 2nd worst observation.

df[‘VaR’] = df.sum(axis=1)
VaR_Portfolio = df.sort_values(‘VaR’)
print (“Value at Risk of the Fixed Income portfolio:”,abs(VaR_Portfolio.iloc[1,9]))

The above result will give the 99% 1 day VaR for our Fixed income portfolio. The above model in Python is expected to function as a fast calculator for approximating the VaR of the fixed income book. In case we would be interested in 95% 1 day VaR, we just need to tweak the final code snippet a bit for looking up the right observation from the sorted list.