Net present value and duration of a set of bonds¶
Problem¶
Write a function that returns the net present value and the duration of several assets at once, given their cash flows on a common schedule and a non-flat rate curve (exercise 47). Apply it to four assets over five years (exercise 48).
Method¶
With cash flows in the rows of \(C\), payment dates \(t\) and evaluation date \(t_0\):
\[
v = (1 + \tilde{i})^{-(t - t_0)}, \qquad NPV = C\, v^\top, \qquad
D = \frac{C\,\big((t - t_0) \circ v\big)^\top}{NPV}
\]
Code¶
function [NPV, D] = F_es47(t, t_0, C, i_tilde)
% inputs: t := vector of the schedule
% t_0 := (scalar) starting point of the investment
% C := mxn matrix of cash flows
% i_tilde := non-flat interest rate curve
% outputs: NPV := Net Present Value
% D := Duration
% Refer to row vectors!
v = (1 + i_tilde).^(-(t - t_0)); % discount factor vector (t = payment date, t_0 = evaluation date)
NPV = C * v'; % column vector: one net present value per asset (row of C)
D = (C * ((t - t_0) .* v)') ./ NPV;
end
import numpy as np
from F_es47 import F_es47 # uses the function in F_es47.py (same folder), like F_es47.m
# %% Point 1
t_0 = 0 # by default
t = np.arange(1, 6) # schedule: MATLAB 1:5
C = np.array([[7, 7, 7, 7, 107], # flows matrix
[6, 6, 6, 106, 0],
[0, 0, 100, 0, 0],
[0, 0, 0, 0, 100]])
i_tilde = np.array([.05, .046, .044, .049, .052]) # non-flat yield structure
NPV, D = F_es47(t, t_0, C, i_tilde)
print("NPV =", NPV)
print("D =", D)
import numpy as np
def F_es47(t, t_0, C, i_tilde):
# inputs: t := vector of the schedule
# t_0 := (scalar) starting point of the investment
# C := mxn matrix of cash flows (one row per asset)
# i_tilde := non-flat interest rate curve
# outputs: NPV := Net Present Value
# D := Duration
v = (1 + i_tilde) ** (-(t - t_0)) # discount factor vector
NPV = C @ v # one net present value per asset (row of C)
D = (C @ ((t - t_0) * v)) / NPV
return NPV, D # MATLAB: function [NPV, D] = ...
Results¶
Rate curve: 5.0%, 4.6%, 4.4%, 4.9%, 5.2% for years 1 to 5.
| Asset | Cash flows | NPV | Duration |
|---|---|---|---|
| 7% bond, 5 years | 7, 7, 7, 7, 107 | 108.04 | 4.41 |
| 6% bond, 4 years | 6, 6, 6, 106 | 104.01 | 3.68 |
| Zero-coupon, 3 years | 100 at year 3 | 87.88 | 3.00 |
| Zero-coupon, 5 years | 100 at year 5 | 77.61 | 5.00 |
Takeaways¶
- One matrix product values all the assets together: each row of \(C\) is an asset.
- The zero-coupon bonds confirm the formula: their duration equals their maturity.
- Higher coupons shorten duration, because more of the value arrives early.