【问题标题】:Pricing an Amortizing Floating Rate Bond using QuantLib and Python使用 QuantLib 和 Python 为摊销浮动利率债券定价
【发布时间】:2021-01-01 04:59:39
【问题描述】:

我正在尝试使用 QuantLib Python 为摊销浮动利率债券定价。

下面是我的代码:

notional = [3640875000, 3640875000, 3640875000, 3640875000, 3640875000, 3640875000, 3640875000, 3640875000, 3640875000, 3380812500, 3120750000, 2860687500, 2600625000, 2340562500, 2080500000, 1820437500, 1560375000, 1300312500, 1040250000, 780187500, 520125000, 260062500]
tenor = ql.Semiannual
calendar = ql.UnitedStates()
valuationDate = ql.Date(30, 6, 2020)
ql.Settings.instance().evaluationDate = valuationDate
issueDate = ql.Date(1, 2, 2020)
maturityDate = ql.Date(1, 2, 2031)
spread = 0.0008
schedule = ql.Schedule(issueDate, maturityDate, ql.Period('6M'), ql.UnitedStates(), ql.ModifiedFollowing, ql.ModifiedFollowing, ql.DateGeneration.Forward, False)
myDates = [ql.Date(30,6,2020), ql.Date(3,8,2020), ql.Date(1,2,2021), ql.Date(2,8,2021), ql.Date(1,2,2022), ql.Date(1,8,2022), ql.Date(1,2,2023), ql.Date(1,8,2023), ql.Date(1,2,2024), ql.Date(1,8,2024), ql.Date(3,2,2025), ql.Date(1,8,2025), ql.Date(2,2,2026), ql.Date(3,8,2026), ql.Date(1,2,2027), ql.Date(2,8,2027), ql.Date(1,2,2028), ql.Date(1,8,2028), ql.Date(1,2,2029), ql.Date(1,8,2029), ql.Date(1,2,2030), ql.Date(1,8,2030), ql.Date(3,2,2031)]
fwds = [0.030299999999999997, 0.025, 0.01354543171228029, 0.019589368178700814, 0.01958777464424011, 0.019589368178700814, 0.02057467941338146, 0.025178974367120032, 0.025177220897067684, 0.02517897436712047, 0.02509806907076861, 0.02476222313506464, 0.024759679154385567, 0.02476222313506464, 0.024759679154385567, 0.024762223135064203, 0.024760527109263717, 0.02476222313506464, 0.024759679154385567, 0.024762223135064203, 0.024903682036959026, 0.025577044856498768, 0.025574331077211018]
fwdcurve = ql.ForwardCurve(myDates, fwds, ql.Actual360(), ql.UnitedStates())
fwdhandle = ql.YieldTermStructureHandle(fwdcurve)
index = ql.IborIndex('MyIndex', ql.Period('6M'), 0, ql.USDCurrency(), ql.UnitedStates(), ql.ModifiedFollowing, True, ql.Actual360(), fwdhandle)
index.addFixing(ql.Date(30, 1, 2020), 2.98/100)
amortizingfloatbond = ql.AmortizingFloatingRateBond(0, notional, schedule, index, ql.Actual360(), ql.ModifiedFollowing, 2, [spread])
dates = [ql.Date(30, 6, 2020), ql.Date(30, 12, 2020), ql.Date(30, 6, 2021), ql.Date(30, 6, 2023), ql.Date(30, 6, 2025), ql.Date(30, 6, 2030), ql.Date(30, 6, 2035), ql.Date(30, 6, 2040)] 
zeros = [0.0091, 0.0090, 0.0104, 0.0194, 0.0135, 0.0425, 0.0379, 0.0317]
curve = ql.ZeroCurve(dates, zeros, ql.Actual360(), ql.UnitedStates())
discount_handle = ql.YieldTermStructureHandle(curve)
discount = ql.DiscountingBondEngine(discount_handle)
amortizingfloatbond.setPricingEngine(discount)
for i, cf in enumerate(amortizingfloatbond.cashflows()):
    print((i + 1), cf.date(), cf.amount())`

我根据现有数据构建了我的零曲线和远期曲线,并使用远期利率来构建 ibor 指数,并使用零利率来贴现我的现金流。

以下现金流来自 QuantLib Python:

[1840664583.3333333, 1840664583.3333333, 1840664583.3333333, 1850778125.0, 1830551041.6666667, 1860891666.6666665, 1830551041.6666667, 1860891666.6666665, 1840664583.3333333, 260062500.0, 1746753124.9999998, 260062500.0, 1551706250.0, 260062500.0, 1470075520.8333333, 260062500.0, 1314760416.6666665, 260062500.0, 1183284375.0, 260062500.0, 1051808333.3333333, 260062500.0, 925389062.5, 260062500.0, 788856250.0, 260062500.0, 664604166.6666666, 260062500.0, 523014583.3333333, 260062500.0, 398762499.99999994, 260062500.0, 261507291.66666666, 260062500.0, 134365624.99999997, 260062500.0]

截至以下日期:

[Date(3,8,2020), Date(1,2,2021), Date(2,8,2021), Date(1,2,2022), Date(1,8,2022), Date(1,2,2023), Date(1,8,2023), Date(1,2,2024), Date(1,8,2024), Date(1,8,2024), Date(3,2,2025), Date(3,2,2025), Date(1,8,2025), Date(1,8,2025), Date(2,2,2026), Date(2,2,2026), Date(3,8,2026), Date(3,8,2026), Date(1,2,2027), Date(1,2,2027), Date(2,8,2027), Date(2,8,2027), Date(1,2,2028), Date(1,2,2028), Date(1,8,2028), Date(1,8,2028), Date(1,2,2029), Date(1,2,2029), Date(1,8,2029), Date(1,8,2029), Date(1,2,2030), Date(1,2,2030), Date(1,8,2030), Date(1,8,2030), Date(3,2,2031), Date(3,2,2031)]

截至 2020 年 8 月 3 日的正确现金流应如下所示: ((0.025 * (34/360)) + 0.0008) * 3640875000 = 37723510.42

我的代码有什么问题,我应该如何继续使用 QuantLib 和 Python 计算摊销浮动利率债券的正确现金流?

另外,请告知如何显示我的 ibor 指数中的利率。

我们非常感谢 LB 或 GB 的任何帮助!!

谢谢。

AA

【问题讨论】:

    标签: python quantlib


    【解决方案1】:

    这是 QuantLib 包装器中的问题和代码中的错误调用的组合。

    在你的代码中,你有

    amortizingfloatbond = ql.AmortizingFloatingRateBond(0, notional, schedule, index, ql.Actual360(), ql.ModifiedFollowing, 2, [spread])
    

    您传递的最后一个参数是传动装置的位置,而不是价差;所以债券支付 0.0008 * Libor + 默认价差。不幸的是,默认价差是 1,而不是 0(可能是来自 gearings 的复制粘贴错误,其中 1 是正确的默认值)。最后,你的债券支付了 0.0008 * Libor + 100%,产生了荒谬的现金流。

    要绕过问题并正确初始化绑定,可以使用调用

    amortizingfloatbond = ql.AmortizingFloatingRateBond(
        0, notional, schedule, index, ql.Actual360(), ql.ModifiedFollowing, 2, spreads=[spread])
    

    正确设置点差。

    此时第一张优惠券的金额为56324336.25,正确;应该修改您的预期值公式。首先,LIBOR 的固定值为 0.0298,您使用

    index.addFixing(ql.Date(30, 1, 2020), 2.98/100)
    

    第二,不是 ((0.0298 * T) + 0.0008);它是 (0.0298 + 0.0008) * T,其中点差也乘以应计时间。最后,时间不是34/360;估值日期和息票支付日期之间有 34 天,但现金流量基于息票的长度,即 6 个月,或更准确地说,在本例中为 182 天。所以:(0.0298 + 0.0008) * (182/360) * 3640875000 = 56324336.25 这是返回的金额。

    最后:要显示费率,请使用

    for i, cf in enumerate(amortizingfloatbond.cashflows()):
        c = ql.as_floating_rate_coupon(cf)
        if c:
           print((i + 1), c.rate(), c.indexFixing(), c.fixingDate())
    

    【讨论】:

    • 非常感谢您的及时回复!这真的很有帮助!
    猜你喜欢
    • 2013-02-22
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多