Wie lang ist eine Anleihe wirklich?
Die Laufzeit sagt, wann die letzte Zahlung eintrifft, doch eine Anleihe mit hohen Kupons gibt einen Großteil Ihres Geldes früher zurück. Die Macaulay-Duration ist die durchschnittliche Zeit bis zum Erhalt der Zahlungen, jeder Zahlungszeitpunkt gewichtet mit seinem Anteil am Preis: sum(t * PV(t)) / Preis. Eine Nullkuponanleihe hat eine Duration gleich ihrer Laufzeit; Kupons senken sie. Unsere 10-jährige 5-%-Anleihe bei 6 % Rendite hat eine Duration von 7,9 Jahren. Die Duration ist die wirkliche zeitliche Länge der Anleihe.
import numpy as np
def bond_cashflows(face, coupon_rate, years, freq):
n = int(round(years * freq))
times = np.arange(1, n + 1) / freq
flows = np.full(n, face * coupon_rate / freq)
flows[-1] += face
return times, flows
times, flows = bond_cashflows(1000, 0.05, 10, 2)
pv = flows / (1 + 0.06 / 2) ** (2 * times) # present value of each payment
price = pv.sum()
macaulay = (times * pv).sum() / price # the average time, weighted by present value
print(round(price, 4), round(macaulay, 4)) # 925.6126 7.895 shorter than the 10-year maturityVon der Duration zum Preisrisiko
Die Division durch 1 + ytm / freq ergibt die modifizierte Duration, die eine direkte Bedeutung hat: Sie ist der prozentuale Preisrückgang bei einem Renditeanstieg um eine Einheit (100 Punkte), eine modifizierte Duration von 7,67 heißt also näherungsweise etwa -7,67 % bei +1 Prozentpunkt: dP / P ≈ -D_mod * dy. Diese Zahl nennen Risikoabteilungen als Zinssensitivität der Anleihe. Sie erklärt auch, warum die lange Anleihe des vorigen Themas so viel stärker fiel als die kurze: Ihre Duration ist höher.
modified = macaulay / (1 + 0.06 / 2)
print(round(modified, 4)) # 7.6654 about -7.67% of price for +1 percentage point of yield
dy = 0.01
print(round(price * (1 - modified * dy), 2)) # 854.66 the first-order estimate after a rise to 7%
# the exact price at 7% is 857.88: duration alone underestimates itKonvexität: die Krümmung
Die Preis-Rendite-Beziehung ist eine Kurve, keine Gerade, und die Duration nur ihre Tangente. Die Tangente unterschätzt den Preis bei Bewegungen in beide Richtungen, weil die Kurve nach oben gekrümmt ist: Eine Anleihe gewinnt bei fallenden Renditen mehr, als sie bei einem gleich großen Anstieg verliert. Die Konvexität misst diese Krümmung aus der zweiten Ableitung: sum(Zahlung * t * (t + 1/freq) / (1 + y/freq) ** (freq * t + 2)) / Preis. Der Term 0.5 * Konvexität * dy² zur Duration-Schätzung ergibt eine viel bessere Preisprognose, und er zählt umso mehr, je größer die Bewegung ist.
convexity = (flows * times * (times + 1 / 2) / (1 + 0.06 / 2) ** (2 * times + 2)).sum() / price
print(round(convexity, 3)) # 71.785
for dy in (0.01, -0.01, 0.03):
exact = bond_price(1000, 0.05, 0.06 + dy, 10)
duration_only = price * (1 - modified * dy)
with_convexity = price * (1 - modified * dy + 0.5 * convexity * dy ** 2)
print(dy, round(exact, 2), round(duration_only, 2), round(with_convexity, 2))
# 0.01 857.88 854.66 857.99
# -0.01 1000.0 996.56 999.88
# 0.03 739.84 712.77 742.67 for a big move convexity matters most# Duration by maturity for a 5% bond at a 6% yield: it grows with maturity, but slower than one for one
for years in (1, 5, 10, 30):
t_, f_ = bond_cashflows(1000, 0.05, years, 2)
p_ = f_ / (1 + 0.06 / 2) ** (2 * t_)
print(years, round((t_ * p_).sum() / p_.sum(), 3))
# 1 0.988
# 5 4.472
# 10 7.895
# 30 14.77bond_price.- Macaulay-Duration =
sum(t * PV) / Preis, die durchschnittliche Zeit bis zum Geld; bei einer Nullkuponanleihe ist sie die Laufzeit. - Modifizierte Duration = Macaulay /
(1 + ytm / freq): der relative Preisrückgang bei +1 Rendite,dP / P ≈ -D_mod * dy. - Preisschätzung =
Preis * (1 - D_mod * dy + 0.5 * Konvexität * dy²); der Konvexitätsterm korrigiert die Tangente, vor allem bei großen Bewegungen.
Als Nächstes: Zinskurven und Interpolation, denn unterschiedliche Laufzeiten haben unterschiedliche Zinsen.
Lab: Was bewertet wird
- Mit
macaulay_durationdie durchschnittliche Zeit bis zum Geld finden25 Pkt. - Mit
modified_durationdaraus eine Preissensitivität machen25 Pkt. - Mit
convexitydie Krümmung erfassen25 Pkt. - Mit
price_estimateden neuen Preis ohne Neubewertung vorhersagen25 Pkt.