Оценка плавающей облигации в quantlib с использованием Python

Я пытаюсь оценить очень простую облигацию с плавающей ставкой в ​​​​python, используя оболочку Quantlib (v1.2) SWIG. Я изменил пример, включенный в документацию.

Моя облигация имеет срок погашения 4 года. Ставка libor установлена ​​на уровне 10%, а спред облигации равен 0. Мой вопрос: если я дисконтирую по ставке 10%, почему PV облигации не равна 100? Я получаю значение 99,54.

Спасибо!

from QuantLib import *

frequency_enum, settle_date = 4, Date(5, 1, 2010)
maturity_date = Date(5, 1, 2014)
face_amount = 100.0
settlement_days = 0
fixing_days = 0

calendar = NullCalendar()
settle_date = calendar.adjust(settle_date)
todays_date = calendar.advance(settle_date, -fixing_days, Days)
Settings.instance().evaluationDate = todays_date

rate = 10.0 / 100.0

flat_forward = FlatForward(settle_date,
                           rate,
                           Thirty360(),
                           Compounded,
                           frequency_enum)

discounting_term_structure = RelinkableYieldTermStructureHandle(flat_forward)
index_term_structure = RelinkableYieldTermStructureHandle(flat_forward)

index = USDLibor(Period(3, Months), index_term_structure)

schedule = Schedule(settle_date,
                    maturity_date, Period(frequency_enum),
                    NullCalendar(),
                    Unadjusted, Unadjusted,
                    DateGeneration.Forward, False)

floating_bond = FloatingRateBond(settlement_days,
                                 face_amount,
                                 schedule,
                                 index,
                                 Thirty360(),
                                 Unadjusted,
                                 fixing_days,
                                 [],   # Gearings
                                 [0],  # Spreads
                                 [],      # Caps
                                 [],      # Floors
                                 False,    # Fixing in arrears
                                 face_amount,
                                 settle_date)

bond_engine = DiscountingBondEngine(discounting_term_structure)
floating_bond.setPricingEngine(bond_engine)

# coupon pricers
pricer = BlackIborCouponPricer()

volatility = 0.0
vol = ConstantOptionletVolatility(settlement_days,
                                  calendar,
                                  Unadjusted,
                                  volatility,
                                  Thirty360())

pricer.setCapletVolatility(OptionletVolatilityStructureHandle(vol))
setCouponPricer(floating_bond.cashflows(), pricer)

print floating_bond.NPV(), floating_bond.cleanPrice(), floating_bond.dirtyPrice()

person ducky    schedule 07.03.2013    source источник


Ответы (1)


Ставки купонов фиксируются с помощью счетчика дней USDLibor (т. е. Actual/360), который не соответствует указанному вами счетчику дней платежей (30/360). Вы можете увидеть это, просмотрев купоны:

cfs = floating_bond.cashflows()
coupons = [ as_coupon(c) for c in cfs[:-1] ] # the last one is the redemption
print [ (c.rate(), c.accrualPeriod()) for c in coupons ]

что дает вам T = 0,25 для всех купонов, но ставки ниже 10%.

Чтобы получить желаемую цену, вы должны сопоставить курс и период начисления. Один из способов — передать Actual360() в качестве счетчика дней облигаций, который дает цену 100,002 на моем компьютере (дальше я не исследовал, но несоответствие может быть связано с датой окончания фиксинга LIBOR, которая определяется с помощью календарь в долларах США и может не совпадать с окончанием купона). Другой способ — создать собственный индекс LIBOR с внутренним счетчиком на 30/360 дней; Я не пробовал это сам, но вы можете сделать это, создав соответствующий экземпляр класса IborIndex.

person Luigi Ballabio    schedule 08.03.2013
comment
Большое спасибо. Я создал собственный индекс и получил точный результат 100,0! Пользовательский индекс: index = IborIndex('USD Libor', Period(3, Months), settlement_days, USDCurrency(), NullCalendar(), Unadjusted, False, Thirty360(), index_term_structure) - person ducky; 09.03.2013