I am trying to calculate the zero rate for a piecewise linear zero curve. I have the following deposit on the short end

  • STIBOR 1D, is identified as a tomorrow next deposit: 0.02416
  • STIBOR 3 Month: 0.02701

I then use the very nice package QuantLib to find the continuous zero rates:

from datetime import datetime, date, timedelta
import pandas as pd
date_today = datetime(2022,12,30)
# Set the date today
ql_date_today = ql.Date(date_today.strftime("%Y-%m-%d"), "%Y-%m-%d") #
ql.Settings.instance().evaluationDate = ql_date_today 
helpers = []
depositRates = [0.02416, 0.02701]
depositMaturities = ['1D', '3M']
calendar = ql.Sweden()
fixingDays = 2
endOfMonth = False 
convention = ql.ModifiedFollowing
dayCounter = ql.Actual360()
for r,m in zip(depositRates, depositMaturities):
    if m == '1D':
        fixingDays = 1 
        convention = ql.Following
    elif m == '3M':
        convention = ql.Following
        fixingDays = 2
curve1 = ql.PiecewiseLinearZero(0, ql.TARGET(), helpers, ql.Actual365Fixed())

def ql_to_datetime(d):
    return datetime(d.year(), d.month(), d.dayOfMonth())
def calc_days(maturity, date_now = date_today):
    return  (maturity-date_now).days
dates, rates = zip(*curve1.nodes())
dates = list(map(ql_to_datetime, dates))
days = list(map(calc_days, dates))
df = pd.DataFrame(dict({"Date": dates, "Rate": rates, "Days" : days}))

The result from QuantLib is:

Date Rate Days
0 2022-12-30 00:00:00 0.0244947 0
1 2023-01-03 00:00:00 0.0244947 4
2 2023-04-03 00:00:00 0.027174 94

Now I wish to recreate the values that Quantlib produces, given that the curve is bootstrapped with actual 365. For the first deposit I use the simple rate, $DF = \frac{1}{1+RT}$, to calculate the discount factor (I also find it interesting that the daycount convention that gives the matching result to Quantlib is given by 1/360, when my intuition tells me it should be 4/360 given the maturity date):

$$ DF_1 = \frac{1}{1+0.02416 \cdot \frac{1}{360}} \approx 0.999932893 . $$

Then the continuous zero rate becomes:

$$ r_1 = -365/1 \cdot \ln (DF_1) \approx 0.02449473. $$

Moreover, if we continue with the second rate we obtain the following discount factor:

$$ DF_2 = \frac{0.999932893 }{1+0.02701 \cdot \frac{94}{360}} \approx 0.99293014. $$

At last the continuous zero rate for the second deposit is

$$ r_1 = -365/94 \cdot \ln (DF_2) \approx 0,02754960 . $$

Thus, the results that I get by calculating the zero rates manually for the second deposit does not really match QuantLib's result so I know I am doing my calculations wrong. I have tried to dig in the c++ source code in Quantlib with no success. I have also tried to change the maturity dates in the calculations but still I have not found a matching value for the deposits. I would be glad for any help or pointers.


1 Answer 1


I found the answer after extensive digging in this forum, particularly what gave me the answer was the following post How does bloomberg calculate the discount rate from EUR estr curve? [closed].

Thus, for the second deposit let $T_s$, $T_e$ denote the start and end of the deposit respectively. Then allow $t$ be the time of the you wish to calculate the discount factor. Given the holidays during 2022-12-30 we set $T_s = 4$ and $T_e = 94$. Further we consider $t = 0$. Then the solution we are after is given by:

$$ r_2 = -\frac{365}{T_e-T_s} \cdot \log ( \frac{DF(t,T_s)}{1+R \cdot (T_e - T_s)/360} ). $$

If we continue with calculating $DF(t, T_s)$ we obtain

$$ DF(t, T_s) = e^{(-r_1 \cdot (T_s -t) / 365)} = e^{(-r_1 \cdot (4 -0) / 365)} \approx 0.9997316. $$

Then the final result is

$$ r_2 = -\frac{365}{94-4} \cdot \log ( \frac{0.9997316}{1+0.02701 \cdot (94 - 4)/360} ) \approx 0.0271740. $$


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