首页 > 解决方案 > QuantLib-Python:使用 VanillaSwap 仪器的 quantlib Schedule 解决非正时间前向误差

问题描述

我正在尝试使用 QuantLib 环境中的自举曲线对远期掉期进行定价。对于我的 2019-04-04 估值日期,曲线引导程序按预期运行。我还可以轻松地为 10Y10Y 前向启动掉期定价。当我尝试为 15Y5Y 远期掉期定价时,问题就出现了。假设我的结算是 t+2 (2019-04-08),我使用结算日期和日历对象找到掉期的远期开始日期,该错误似乎主要出现在我的远期开始日期在周末时,因此使用下一个工作日作为开始日期。在我们的例子中,2034-04-08 是星期六,所以我们最终将交换的开始日期定为 2034-04-10。然后引发此错误:

无法计算 2034 年 4 月 11 日和 2034 年 4 月 11 日之间的远期汇率:使用 Actual/360 daycounter 的非正时间 (0)

C++ Quantlib Vanilla Swap: setting future fix dates and gearing for floating leg但我没有找到解决这个“问题”的正式问题。

试图理解这个问题,我相信向后的日期生成可能是问题的一部分,因为它似乎创建了一个存根。使用反向生成的交换开始日期是 2034 年 4 月 11 日,而我提供的交换开始日期是 2034 年 4 月 10 日。这显示在我的时间表(固定和浮动)中。

进一步研究我的研究,我在这里寻找“存根”:https ://leanpub.com/quantlibpythoncookbook/read并找到了我认为是答案的一部分。Schedule 构造函数允许指定短/长前/后存根,但即使我将 firstDate 指定为 2034 年 4 月 11 日,也会引发相同的错误。这是重现错误的完整代码。如您所见,我的日程安排包括 2034 年 4 月 10 日2034 年4 月 11 日,我认为这是导致我的问题的原因。我仍然对为什么以及如何解决这个问题感到困惑。


import QuantLib as ql

# my quotes
nodes=(
 (ql.Date( 4, 4, 2019 ), 1.0),
 (ql.Date( 8, 4, 2020 ), 0.9744804179560926),
 (ql.Date( 8, 4, 2021 ), 0.9523386108738999),
 (ql.Date( 8, 4, 2022 ), 0.9315169815568433),
 (ql.Date( 11, 4, 2023 ), 0.910405285996171),
 (ql.Date( 8, 4, 2024 ), 0.8892891964251837),
 (ql.Date( 8, 4, 2025 ), 0.8676501405451038),
 (ql.Date( 8, 4, 2026 ), 0.8457795884699698),
 (ql.Date( 8, 4, 2027 ), 0.8237398951999767),
 (ql.Date( 10, 4, 2028 ), 0.801457566049863),
 (ql.Date( 9, 4, 2029 ), 0.7795144954869505),
 (ql.Date( 8, 4, 2031 ), 0.7362944371445531),
 (ql.Date( 11, 4, 2034 ), 0.6755019523836218),
 (ql.Date( 12, 4, 2039 ), 0.5864073271433347),
 (ql.Date( 8, 4, 2044 ), 0.5120023623536163),
 (ql.Date( 8, 4, 2049 ), 0.4479312303231183),
 (ql.Date( 8, 4, 2059 ), 0.34859916237300465),
 (ql.Date( 8, 4, 2069 ), 0.2788046487083811))

node_dates, node_rates = zip(*nodes)

# Construct the discount curve
curve = ql.DiscountCurve(node_dates, node_rates, ql.Actual360(), ql.UnitedStates())
termStruct = ql.RelinkableYieldTermStructureHandle()
termStruct.linkTo(curve)


curve_date = ql.Date(4,4,2019) # the curve date
settlement = ql.Period(2,
                       ql.Days)

settle_date = ql.UnitedStates().advance(curve_date,
                                        settlement) # the settlement date, assume t+2 settlement

fwdstart = ql.UnitedStates().advance(settle_date,
                                     ql.Period(15,ql.Years)) # forward start date of swap

fwdend = ql.UnitedStates().advance(fwdstart,
                                    ql.Period(5,ql.Years)) # forwrad end date of swap

fixedSchedule = ql.Schedule( fwdstart,  # forward start
                             fwdend,  # forward end
                             ql.Period('6M'),  # period tenor
                             ql.UnitedStates(),  # calendar
                             ql.ModifiedFollowing,  # convention
                             ql.ModifiedFollowing,  # termination date convention
                             ql.DateGeneration.Backward,  # date generation
                             True  # EoM
                             )
print('\n' + 10*'*' + ' Fixed Schedule ' + 10*'*')
for d in fixedSchedule:
    print(d)
print(40*'*')

floatingSchedule = ql.Schedule( fwdstart,  # forward start
                                fwdend,  # forward end
                                ql.Period('3M'),  # period tenor
                                ql.UnitedStates(),  # calendar
                                ql.ModifiedFollowing,  # convention
                                ql.ModifiedFollowing,  # termination date convention
                                ql.DateGeneration.Backward,  # date generation
                                True  # EoM
                                )

print('\n' + 10*'*' + ' Floating Schedule ' + 10*'*')
for d in floatingSchedule:
    print(d)
print(40*'*')

forwardswap = ql.VanillaSwap( type=ql.VanillaSwap.Receiver,  # direction
                              nominal=1E8,  # notional
                              fixedSchedule=fixedSchedule,  # fixed schedule
                              fixedRate=0.023,  # fixed rate
                              fixedDayCount=ql.Actual360(),  # fixed leg basis
                              floatSchedule=floatingSchedule,  # floating schedule
                              index=ql.USDLibor(ql.Period('3M')),
                              spread=0.0,  # spread
                              floatingDayCount=ql.Thirty360() # float leg basis
                              )

swap_engine = ql.DiscountingSwapEngine(termStruct)
forwardswap.setPricingEngine(swap_engine)



标签: pythonquantitative-financequantlibquantlib-swig

解决方案


推荐阅读