QuantLib-Python: Устранение неположительной ошибки пересылки по времени с помощью QuantLib Schedule для инструмента VanillaSwap - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь оценить форвардный своп, используя кривую начальной загрузки в среде QuantLib.Для моей оценочной даты 2019-04-04, кривая начальной загрузки работает как ожидалось.Я также могу легко оценить стартовый своп на 10Y10Y.Проблема возникает, когда я пытаюсь оценить форвардный своп на 15Y5Y.Предположим, мой расчет t + 2 (2019-04-08), и я нахожу дату начала форвардного свопа, используя дату расчета и объект календаря, Кажется, что ошибка возникает в основном, когда моя форвардная дата начала падаетвыходные , поэтому в качестве даты начала используйте следующий рабочий день.В нашем случае 2034-04-08 - суббота, поэтому у нас будет своп с начальной датой 2034-04-10.Затем возникает ошибка:

не может рассчитать форвардный курс в период с 11 апреля 2034 года по 11 апреля 2034 года: неположительное время (0) с использованием фактического / 360 дневного счетчика

Это было описано в комментариях здесь C ++ Quantlib Vanilla Swap: установка будущих сроков фиксации и переключения передач для плавающей ноги , но я не нашел формального вопроса, касающегося этой «проблемы».

Пытаясь понять проблему, я полагаю, что обратная генерация даты может быть частью проблемы, поскольку кажется, что она создает заглушку.Дата начала свопа с использованием обратной генерации - 11 апреля 2034 года, а дата начала свопа, которую я предоставляю, - 10 апреля 2034 года. Это отражено в моем расписании (фиксированном и плавающем).

Идя дальше в своем исследовании, я искал "заглушку" здесь: https://leanpub.com/quantlibpythoncookbook/read и нашел то, что, по моему мнению, является частью ответа.Конструктор Schedule позволяет указывать короткие / длинные передние / задние заглушки, но даже если я укажу firstDate как 11 апреля 2034 года, выдается такая же ошибка.Вот полный код, воспроизводящий ошибку.Как вы можете видеть, мое расписание включает 10 апреля 2034 года И 11 апреля 2034 года, которое, как я считаю, является причиной моей проблемы.Я все еще не понимаю, почему и как это решить.


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)



...