Skip to content

Discount factors, present value and duration

Course exercises 44–45 · Part I

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.