Bond
簡單的 QuantLib 債券數學
我是 QuantLib 的新手,正試圖讓它複製一些簡單的債券數學。
假設我們有一張 5 年期債券,年票面金額為 5美元,面值為 100美元,利率為 4%。經典計算得出債券的現值為104.45美元。當我嘗試在 QuantLib-Python 中執行這個簡單的範例時,我得到了 104.70 美元——儘管我嘗試去除日曆約定。
我如何使用 QuantLib 來匹配這個簡單的債券數學?
from QuantLib import * # Construct yield curve calc_date = Date(1, 1, 2017) Settings.instance().evaluationDate = calc_date spot_dates = [Date(1,1,2017), Date(1,1,2018), Date(1,1,2027)] spot_rates = [0.0, 0.04, 0.04] day_count = SimpleDayCounter() calendar = NullCalendar() interpolation = Linear() compounding = Compounded compounding_frequency = Annual spot_curve = ZeroCurve(spot_dates, spot_rates, day_count, calendar, interpolation, compounding, compounding_frequency) spot_curve_handle = YieldTermStructureHandle(spot_curve) # Construct bond schedule issue_date = Date(1, 1, 2017) maturity_date = Date(1, 1, 2022) tenor = Period(Semiannual) calendar = NullCalendar() business_convention = Unadjusted date_generation = DateGeneration.Backward month_end = False schedule = Schedule(issue_date, maturity_date, tenor, calendar, business_convention, business_convention, date_generation, month_end) # Create FixedRateBond Object coupon_rate = 0.05 coupons = [coupon_rate] settlement_days = 0 face_value = 100 fixed_rate_bond = FixedRateBond(settlement_days, face_value, schedule, coupons, day_count) # Set Valuation engine bond_engine = DiscountingBondEngine(spot_curve_handle) fixed_rate_bond.setPricingEngine(bond_engine) # Calculate present value value = fixed_rate_bond.NPV() print(value)
首先,正如學生 T 建議的那樣,您可以檢查現金流是否符合您的預期:
for c in fixed_rate_bond.cashflows(): print '%20s %12f' % (c.date(), c.amount()) July 1st, 2017 2.500000 January 1st, 2018 2.500000 July 1st, 2018 2.500000 January 1st, 2019 2.500000 July 1st, 2019 2.500000 January 1st, 2020 2.500000 July 1st, 2020 2.500000 January 1st, 2021 2.500000 July 1st, 2021 2.500000 January 1st, 2022 2.500000 January 1st, 2022 100.000000
他們看起來沒問題,所以問題一定出在貼現曲線上。一個問題是您將其實例化為:
spot_dates = [Date(1,1,2017), Date(1,1,2018), Date(1,1,2027)] spot_rates = [0.0, 0.04, 0.04] ...
但這意味著第一年零利率將在 0.0 和 0.04 之間插值,當然這會給您錯誤的折扣因子;所以你應該使用
spot_dates = [Date(1,1,2017), Date(1,1,2018), Date(1,1,2027)] spot_rates = [0.04, 0.04, 0.04]
反而。不過,這給出了104.67美元的價格,這仍然不是您想要的。下一個問題是您正在以 4% 的利率和年復利頻率初始化曲線;這給你的折扣係數等於 $ B(T) = 1/(1+R)^T $ ,您可以驗證:
for i, c in enumerate(fixed_rate_bond.cashflows()): T = day_count.yearFraction(calc_date, c.date()) B = 1/math.pow(1.04, T) print '%20s %12f %12f %12f %12f' % (c.date(), c.amount(), T, B, spot_curve.discount(c.date())) July 1st, 2017 2.500000 0.500000 0.980581 0.980581 January 1st, 2018 2.500000 1.000000 0.961538 0.961538 July 1st, 2018 2.500000 1.500000 0.942866 0.942866 January 1st, 2019 2.500000 2.000000 0.924556 0.924556 July 1st, 2019 2.500000 2.500000 0.906602 0.906602 January 1st, 2020 2.500000 3.000000 0.888996 0.888996 July 1st, 2020 2.500000 3.500000 0.871733 0.871733 January 1st, 2021 2.500000 4.000000 0.854804 0.854804 July 1st, 2021 2.500000 4.500000 0.838204 0.838204 January 1st, 2022 2.500000 5.000000 0.821927 0.821927 January 1st, 2022 100.000000 5.000000 0.821927 0.821927
由於您有半年一次的優惠券,您可能也想使用半年一次的複利頻率。這給了你折扣因素 $ B(t) = 1/\left(1+\frac{R}{2}\right)^{2T} $ :
for i, c in enumerate(fixed_rate_bond.cashflows()): T = day_count.yearFraction(calc_date, c.date()) B = 1/math.pow(1.02, 2*T) print '%20s %12f %12f %12f %12f' % (c.date(), c.amount(), T, B, spot_curve.discount(c.date())) July 1st, 2017 2.500000 0.500000 0.980392 0.980392 January 1st, 2018 2.500000 1.000000 0.961169 0.961169 July 1st, 2018 2.500000 1.500000 0.942322 0.942322 January 1st, 2019 2.500000 2.000000 0.923845 0.923845 July 1st, 2019 2.500000 2.500000 0.905731 0.905731 January 1st, 2020 2.500000 3.000000 0.887971 0.887971 July 1st, 2020 2.500000 3.500000 0.870560 0.870560 January 1st, 2021 2.500000 4.000000 0.853490 0.853490 July 1st, 2021 2.500000 4.500000 0.836755 0.836755 January 1st, 2022 2.500000 5.000000 0.820348 0.820348 January 1st, 2022 100.000000 5.000000 0.820348 0.820348
通過進一步修正,價格為104.49美元,仍比您預期的高 4 個基點。但此時,您可能還想檢查您的經典計算…