ما طول السند حقًّا؟
يخبر الاستحقاق متى تصل الدفعة الأخيرة، لكن السند الذي يدفع قسائم كبيرة يعيد جزءًا كبيرًا من مالك أبكر. مدة ماكولاي هي متوسط زمن استلام التدفقات، مع ترجيح كل زمن دفع بحصته من السعر: sum(t * PV(t)) / السعر. وسند بلا قسائم مدته تساوي استحقاقه؛ وتخفضها القسائم. وسندنا لعشر سنوات بقسيمة 5% وعائد 6% مدته 7.9 سنة. المدة هي الطول الحقيقي للسند في الزمن.
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 maturityمن المدة إلى مخاطر السعر
القسمة على 1 + ytm / freq تعطي المدة المعدّلة ولها معنى مباشر: هي نسبة انخفاض السعر لارتفاع العائد بوحدة واحدة (100 نقطة)، فمدة معدّلة 7.67 تعني نحو -7.67% مقابل +1 نقطة مئوية تقريبًا من الدرجة الأولى: dP / P ≈ -D_mod * dy. وهذا الرقم تذكره غرف المخاطر حساسيةً للسند لسعر الفائدة. ويفسّر لماذا هبط السند الطويل في الموضوع السابق أكثر بكثير من القصير: مدته أعلى.
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 itالتحدب: التقوّس
علاقة السعر بالعائد منحنى لا خط مستقيم، والمدة ليست سوى مماسه. ويقلّل المماس من تقدير السعر لحركة في أي من الاتجاهين لأن المنحنى ينحني إلى أعلى: يكسب السند عند هبوط العوائد أكثر مما يخسر عند ارتفاعها بالمقدار نفسه. ويقيس التحدب هذا الانحناء من المشتقة الثانية: sum(flow * t * (t + 1/freq) / (1 + y/freq) ** (freq * t + 2)) / السعر. وإضافة الحد 0.5 * التحدب * dy² إلى تقدير المدة تعطي تنبؤًا أفضل بكثير للسعر، ويزداد أثرها كلما كبرت الحركة.
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 تمامًا.- مدة ماكولاي =
sum(t * PV) / السعر، متوسط الزمن إلى المال؛ ومدة سند بلا قسائم هي استحقاقه. - المدة المعدلة = ماكولاي /
(1 + ytm / freq): الانخفاض النسبي في السعر لكل +1 من العائد،dP / P ≈ -D_mod * dy. - تقدير السعر =
السعر * (1 - D_mod * dy + 0.5 * التحدب * dy²)؛ يصحح حد التحدب المماس، خصوصًا للحركات الكبيرة.
التالي: منحنيات العائد والاستيفاء، لأن لكل استحقاق معدلًا مختلفًا.
المختبر: ما الذي يُقيَّم
- اعثر على متوسط زمن استرداد مالك باستخدام
macaulay_duration25 نقطة - حوّلها إلى حساسية للسعر باستخدام
modified_duration25 نقطة - التقط التقوّس باستخدام
convexity25 نقطة - تنبأ بالسعر الجديد دون إعادة التسعير باستخدام
price_estimate25 نقطة