1
$\begingroup$

I have used QuantLib Python to compute 1-month forward rates from zero rates as at 05 December 2019.

My codes can be found below:

import QuantLib as ql

calendar = ql.NullCalendar()
compounding = ql.Compounded
day_convention = ql.Actual360()
valuation_date = ql.Date(5, 12, 2019)
ql.Settings.instance().evaluationDate = valuation_date
dates = [calendar.advance(valuation_date, ql.Period(n, ql.Years)) for n in range(0, 4, 1)]
zero_rates = [0.01, 0.02, 0.03, 0.05]
zero_curve = ql.ZeroCurve(dates, zero_rates, day_convention)
forward_term_structure = ql.YieldTermStructureHandle(zero_curve)
forward_term_structure.enableExtrapolation()
forward_rates_quantlib = []
value_dates = []
maturity_dates = []
discount_factor_value_dates = []
discount_factor_maturity_dates = []
year_frac_value_maturity_dates = []

for date in dates:
    value_date = date
    value_dates.append(value_date)
    maturity_date = date + ql.Period('1M')
    maturity_dates.append(maturity_date)
    forward_rate = forward_term_structure.forwardRate(value_date, maturity_date, day_convention, compounding).rate()
    forward_rates_quantlib.append(forward_rate)
    discount_factor_value_date = zero_curve.discount(value_date)
    discount_factor_value_dates.append(discount_factor_value_date)
    discount_factor_maturity_date = zero_curve.discount(maturity_date)
    discount_factor_maturity_dates.append(discount_factor_maturity_date)
    year_frac_value_maturity_date = day_convention.yearFraction(value_date, maturity_date)
    year_frac_value_maturity_dates.append(year_frac_value_maturity_date)
    
import pandas as pd
manual_calculation = pd.DataFrame()
manual_calculation['Value_Date'] = value_dates
manual_calculation['Discount_Factor_Value_Date'] = discount_factor_value_dates
manual_calculation['Maturity_Date'] = maturity_dates
manual_calculation['Discount_Factor_Maturity_Date'] = discount_factor_maturity_dates
manual_calculation['Year_Frac_Value_Maturity'] = year_frac_value_maturity_dates
manual_calculation['Forward_Rate_QuantLib'] = forward_rates_quantlib

forward_rates_manual = []

for i in range(0, len(manual_calculation), 1):
    df_value = manual_calculation.loc[i, 'Discount_Factor_Value_Date']
    df_mat = manual_calculation.loc[i, 'Discount_Factor_Maturity_Date']
    year_frac = manual_calculation.loc[i, 'Year_Frac_Value_Maturity']
    forward_rates_manual.append(((df_value/df_mat) - 1) * (1/year_frac))
    
manual_calculation['Forward_Rate_Manual'] = forward_rates_manual

import matplotlib.pyplot as plt  
plt.plot(zero_rates, 'o-', label = "Spot")
plt.plot(forward_rates, 'o-', label = "1M Forward (QuantLib)")
plt.plot(forward_rates_manual, 'o-', label = "1M Forward (Manual)")
plt.legend()

As can be seen from the list forward_rates_manual, I have tried to recompute the 1-month forward rates manually using the following formula:

where

means discount factor from value date to valuation date

means discount factor from maturity date to valuation date, where maturity date is value date plus 1 month, and

means the year fraction between value date and maturity date.

However, when I compare forward_rates_quantlib with forward_rates_manual, I can see slight differences arising, and I cannot seem to understand where these come from.

Grateful for any clarification, thanks.

$\endgroup$
1
  • 1
    $\begingroup$ I have found the solution finally. The difference lies in the compounding method. In my codes, I have stated yearly compounding (ql.Compounded), but in my manual computation, my mathematical formula is following a simple rate calculation mode. $\endgroup$ Commented Aug 4, 2021 at 12:47

1 Answer 1

-1
$\begingroup$
import QuantLib as ql

calendar = ql.NullCalendar()
compounding = ql.Compounded
day_convention = ql.Actual360()
valuation_date = ql.Date(5, 12, 2019)
ql.Settings.instance().evaluationDate = valuation_date
dates = [calendar.advance(valuation_date, ql.Period(n, ql.Years)) for n in range(0, 4, 1)]
zero_rates = [0.01, 0.02, 0.03, 0.05]
zero_curve = ql.ZeroCurve(dates, zero_rates, day_convention)
forward_term_structure = ql.YieldTermStructureHandle(zero_curve)
forward_term_structure.enableExtrapolation()
forward_rates_quantlib = []
value_dates = []
maturity_dates = []
discount_factor_value_dates = []
discount_factor_maturity_dates = []
year_frac_value_maturity_dates = []

for date in dates:
    value_date = date
    value_dates.append(value_date)
    maturity_date = date + ql.Period('1M')
    maturity_dates.append(maturity_date)
    forward_rate = forward_term_structure.forwardRate(value_date, maturity_date, day_convention, compounding).rate()
    forward_rates_quantlib.append(forward_rate)
    discount_factor_value_date = zero_curve.discount(value_date)
    discount_factor_value_dates.append(discount_factor_value_date)
    discount_factor_maturity_date = zero_curve.discount(maturity_date)
    discount_factor_maturity_dates.append(discount_factor_maturity_date)
    year_frac_value_maturity_date = day_convention.yearFraction(value_date, maturity_date)
    year_frac_value_maturity_dates.append(year_frac_value_maturity_date)

import pandas as pd

manual_calculation = pd.DataFrame()
manual_calculation['Value_Date'] = value_dates
manual_calculation['Discount_Factor_Value_Date'] = discount_factor_value_dates
manual_calculation['Maturity_Date'] = maturity_dates
manual_calculation['Discount_Factor_Maturity_Date'] = discount_factor_maturity_dates
manual_calculation['Year_Frac_Value_Maturity'] = year_frac_value_maturity_dates
manual_calculation['Forward_Rate_QuantLib'] = forward_rates_quantlib
manual_calculation['ZC'] = zero_rates

forward_rates_manual = []

for i in range(0, len(manual_calculation), 1):
    df_value = manual_calculation.loc[i, 'Discount_Factor_Value_Date']
    df_mat = manual_calculation.loc[i, 'Discount_Factor_Maturity_Date']
    year_frac = manual_calculation.loc[i, 'Year_Frac_Value_Maturity']
    forward_rates_manual.append(((df_value / df_mat) - 1) * (1 / year_frac))

manual_calculation['Forward_Rate_Manual'] = forward_rates_manual
manual_calculation= manual_calculation.set_index('Value_Date')
import matplotlib.pyplot as plt

manual_calculation[['ZC','Forward_Rate_Manual','Forward_Rate_QuantLib']].plot()
plt.legend()
plt.show()
$\endgroup$
1
  • $\begingroup$ This code is substantially the same as the above, with 4 lines of debugging code added near the end. $\endgroup$
    – nbbo2
    Commented Oct 11 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.