Posted by
asavoldi on
URL: http://quantlib.414.s1.nabble.com/NPV-calculation-in-Python-from-a-discounting-curve-tp14960.html
Hello everybody,
I'm trying to calculate the NPV of a couple of bonds, zero coupon and fixed income, using QuantLib in Python, via SWIG interface (QuantLib 1.3, SWIG 1.2). In C++, starting from the discounting curve which is embedded within the code snippet posted below, I obtain the correct values:
NPV (ZCB) = 99.2665
NPV (FRB) = 103.733
However, from Python side, I've got different results:
NPV (ZCB) = 96.45
NPV (FRB) = 100.79
Could you help me to understand the reason of this mis-behaviour?
Thanks in advance,
Antonio
#!/usr/bin/env python
# Copyright (C) 2008 Florent Grenier
# Copyright (C) 2010 Lluis Pujol Bajador
#
# This file is part of QuantLib, a free-software/open-source library
# for financial quantitative analysts and developers -
http://quantlib.org/#
# QuantLib is free software: you can redistribute it and/or modify it
# under the terms of the QuantLib license. You should have received a
# copy of the license along with this program; if not, please email
# <quantlib-dev@lists.sf.net>. The license is also available online at
# <
http://quantlib.org/license.shtml>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the license for more details.
# This example shows how to set up a term structure and then price
# some simple bonds. The last part is dedicated to peripherical
# computations such as "Yield to Price" or "Price to Yield"
# this script should be the prototype which demonstrate how to
# use discounting curve for calculating the Net Present Value
# of a Bond (Fixed Rate, Zero Coupon, and Floating Rate)
# Test cases for Bonds pricing module
# Fixed rate bond
# Zero coupon bond
# Floating rate bond
from QuantLib import *
# global data
calendar = TARGET()
settlementDate = Date(01,January,2014)
settlementDate = calendar.adjust(settlementDate)
fixingDays = 0
settlementDays = 0
todaysDate = calendar.adjust(calendar.advance(settlementDate, -fixingDays, Days))
Settings.instance().evaluationDate = todaysDate
termStructureDayCounter = ActualActual(ActualActual.ISDA)
print 'Today: ' + str(todaysDate)
print 'Settlement Date: ' + str(settlementDate)
# dates and rates vectors
dates = [
settlementDate,
settlementDate + 1*QuantLib.Weeks,
settlementDate + 1*QuantLib.Months,
settlementDate + 2*QuantLib.Months,
settlementDate + 3*QuantLib.Months,
settlementDate + 4*QuantLib.Months,
settlementDate + 5*QuantLib.Months,
settlementDate + 6*QuantLib.Months,
settlementDate + 9*QuantLib.Months,
settlementDate + 1*12*QuantLib.Months,
settlementDate + 18*QuantLib.Months,
settlementDate + 2*12*QuantLib.Months,
settlementDate + 3*12*QuantLib.Months,
settlementDate + 4*12*QuantLib.Months,
settlementDate + 5*12*QuantLib.Months,
settlementDate + 6*12*QuantLib.Months,
settlementDate + 7*12*QuantLib.Months,
settlementDate + 8*12*QuantLib.Months,
settlementDate + 9*12*QuantLib.Months,
settlementDate + 10*12*QuantLib.Months,
settlementDate + 11*12*QuantLib.Months,
settlementDate + 12*12*QuantLib.Months,
settlementDate + 15*12*QuantLib.Months,
settlementDate + 20*12*QuantLib.Months,
settlementDate + 25*12*QuantLib.Months,
settlementDate + 30*12*30]
rates = [
0.002762549,
0.002762549,
0.002762549,
0.002762549,
0.002762549,
0.00347872,
0.004126332,
0.004714056,
0.006191223,
0.007362001,
0.009215772,
0.01082479,
0.01404554,
0.01738827,
0.02061265,
0.02351719,
0.02602376,
0.02813818,
0.0299055,
0.03138197,
0.0326213,
0.03366947,
0.03600337,
0.03835103,
0.03976059,
0.04070031
]
#######################################
# BONDS TO BE PRICED #
#######################################
# common data
faceAmount = 100;
# Discounting curve built up on the provided dates/rates
bondDiscountingTermStructure = ZeroCurve(dates, rates, termStructureDayCounter)
discountingTermStructure = RelinkableYieldTermStructureHandle()
bondEngine = DiscountingBondEngine(discountingTermStructure)
# zero coupon bond
zeroCouponBond = ZeroCouponBond(settlementDays,
UnitedStates(UnitedStates.GovernmentBond),
faceAmount,
Date(01,January,2015),
Following,
100,
Date(01,January,2005))
zeroCouponBond.setPricingEngine(bondEngine)
# fixed 4.5% US Treasury note
fixedBondSchedule = Schedule(Date(01, January, 2005),
Date(01, January, 2015),
Period(Annual),
UnitedStates(UnitedStates.GovernmentBond),
Unadjusted,
Unadjusted,
DateGeneration.Backward,
False)
fixedRateBond = FixedRateBond(settlementDays,
faceAmount,
fixedBondSchedule,
[0.045],
ActualActual(ActualActual.Bond),
ModifiedFollowing,
100.0,
Date(01, January, 2005))
fixedRateBond.setPricingEngine(bondEngine);
discountingTermStructure.linkTo(bondDiscountingTermStructure)
#############################
# BOND PRICING #
#############################
# write column headings
def formatPrice(p,digits=2):
format = '%%.%df' % digits
return format % p
def formatRate(r,digits=2):
format = '%%.%df %%%%' % digits
return format % (r*100)
def report(Info, Zc, Fix, Frn, format):
if format== "Price":
Zc = formatPrice(Zc)
Fix = formatPrice(Fix)
Frn = formatPrice(Frn)
else:
if Info.find("coupon")==-1:
Zc = formatRate(Zc)
else:
Zc = "N/A"
Fix = formatRate(Fix)
Frn = formatRate(Frn)
print '%19s' % Info + ' |' + \
' |'.join(['%10s' % y for y in [Zc, Fix, Frn] ])
headers = [ "ZC", "Fixed", "Floating" ]
print ''
print '%19s' % '' + ' |' + \
' |'.join(['%10s' % y for y in headers])
separator = " | "
widths = [ 18, 10, 10, 10 ]
width = widths[0] + widths[1] + widths[2] + widths[3] + widths[3];
rule = "-" * width
dblrule = "=" * width
tab = " " * 8
print rule
report( "Net present value",
zeroCouponBond.NPV(),
fixedRateBond.NPV(),
#floatingRateBond.NPV(),
0,
"Price")
print ''