2015-11-23 2 views
1

Я пытаюсь получить официальный пример C++ cpibond, работающий в Python. Оригинальный пример здесь: https://github.com/lballabio/quantlib/blob/master/QuantLib/test-suite/inflationcpibond.cpp и Скале здесь: https://github.com/lballabio/quantlib/blob/master/QuantLib-SWIG/Scala/examples/CPIBond.scalaПример примера QuantLib cpibond в Python

Когда я бегу, что я попытался я получаю эту ошибку:

RuntimeError: 1st iteration: failed at 1st alive instrument, maturity September 1st, 2010, reference date September 1st, 2009: 2nd leg: Missing UK RPI fixing for September 1st, 2009

Вот моя попытка:

import QuantLib as ql 
calendar = ql.UnitedKingdom() 
dayCounter = ql.ActualActual(); 
convention = ql.ModifiedFollowing 

today = ql.Date(20, 11, 2009) 
evaluationDate = calendar.adjust(today) 
ql.Settings.instance().setEvaluationDate(evaluationDate)   
yTS = ql.YieldTermStructureHandle(ql.FlatForward(evaluationDate, 0.05, dayCounter)) 

from_date = ql.Date(20, ql.July, 2007); 
to_date = ql.Date(20, ql.November, 2009); 
tenor = ql.Period(1, ql.Months) 
rpiSchedule = ql.Schedule(from_date, to_date, tenor, calendar, 
           convention, convention, 
           ql.DateGeneration.Backward, False) 
cpiTS = ql.RelinkableZeroInflationTermStructureHandle() 
inflationIndex = ql.UKRPI(False, cpiTS) 
fixData = [206.1, 207.3, 208.0, 208.9, 209.7, 210.9, 
        209.8, 211.4, 212.1, 214.0, 215.1, 216.8, 
        216.5, 217.2, 218.4, 217.7, 216, 
        212.9, 210.1, 211.4, 211.3, 211.5, 
        212.8, 213.4, 213.4, 213.4, 214.4,213.4, 214.4] 
dte_fixings=[dtes for dtes in rpiSchedule] 
print len(dte_fixings) 
print len(fixData) 
#must be the same length 
inflationIndex.addFixings(dte_fixings, fixData) 
observationLag = ql.Period(2, ql.Months) 
zciisData =[(ql.Date(25, ql.November, 2010), 3.0495), 
       (ql.Date(25, ql.November, 2011), 2.93), 
       (ql.Date(26, ql.November, 2012), 2.9795), 
       (ql.Date(25, ql.November, 2013), 3.029), 
       (ql.Date(25, ql.November, 2014), 3.1425), 
       (ql.Date(25, ql.November, 2015), 3.211), 
       (ql.Date(25, ql.November, 2016), 3.2675), 
       (ql.Date(25, ql.November, 2017), 3.3625), 
       (ql.Date(25, ql.November, 2018), 3.405), 
       (ql.Date(25, ql.November, 2019), 3.48), 
       (ql.Date(25, ql.November, 2021), 3.576), 
       (ql.Date(25, ql.November, 2024), 3.649), 
       (ql.Date(26, ql.November, 2029), 3.751), 
       (ql.Date(27, ql.November, 2034), 3.77225), 
       (ql.Date(25, ql.November, 2039), 3.77), 
       (ql.Date(25, ql.November, 2049), 3.734), 
       (ql.Date(25, ql.November, 2059), 3.714)] 

lRates=[rtes/100.0 for rtes in zip(*zciisData)[1]] 
baseZeroRate = lRates[0] 

zeroSwapHelpers = [ql.ZeroCouponInflationSwapHelper(a[1]/100,observationLag, 
    a[0], calendar, convention, dayCounter, inflationIndex) for a in zciisData] 


cpiTS.linkTo(ql.PiecewiseZeroInflation(   
    evaluationDate, calendar, dayCounter, observationLag, 
    inflationIndex.frequency(), inflationIndex.interpolated(), 
    baseZeroRate, 
    yTS, zeroSwapHelpers, 1.0e-12, ql.Linear())) 


notional = 1000000 


fixedRates = [0.1]  

fixedDayCounter = ql.Actual365Fixed() 
fixedPaymentConvention = ql.ModifiedFollowing 
fixedPaymentCalendar = ql.UnitedKingdom() 
contractObservationLag = ql.Period(3, ql.Months) 
observationInterpolation = ql.CPI.Flat 
settlementDays = 3 
growthOnly = True 

baseCPI = 206.1 
startDate = ql.Date(2, 10, 2007) 
endDate = ql.Date(2, 10, 2052) 

fixedSchedule = ql.Schedule(startDate, endDate, 
        ql.Period(6, ql.Months), fixedPaymentCalendar, 
        ql.Unadjusted, 
        ql.Unadjusted, 
        ql.DateGeneration.Backward, False) 

bond = ql.CPIBond(settlementDays, notional, growthOnly, 
         baseCPI, contractObservationLag, 
         inflationIndex, observationInterpolation, 
         fixedSchedule, fixedRates, fixedDayCounter, 
         fixedPaymentConvention) 

bondEngine=ql.DiscountingBondEngine(yTS) 
bond.setPricingEngine(bondEngine) 
print bond.NPV() 
print bond.cleanPrice() 

Большинство моя проблема в том, что мне трудно понять, как объекты подходят друг другу.

ответ

1

получил вышеупомянутый пример работы:

import QuantLib as ql 
import datetime as dt 
calendar = ql.UnitedKingdom() 
dayCounter = ql.ActualActual(); 
convention = ql.ModifiedFollowing 
lag = 3 

today = ql.Date(5,3,2008) 
evaluationDate = calendar.adjust(today) 
issue_date = calendar.advance(evaluationDate,-1, ql.Years) 
maturity_date = ql.Date(2,9,2052) 
fixing_date = calendar.advance(evaluationDate,-lag, ql.Months) 

ql.Settings.instance().setEvaluationDate(evaluationDate)   
yTS = ql.YieldTermStructureHandle(ql.FlatForward(evaluationDate, 0.05, dayCounter)) 

tenor = ql.Period(1, ql.Months) 

from_date = ql.Date(20, ql.July, 2007); 
to_date = ql.Date(20, ql.November, 2009); 
rpiSchedule = ql.Schedule(from_date, to_date, tenor, calendar, 
           convention, convention, 
           ql.DateGeneration.Backward, False) 

# this is the going to be holder the inflation curve. 
cpiTS = ql.RelinkableZeroInflationTermStructureHandle() 
inflationIndex = ql.UKRPI(False, cpiTS) 
fixData = [206.1, 207.3, 208.0, 208.9, 209.7, 210.9, 
      209.8, 211.4, 212.1, 214.0, 215.1, 216.8, 
      216.5, 217.2, 218.4, 217.7, 216, 
      212.9, 210.1, 211.4, 211.3, 211.5, 
      212.8, 213.4, 213.4, 213.4, 214.4] 
dte_fixings=[dtes for dtes in rpiSchedule] 
print len(fixData) 
print len(dte_fixings[:len(fixData)]) 
#must be the same length 
#inflationIndex.addFixings(dte_fixings[:len(fixData)], fixData) 
#Current CPI level 
#last observed rate 
fixing_rate = 214.4 


inflationIndex.addFixing(fixing_date, fixing_rate) 

observationLag = ql.Period(lag, ql.Months) 
zciisData =[(ql.Date(25, ql.November, 2010), 3.0495), 
       (ql.Date(25, ql.November, 2011), 2.93), 
       (ql.Date(26, ql.November, 2012), 2.9795), 
       (ql.Date(25, ql.November, 2013), 3.029), 
       (ql.Date(25, ql.November, 2014), 3.1425), 
       (ql.Date(25, ql.November, 2015), 3.211), 
       (ql.Date(25, ql.November, 2016), 3.2675), 
       (ql.Date(25, ql.November, 2017), 3.3625), 
       (ql.Date(25, ql.November, 2018), 3.405), 
       (ql.Date(25, ql.November, 2019), 3.48), 
       (ql.Date(25, ql.November, 2021), 3.576), 
       (ql.Date(25, ql.November, 2024), 3.649), 
       (ql.Date(26, ql.November, 2029), 3.751), 
       (ql.Date(27, ql.November, 2034), 3.77225), 
       (ql.Date(25, ql.November, 2039), 3.77), 
       (ql.Date(25, ql.November, 2049), 3.734), 
       (ql.Date(25, ql.November, 2059), 3.714)] 

#lRates=[rtes/100.0 for rtes in zip(*zciisData)[1]] 
#baseZeroRate = lRates[0] 

zeroSwapHelpers = [ql.ZeroCouponInflationSwapHelper(rate/100,observationLag, 
    date, calendar, convention, dayCounter, inflationIndex) for date,rate in zciisData] 


# the derived inflation curve 
jj=ql.PiecewiseZeroInflation(   
           evaluationDate, calendar, dayCounter, observationLag, 
           inflationIndex.frequency(), inflationIndex.interpolated(), 
           zciisData[0][1],#baseZeroRate, 
           yTS, zeroSwapHelpers, 1.0e-12, ql.Linear()) 

cpiTS.linkTo(jj) 

notional = 1000000 

fixedRates = [0.1]  

fixedDayCounter = ql.Actual365Fixed() 
fixedPaymentConvention = ql.ModifiedFollowing 
fixedPaymentCalendar = ql.UnitedKingdom() 
contractObservationLag = ql.Period(3, ql.Months) 
observationInterpolation = ql.CPI.Flat 
settlementDays = 3 
growthOnly = False 

baseCPI = 206.1 


fixedSchedule = ql.Schedule(issue_date, 
        maturity_date, 
        ql.Period(ql.Semiannual), 
        fixedPaymentCalendar, 
        ql.Unadjusted, 
        ql.Unadjusted, 
        ql.DateGeneration.Backward, 
        False) 

bond = ql.CPIBond(settlementDays, 
        notional, 
        growthOnly, 
        baseCPI, 
        contractObservationLag, 
        inflationIndex, 
        observationInterpolation, 
        fixedSchedule, 
        fixedRates, 
        fixedDayCounter, 
        fixedPaymentConvention) 

#bond2= ql.QuantLib.C 

bondEngine=ql.DiscountingBondEngine(yTS) 
bond.setPricingEngine(bondEngine) 
print bond.NPV() 
print bond.cleanPrice() 
compounding = ql.Compounded 
yield_rate = bond.bondYield(fixedDayCounter,compounding,ql.Semiannual) 
y_curve = ql.InterestRate(yield_rate,fixedDayCounter,compounding,ql.Semiannual) 
##Collate results 
print "Clean Price:", bond.cleanPrice() 
print "Dirty Price:", bond.dirtyPrice() 
print "Notional:", bond.notional() 
print "Yield:", yield_rate 
print "Accrued Amount:", bond.accruedAmount() 
print "Settlement Value:", bond.settlementValue() 

#suspect there's more to this for TIPS 
print "Duration:", ql.BondFunctions.duration(bond,y_curve) 
print "Convexity:", ql.BondFunctions.convexity(bond,y_curve) 
print "Bps:", ql.BondFunctions.bps(bond,y_curve) 
print "Basis Point Value:", ql.BondFunctions.basisPointValue(bond,y_curve) 
print "Yield Value Basis Point:", ql.BondFunctions.yieldValueBasisPoint(bond,y_curve) 

print "NPV:", bond.NPV() 

# get the cash flows: 
#cf_list=[(cf.amount(),cf.date()) for cf in bond.cashflows()] 

def to_datetime(d): 
    return dt.datetime(d.year(),d.month(), d.dayOfMonth()) 

for cf in bond.cashflows(): 
    try: 
     amt=cf.amount() 
     rte=jj.zeroRate(cf.date()) 
     zc=yTS.zeroRate(cf.date(),fixedDayCounter,compounding,ql.Semiannual).rate() 
    except: 
     amt=0 
     rte=0 
     zc=0 
    print to_datetime(cf.date()),amt,rte,zc 

Проблема, кажется, что объект inflationIndex необходимо одну дату вместо нескольких точек индекса. Мое предположение заключалось в том, что он вытащил последнюю действительную точку.

Принцип работы прайсера заключается в том, что реальные купоны увеличиваются по структуре сроков кривой инфляции, zciisData. Следовательно, результат становится номинальным будущим денежным потоком. Чтобы заплатить тогда, бенефициарий просто скидывает их номинальной структурой. Я добавил дополнительный код для печати определенных денежных потоков и «фактора роста», а затем ставки дисконтирования.

Смежные вопросы