Estoy usando QuantLib para calcular los precios de los bonos de tasa fija en diferentes escenarios. En el primer paso me gustaría replicar el precio actual de mercado mediante el ajuste de la curva de rendimiento de la zspread. Utilizando la función de BondFunctions.zSpread puedo acercarme (en el ejemplo de abajo (97.85 frente a un precio de mercado de 98), pero me pregunto por qué nosotros no convergen al mismo precio cuando la alteración de la propagación de forma continua. Me estoy perdiendo algo?
El código siguiente se adapta Simple QuantLib de Bonos de Matemáticas
import pytest
import QuantLib as ql
from QuantLib import *
# Construct yield curve
calc_date = Date(1, 1, 2017)
Settings.instance().evaluationDate = calc_date
spot_dates = [Date(1,1,2017), Date(1,1,2018), Date(1,1,2027)]
# corrected!
# spot_rates = [0.0, 0.04, 0.04]
spot_rates = [0.04, 0.04, 0.04]
day_count = SimpleDayCounter()
calendar = NullCalendar()
interpolation = Linear()
compounding = Compounded
# corrected!
compounding_frequency = Annual
compounding_frequency = Semiannual
spot_curve = ZeroCurve(spot_dates, spot_rates, day_count, calendar,
interpolation, compounding,
compounding_frequency)
spot_curve_handle = YieldTermStructureHandle(spot_curve)
# Construct bond schedule
issue_date = Date(1, 1, 2017)
maturity_date = Date(1, 1, 2022)
tenor = Period(Semiannual)
calendar = NullCalendar()
business_convention = Unadjusted
date_generation = DateGeneration.Backward
month_end = False
schedule = Schedule(issue_date, maturity_date, tenor, calendar,
business_convention, business_convention,
date_generation, month_end)
# Create FixedRateBond Object
coupon_rate = 0.05
coupons = [coupon_rate]
settlement_days = 0
face_value = 100
fixed_rate_bond = FixedRateBond(settlement_days,
face_value,
schedule,
coupons,
day_count)
# Set Valuation engine
bond_engine = DiscountingBondEngine(spot_curve_handle)
fixed_rate_bond.setPricingEngine(bond_engine)
# Calculate present value
value = fixed_rate_bond.NPV()
assert value == pytest.approx(104.49, abs=1.e-2)
# fix a hypothetical market price
px = 98.
# compute the implied z spread
zspread = ql.BondFunctions.zSpread(fixed_rate_bond,
px,
spot_curve, day_count, compounding,
compounding_frequency, calc_date, 1.e-16, 1000000, 0.)
def impl_clean_price(spread):
spread1 = ql.SimpleQuote(spread)
spread_handle1 = ql.QuoteHandle(spread1)
ts_spreaded1 = ql.ZeroSpreadedTermStructure(spot_curve_handle,
spread_handle1)
ts_spreaded_handle1 = ql.YieldTermStructureHandle(ts_spreaded1)
ycsin = ts_spreaded_handle1
fixed_rate_bond = FixedRateBond(settlement_days,
face_value,
schedule,
coupons,
day_count)
# Set Valuation engine
bond_engine = DiscountingBondEngine(ycsin)
fixed_rate_bond.setPricingEngine(bond_engine)
value = fixed_rate_bond.cleanPrice()
return value
# the two clean prices are 98 and 97.8517891975
print px
print impl_clean_price(zspread)
print abs(px-impl_clean_price(zspread))