Discount factors, present value and duration¶
Problem¶
On a half-yearly schedule up to five years, build the discount factors for a flat 2% rate and
for an upward-sloping rate curve (exercise 44). Then, for five assets whose cash flows are
stored in Exercise_17.mat, compute present value and duration under both curves, and the
duration of a portfolio of them (exercise 45).
Method¶
\[
v(t) = (1 + i(t))^{-t}, \qquad PV = C\, v^\top, \qquad
D = \frac{C\,(t \circ v)^\top}{C\, v^\top}
\]
where each row of \(C\) is one asset's cash flows. For a portfolio with quantities \(q\), the same formula applies to the combined flows \(q\,C\).
The five assets are: a zero-coupon bond at 6 months, one at 1 year, and bonds with half-yearly coupons maturing at 2, 3 and 5 years.
Code¶
clear all, clc
t = 0.5 : 0.5 : 5; % time schedule (years)
% Point 1
i = 0.02; % flat (annual) interest rate
v = (1 + i).^ -t; % discount factor vector
% Point 2
i_tilde = [0.008, 0.010, 0.015, 0.018, 0.025, ...
0.031, 0.037, 0.040, 0.045, 0.047]; % floating (annual) interest rate curve (one rate per maturity)
v_tilde = (1 + i_tilde).^ -t % discount factor vector
clear all, clc
% inputs from exercise 44
t = 0.5:0.5:5; % time schedule (years)
i = 0.02;
v = (1 + i).^ -t;
i_tilde = [0.008, 0.010, 0.015, 0.018, 0.025, ...
0.031, 0.037, 0.040, 0.045, 0.047];
v_tilde = (1 + i_tilde).^ -t;
% Point 1
load('Exercise_17.mat');
% Present Value with flat yield curve
PV_flat = C * v'
% Present Value with non-flat yield curve
PV_nonflat = C * v_tilde'
% Point 2
% Duration of the five assets with a flat yield curve
D_flat = (C * (t .* v)') ./ (C * v') % numerator: present values weighted by time
% denominator: present value of all the cash flows
% Duration of the five assets with a non-flat yield curve
D_nonflat = (C * (t .* v_tilde)') ./ (C * v_tilde')
% Point 3
q = [50, 100, 70, 80, 30];
% Duration of portfolio q with a flat yield curve
D_portq_flat = (q * C * (t .* v)') ./ (q * C * v')
% Duration of portfolio q with a non-flat yield curve
D_portq_nonflat = (q * C * (t .* v_tilde)') ./ (q * C * v_tilde')
import numpy as np
t = np.arange(0.5, 5.01, 0.5) # MATLAB: t = 0.5 : 0.5 : 5 (time schedule, years)
# %% Point 1
i = 0.02 # flat (annual) interest rate
v = (1 + i) ** -t # discount factor vector
# %% Point 2
i_tilde = np.array([0.008, 0.010, 0.015, 0.018, 0.025,
0.031, 0.037, 0.040, 0.045, 0.047]) # one rate per maturity
v_tilde = (1 + i_tilde) ** -t # discount factor vector
print("v_tilde =", v_tilde)
import numpy as np
from scipy.io import loadmat # to read MATLAB .mat files
# inputs from exercise 44
t = np.arange(0.5, 5.01, 0.5)
i = 0.02
v = (1 + i) ** -t
i_tilde = np.array([0.008, 0.010, 0.015, 0.018, 0.025,
0.031, 0.037, 0.040, 0.045, 0.047])
v_tilde = (1 + i_tilde) ** -t
# %% Point 1
C = loadmat('Exercise_17.mat')['C'] # MATLAB: load('Exercise_17.mat') (C = cash flows, one row per asset)
# Present Value with flat yield curve
PV_flat = C @ v # MATLAB: C * v'
print("PV_flat =", PV_flat)
# Present Value with non-flat yield curve
PV_nonflat = C @ v_tilde
print("PV_nonflat =", PV_nonflat)
# %% Point 2
# Duration of the five assets with a flat yield curve
D_flat = (C @ (t * v)) / (C @ v) # numerator: present values weighted by time
print("D_flat =", D_flat)
# Duration of the five assets with a non-flat yield curve
D_nonflat = (C @ (t * v_tilde)) / (C @ v_tilde)
print("D_nonflat =", D_nonflat)
# %% Point 3
q = np.array([50, 100, 70, 80, 30])
# Duration of portfolio q with a flat yield curve
D_portq_flat = (q @ C @ (t * v)) / (q @ C @ v)
print("D_portq_flat =", D_portq_flat)
# Duration of portfolio q with a non-flat yield curve
D_portq_nonflat = (q @ C @ (t * v_tilde)) / (q @ C @ v_tilde)
print("D_portq_nonflat =", D_portq_nonflat)
Results¶
| Asset | PV, flat 2% | PV, curve | Duration, flat | Duration, curve |
|---|---|---|---|---|
| ZCB 6 months | 99.01 | 99.60 | 0.50 | 0.50 |
| ZCB 1 year | 98.04 | 99.01 | 1.00 | 1.00 |
| Bond 2 years | 98.07 | 98.46 | 1.99 | 1.98 |
| Bond 3 years | 98.58 | 95.58 | 2.94 | 2.94 |
| Bond 5 years | 100.52 | 89.07 | 4.77 | 4.75 |
Portfolio duration: 1.95 years with the flat rate, 1.91 with the curve.
Takeaways¶
- A zero-coupon bond's duration is its maturity; coupons pull the duration below maturity.
- The curve is below 2% at short maturities and above it at long ones, so it raises the value of short assets and cuts the 5-year bond from 100.52 to 89.07.
- Portfolio duration is the value-weighted average of the assets' durations, which is why it can be computed on the combined cash flows in one step.