estoy intrigado por la manera Quantlib se encarga de la evaluación de la fecha en el rendimiento de la estructura a plazo de las clases. Tengo el siguiente código de ejemplo:
import QuantLib as ql
import pandas as pd
#Curve
def build_termstruc(curve_date):
helpers = []
handle = ql.YieldTermStructureHandle()
tenors = [1,3,6,9,12,18,2,3,4,5,6,7,8,9,10,15,20]
swap_rates = [2.75,2.875,2.99,3.12,3.25,3.5,3.61,3.795,3.925,4.025,4.115,4.195,4.265,4.335,4.4,4.555,4.68]
fixing_days = 0
calendar = ql.NullCalendar()
settlement_days = 0
day_counter = ql.Actual360()
index = ql.OvernightIndex("index", settlement_days,ql.CLPCurrency(),calendar,day_counter)
for i in range(len(tenors)):
if i == 0:
helpers += [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(swap_rates[i]/100)),
ql.Period(1,ql.Days),
fixing_days,
calendar,
ql.Unadjusted,
False,
ql.Actual360())]
continue
elif i < 6 and i > 0:
period = ql.Period(tenors[i], ql.Months)
frequency = ql.Months
elif i >=6:
period = ql.Period(tenors[i], ql.Years)
frequency = ql.Years
helpers += [ql.OISRateHelper(settlement_days,
period,
ql.QuoteHandle(ql.SimpleQuote(swap_rates[i]/100)),
index,
handle,
False,
0,
ql.Following,
frequency)]
return ql.PiecewiseFlatForward(curve_date, helpers, ql.Actual360())
def build_bond():
#Bond
issue_date = ql.Date(1,6,2015)
maturity_date = ql.Date(1,6,2020)
calendar = ql.NullCalendar()
coupon_day_count = ql.Unadjusted
payment_convention = ql.Following
date_generation = ql.DateGeneration.Forward
month_end = False
settlement_days = 0
int_day_count = ql.Thirty360()
notional = 100
coupons = [4.5/100]
#non static variables
schedule = ql.Schedule (issue_date,
maturity_date,
ql.Period(ql.Semiannual),
calendar,
coupon_day_count,
payment_convention,
date_generation,
month_end)
return ql.FixedRateBond(settlement_days, notional, schedule, coupons, int_day_count)
def test1():
curve_date = ql.Date(14,11,2018)
ql.Settings.instance().evaluationDate = curve_date
ts = build_termstruc(curve_date)
bond = build_bond()
bond_IIR = ql.InterestRate(3.78/100, ql.Actual365Fixed(), ql.Compounded, ql.Annual)
npv = ql.CashFlows.npv(bond.cashflows(), bond_IIR, False)
spread = ql.CashFlows.zSpread(bond.cashflows(), npv, ts, ql.Actual360(), ql.Compounded, ql.Annual, True)*100
print('NPV: ', npv,'Spread: ', spread)
def test2():
curve_date = ql.Date(14,11,2018)
ts = build_termstruc(curve_date)
ql.Settings.instance().evaluationDate = curve_date
bond = build_bond()
bond_IIR = ql.InterestRate(3.78/100, ql.Actual365Fixed(), ql.Compounded, ql.Annual)
npv = ql.CashFlows.npv(bond.cashflows(), bond_IIR, False)
spread = ql.CashFlows.zSpread(bond.cashflows(), npv, ts, ql.Actual360(), ql.Compounded, ql.Annual, True)*100
print('NPV: ', npv,'Spread: ', spread)
if __name__ == '__main__':
test1()
test2()
La idea de que el código es que los dos primeros métodos de construir una estructura a plazo y de bonos y los otros dos (test1 y test2) sólo cambiar la posición en la evaluationDate se establece. El resultado es el siguiente:
NPV: 103.15824069057247 Spread: 0.18307250901326033
NPV: 103.15824069057247 Spread: 0.18307250901326033
No entiendo por qué estoy recibiendo diferentes z-spreads si im ajuste de la curva de la fecha de referencia.