1
$\begingroup$

Dollar duration $DV01$ is defined as negative of the price of the bond wrt yield:

$$DV01 = - \frac{\partial P}{\partial y}.$$

As we know that $P = \sum_{t=1}^{n} \frac{CF_{t}}{(1+y)^{t}}$, then

$$DV01 = - \sum_{t=1}^{n} t \frac{CF_{t}}{(1+y)^{t+1}}.$$

Now, as cash-flow stream ($\{CF\}_{t}$) is predetermined, then using current yield curve, one can compute $DV01$. I call this formula as a theoretical value for $DV01$, as it does not capture empirical relationship between price and yield of the bond.

Questions: 1) Do practitioners use the above theoretical formula to compute $DV01$? 2) More importantly, isn't empirically estimated $DV01$ through regression ($P_{t} = \alpha +\beta y_{t} + \epsilon_t$) describe price-yield relationship better than the theoretical formula above?

P.S. The formulation of the question is in the context of $DV01$, but it is relevant for all variations of duration.

$\endgroup$
4
  • $\begingroup$ Your linear regression equation looks to estimate price at time $t$ as a linear function of yield at time $t$ -- assuming you mean to estimate change in price at time $t$ as a linear function of change in yield at time $t$? $\endgroup$
    – Rylan
    Commented Apr 30 at 13:20
  • $\begingroup$ The $\beta$ coefficient in the above equation has the following interpretation: 1bp change (increase/decrease) impact on price level. In other words, how much would price of the bond change if yield changes by 1bp. $\endgroup$
    – Sane
    Commented Apr 30 at 13:23
  • $\begingroup$ Right, but what I'm saying is just mechanically, if you try to find a linear relationship between bond prices and yields, you will likely have trouble. If you try to find a linear relationship between changes in bond prices and small changes in yield over a short period of time, you'll likely have better luck $\endgroup$
    – Rylan
    Commented Apr 30 at 13:31
  • $\begingroup$ Agree ... I will have troubles if i try to fit a linear model when price series is not stationary. Indeed, specification of the model is secondary in the context of my question. I can easily modify it. $\endgroup$
    – Sane
    Commented Apr 30 at 13:35

2 Answers 2

5
$\begingroup$

Question 1: Not that often, usually finite difference is use to compute it (bump and reprice). See for example this complete step by step explanation of Bloomberg's DV01 computation in SWPM. Practically, its the same though.

Question 2: No, because DV01 is an exact linear approximation to the price yield function already. That is similar to the Greek Delta in option pricing, where no one uses some sort of regression to estimate the change of the option value with respect to a change in the price of the underlying either.



TL;DR

You correctly define the price of a bond as the discounted cashflows. Insofar, I am a bit puzzled by your question. As you showed, yield and price have a direct relationship. Demand and supply changes will change price, and hence yield accordingly. A simple example with code for US T-bills can be found here.

(Modified) duration, is a mathematical derivative (rate of change) of price and measures the percentage rate of change of price with respect to yield. DV01 is the same thing measured in absolute (dollar) terms.

Let's look at the bond price formula on Wikipedia

\begin{matrix} \left(\frac{C}{1+i}+\frac{C}{(1+i)^2}+ ... +\frac{C}{(1+i)^N}\right) + \frac{M}{(1+i)^N} \end{matrix} \begin{matrix} \left(\sum_{n=1}^N\frac{C}{(1+i)^n}\right) + \frac{M}{(1+i)^N} \end{matrix} \begin{matrix} C\left(\frac{1-(1+i)^{-N}}{i}\right)+M(1+i)^{-N} \end{matrix}

C  = coupon payment (periodic interest payment)
N = number of payments 
i = market interest rate, or required yield, or observed / appropriate yield to maturity
M = value at maturity, usually equals face value (Nominalwert)
P = market price of bond

Put in Python this looks like this

M = 1000 # nominal value
coupon = 0.05 # pct per period
c = coupon*M
i = 0.1 # YTM
N = 3 # periods

p = c*((1 - (1+i)**-N)/i)  + M/(1+i)**N

yielding a price of ~875.66 in this example. Now, YTM is usally derived from a market quoted price. For this, you need some solver. It's relatively straighforward to use Newton Raphson in this example.

# Finding the yield of a coupon bearing bond 
def newtonRaphson(m,p,t,c,r,f,epsilon=0.00001):        
    def fx(r):
        cum = 0
        red = m*(1+(r/100/f))**(-t*f)
        for i in range(1,t*f+1):
            cum += c/f*(1+(r/100/f))**(-i)
        cum += red    
        return p-cum

    def fxdx(r):
        cum = 0
        red = t*m*(1+(r/100/f))**-(t*f+1)
        for i in range(1,t*f+1):
            T = i/f
            cum += t*c/f*(1+(r/100/f))**-(i+1)
        cum += red
        return cum
    
    x_n = r
    i = 1
    while abs(fx(x_n)) > epsilon:
        x_next = x_n/100 - fx(x_n)/fxdx(x_n)
        x_n = x_next*100
        print('Guess {}: {}'.format(i, round(x_n,5)))
        i += 1
        if i > 10:
            print('No solution found.')
            break
    ytm = round(x_n,6)
    return ytm

enter image description here

Not surprisingly, this matches the yield we used to compute the price before.

Now that we established how YTM and prices are related to each other we an look at this in a more generic way. I often find charts intuitive.

def bond_price(N,i,M,c,f):
    return ((M*c/f*(1-(1+i/f)**(-f*N)))/(i/f)) + M*(1+(i/f))**(-f*N)

freq = 1
bond_price(N,i,M, coupon,freq)

freq = 2 # payments per year (semi annual)
N = 20 # maturity in years 
int_changes = np.arange(start=0.001, stop=0.14, step=0.001)  
M = 1000 # Nominal
c= 0.05 # 5% coupon

[plt.plot(int_changes, bond_price(i ,int_changes,M,c, freq), label = f'Bond with {i} year(s) maturity') for i in np.arange(start=1, stop=32, step=10)]
plt.xlabel("YTM")
plt.ylabel("Bond price")
plt.title('Bond prices as a function of interest rates')
plt.axvline(x=0.05, color='black', linestyle='-.', linewidth = 0.4)
plt.axvline(x=0.02, color='black', linestyle='-.', linewidth = 0.4)
plt.axhline(y=1688, color='c', linestyle='-', linewidth = 0.4)

plt.legend(prop={'size': 10})
plt.show()

enter image description here

Duration is just a linear approximation to this curve, similar to how delta works for options (see here). Implementing the formula in Wikipedia you compute it as such.

M = 100 
c = 0.07
freq = 1
N = 5
r = 0.07  
year = [i for i in range(1,N+1)]
Cashflow = [round(M * c, 3) if i < N else 100 +  round(M * c, 3) for i in range(1,N+1)]
dcf_t = [f"1/((1+{r})^{i})" for  i in range(1,N+1)]
dcf = [round(1/((1+r)**i), 5) for  i in range(1,N+1)]
cf_weighted = [i*round(M * c, 3) * round(1/((1+r)**i), 5) if i < N else  i*(100 + round(M * c, 3)) * round(1/((1+r)**i), 5)for  i in range(1,N+1) ]
cf_disc = [round(M * c, 3) * round(1/((1+r)**i), 5) if i < N else  (100 + round(M * c, 3)) * round(1/((1+r)**i), 5)for  i in range(1,N+1) ]


df = pd.DataFrame({"Year" : year, "Cashflow" : Cashflow, "Discount Formula" : dcf_t,  "Discount Factor" : dcf,  "NPV Weighted CF" :  cf_weighted, "NPV CF" :  cf_disc})
df

enter image description here

Using a free online bond calculator or WolframAlpha provides identical values.

enter image description here

Computing MD via finite difference (similar to how BBG computes DV01 and the delta example linked above) works like this. $$ Modified Duration = \frac{P^{-} - P^{+}}{2*P_0*dY}$$

where $dY$ is difference in the interest rate / YTM (frequently 100bp)
$P^{-}$ Price of bond if rates down
$P^{+}$ Price of bond if rates up
$P_0$ Market value of bond

enter image description here

Adding duration to the chart above looks like this

int_changes = np.arange(start=0.001, stop=0.14, step=0.001)  
plt.plot(int_changes, bond_price(N ,int_changes,M,c, freq), label = f'Bond with {N} year(s) maturity') 
plt.plot(int_changes,  [bond_price(N,r,M, c,freq) - duration/(1+r)*i*100 + duration/(1+r)*r*100 for i in int_changes], label = f'Duration approximation', linestyle='dashdot')
plt.xlabel("YTM")
plt.ylabel("Bond price")
plt.title('Bond prices as a function of interest rates')
plt.axvline(x=r, color='black', linestyle='-.', linewidth = 0.4)
plt.axhline(y=bond_price(N,r,M, c,freq), color='c', linestyle='-', linewidth = 0.4,  label = f'Market price for YTM = {r}' )
plt.legend(prop={'size': 10})
plt.show()

enter image description here



Question 2:

So what about your linear regression idea? You are essentially proposing to use a linear functional form for a convex function. Our example already computed a few observation. Therefore, we can quickly use statsmodel to write the following Python code which implements your idea with our example from above. As you can see, the slope is actually quite similar to the duration we just computed (in absolute values).

x = int_changes
y = bond_price(N ,int_changes,M,c, freq)
model = sm.OLS(y, sm.add_constant(x))
results = model.fit()
results.summary()

enter image description here

Charting this with a scatter plot also shows the similarity (just add plt.axline(xy1=(0, b), slope=m, label=f'$y = {b:+.1f} {m:.1f}x $', color='r') to the chart.

enter image description here

The more pronounced convexity (e.g. the longer maturity), the worse your idea gets. enter image description here

As you can see, for a 30 year bond, your linear regression logic is misstating the change in the current price of the bond be quite a bit, whereas DVO1 (duration) is still an exact linear approximation at the point of interest (the current market price).

Of course, you can change the functional form and make the OLS regression fit the curve, but that will really just provide a very similar result to using duration, and adding convexity (or using Delta and adding Gamma in the options example I linked), albeit in a more convoluted way, and adding estimation errors.

$\endgroup$
2
  • $\begingroup$ This is a great answer, thank you! Just a clarifying question: in practice do yields one-to-one reflect price changes? $\endgroup$
    – Sane
    Commented May 1 at 7:21
  • $\begingroup$ Glad it helped. Yes, yields and prices are always directly connected. $\endgroup$
    – AKdemy
    Commented May 1 at 15:10
2
$\begingroup$

A few thoughts:

  1. At time $t$, in this setup, price and yield to maturity (which I assume we're talking about as there's no time "attached" to $y$) are "equivalent" in the sense that if we know the yield, we can figure out the price exactly, and vice versa. (semi-mathematically, there is a bijection between price and yield for a given bond at time $t$). In that sense, using the derivative or some other Taylor expansion to estimate change in price is appropriate.
  2. The impact of a rate (being general here, not necessarily a YTM!) change can be very different over different times to maturity. Even for YTM, you expect a big impact on price if bonds are maturing in a long time, and a small impact if maturity is soon. If your training set contains one bond observed at 30 years, 30 years - 1 day, ... 29 years, it's probably fine, but if you observe a bond with one year to maturity ,364 days, ... 2 days, then your yield ~ price impact will look very different in your observations
  3. IIRC, empirical DV01 is most useful for, say, a corporate bond, which we can imagine is priced on a government yield curve + a spread. I'm no expert in this part, but you could try estimating the corporate yield change as a function of the government yield change, and then say (for example) that if the government curve rises 1bp then the corporate curve rises $\beta$bp, so as long as beta is fairly small then you could estimate change in bond price for a change in government yield by using "theoretical DV01" $\times \beta$

As always with fixed income, the devil is in the details! these are just a few thoughts

$\endgroup$
3
  • 1
    $\begingroup$ Regarding point #1. I can imagine that mathematically having price implies having yield through the function of the price (as described above). However, is this the case in practice? Isn't it possible to have 1bp increase/decrease in yield but not proportional change in price? (due to some demand-supply market mechanisms, or other factors that did not shift price) $\endgroup$
    – Sane
    Commented Apr 30 at 13:58
  • 2
    $\begingroup$ Good question -- if we're talking about $y$ as the yield to maturity, then that's how $y$ is defined -- loosely it's "the discount rate that makes $P$ equal to the sum of discounted cashflows". So the estimation of price change as yield change * DV01 will be good (it won't be exact, but you can make it arbitrarily good by adding higher order terms to the Taylor expansion). But its a sort of "tail wagging the dog" situation, as the yield is directly observable from the price $\endgroup$
    – Rylan
    Commented Apr 30 at 15:11
  • $\begingroup$ I see, thanks a lot! $\endgroup$
    – Sane
    Commented May 1 at 9:46

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.