【发布时间】:2021-09-20 04:30:33
【问题描述】:
我试图弄清楚如何使用 QuantLib 的价格来估算债券收益率。有很多不同的例子,但我仍然找不到正确的解决方案。
我有一只将于 2039 年 3 月到期的债券,每 182 天支付一次息票。我将使用 QuantLib 进行的计算与来自 Bloomberg 和 Exchange 的数据进行比较。
代码如下:
issueDate = ql.Date(19,6,2019) #05.06.2019
maturityDate = ql.Date(16,3,2039) #16.03.2039
cpn_freq = 2
tenor = ql.Period('26W') #ql.Period(ql.Semiannual)
calendar = ql.Russia()
businessConvention = ql.Following
#businessConvention = ql.Unadjusted
dateGeneration = ql.DateGeneration.Backward
monthEnd = False
schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, businessConvention, businessConvention,
dateGeneration, monthEnd)
dayCount = ql.Actual365Fixed()
#settings for bond
compounding = ql.Compounded
cleanPrice = 105.45
ytm = 0.0728
couponRate = 0.077
coupons = [couponRate]
settlementDays = 1
faceValue = 100
fixedRateBond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)
for c in fixedRateBond.cashflows():
print('%20s %12f' % (c.date(), c.amount()))
它产生与 Bloomberg 相似的结果(相同的票息日期和金额 - 3.839):
October 9th, 2019 2.658082
April 8th, 2020 3.839452
October 7th, 2020 3.839452
April 7th, 2021 3.839452
October 6th, 2021 3.839452
April 6th, 2022 3.839452
October 5th, 2022 3.839452
April 5th, 2023 3.839452
October 4th, 2023 3.839452
April 3rd, 2024 3.839452
October 2nd, 2024 3.839452
April 2nd, 2025 3.839452
October 1st, 2025 3.839452
April 1st, 2026 3.839452
September 30th, 2026 3.839452
March 31st, 2027 3.839452
September 29th, 2027 3.839452
March 29th, 2028 3.839452
September 27th, 2028 3.839452
March 28th, 2029 3.839452
September 26th, 2029 3.839452
March 27th, 2030 3.839452
September 25th, 2030 3.839452
March 26th, 2031 3.839452
September 24th, 2031 3.839452
March 24th, 2032 3.839452
September 22nd, 2032 3.839452
March 23rd, 2033 3.839452
September 21st, 2033 3.839452
March 22nd, 2034 3.839452
September 20th, 2034 3.839452
March 21st, 2035 3.839452
September 19th, 2035 3.839452
March 19th, 2036 3.839452
September 17th, 2036 3.839452
March 18th, 2037 3.839452
September 16th, 2037 3.839452
March 17th, 2038 3.839452
September 15th, 2038 3.839452
March 16th, 2039 3.839452
March 16th, 2039 100.000000
但是,尝试计算 YTD 会给出错误的数字:
fixedRateBond.bondYield(cleanPrice, dayCount, ql.Compounded, ql.Semiannual) * 100
7.170206456184388
但应该是 7.28%。如果我尝试改用:
fixedRateBond.bondYield(cleanPrice, dayCount, ql.Compounded, ql.Period('26W')) * 100
我遇到了一个错误:
Possible C/C++ prototypes are:
Bond::yield(DayCounter const &,Compounding,Frequency,Real,Size)
Bond::yield(DayCounter const &,Compounding,Frequency,Real)
Bond::yield(DayCounter const &,Compounding,Frequency)
Bond::yield(Real,DayCounter const &,Compounding,Frequency,Date const &,Real,Size)
Bond::yield(Real,DayCounter const &,Compounding,Frequency,Date const &,Real)
Bond::yield(Real,DayCounter const &,Compounding,Frequency,Date const &)
Bond::yield(Real,DayCounter const &,Compounding,Frequency)
更新: 如果与实际 ytm 一起使用,看起来 clearPrice 和 dirtyPrice 也会产生错误的结果。但至少有一种解决方法(来自 CookBook)使用曲线来获得 clearPrice 和 dirtyPrice 的正确数字。但我仍然很难为 YTM 找到正确的号码。
bond_yield = fixedRateBond.bondYield(cleanPrice, dayCount, compounding, ql.Semiannual )* 100
bond_dp = fixedRateBond.dirtyPrice(ytm, dayCount, ql.Compounded, ql.Semiannual)
bond_cp = fixedRateBond.cleanPrice(ytm, dayCount, ql.Compounded, ql.Semiannual)
bond_dur = ql.BondFunctions.duration(fixedRateBond,0.0731,dayCount, ql.Compounded,ql.Semiannual, ql.Duration.Modified)
print('Yield: ' + str(bond_yield)) #ql.Period('26W')
print('Dirty price: ' + str(bond_dp))
print('Clean price: ' + str(bond_cp))
print('Accrued amount: ' + str(fixedRateBond.accruedAmount()))
print('Day counter: ' + str(fixedRateBond.dayCounter()))
print('Settlement date: ' + str(fixedRateBond.settlementDate()))
print('Dutation: ' + str(bond_dur))
print('Using curve')
flat_curve = FlatForward(fixedRateBond.settlementDate(), ytm, dayCount, Compounded)
engine = DiscountingBondEngine(YieldTermStructureHandle(flat_curve))
fixedRateBond.setPricingEngine(engine)
P2 = fixedRateBond.dirtyPrice()
print('Dirty price: ' +str(P2))
print('Cleand price: '+str(fixedRateBond.cleanPrice()))
print('YTM:' + str(fixedRateBond.bondYield(dayCount, Compounded,2)))
Yield: 7.150867552757262
Dirty price: 106.15244992161799
Clean price: 104.12724444216592
Accrued amount: 2.0252054794520635
Day counter: Actual/365 (Fixed) day counter
Settlement date: July 12th, 2021
Duration: 9.550427694884139
Using curve:
Dirty price: 107.46228302550196
Clean price: 105.43707754604989
YTM:0.07152117539749295
【问题讨论】: