我正在尝试使用QuantLib环境中的自举曲线对远期掉期定价。对于我2019年4月4日的评估日期,曲线引导程序按预期运行。我还能够轻松地为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 fixing 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)