我正在尝试使用 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)