Hi,
I am new user of Quantlib and now trying to price US Treasury TIPS with the CPIBond class, so I basically try to follow the inflationcpibond sampole C++ code with some modification of dates of settlement and bond start/end dates, also the zcii data. But after such changes, the clean price is only $8.9 when notional is $100. What am I doing wrong? #include "stdafx.h" #include <ql/indexes/inflation/ukrpi.hpp> #include <ql/indexes/inflation/uscpi.hpp> #include <ql/time/calendars/unitedkingdom.hpp> #include <ql/time/calendars/unitedstates.hpp> #include <ql/time/daycounters/actualactual.hpp> #include <ql/time/daycounters/actual365fixed.hpp> #include <ql/termstructures/yield/flatforward.hpp> #include <ql/indexes/ibor/gbplibor.hpp> #include <ql/termstructures/inflation/inflationhelpers.hpp> #include <ql/termstructures/inflation/piecewisezeroinflationcurve.hpp> #include <ql/cashflows/indexedcashflow.hpp> #include <ql/pricingengines/swap/discountingswapengine.hpp> #include <ql/instruments/zerocouponinflationswap.hpp> #include <ql/pricingengines/bond/discountingbondengine.hpp> #include <ql/cashflows/cpicoupon.hpp> #include <ql/cashflows/cpicouponpricer.hpp> #include <ql/instruments/cpiswap.hpp> #include <ql/instruments/bonds/cpibond.hpp> using namespace QuantLib; using namespace std; #include <iostream> namespace { struct Datum { Date date; Rate rate; }; typedef BootstrapHelper<ZeroInflationTermStructure> Helper; std::vector<boost::shared_ptr<Helper> > makeHelpers(Datum iiData[], Size N, const boost::shared_ptr<ZeroInflationIndex>& ii, const Period& observationLag, const Calendar& calendar, const BusinessDayConvention& bdc, const DayCounter& dc) { std::vector<boost::shared_ptr<Helper>> instruments; for (Size i = 0; i < N; i++) { Date maturity = iiData[i].date; Handle<Quote> quote(boost::shared_ptr<Quote>(new SimpleQuote(iiData[i].rate / 100.0))); boost::shared_ptr<Helper> h( new ZeroCouponInflationSwapHelper(quote, observationLag, maturity, calendar, bdc, dc, ii) ); instruments.push_back(h); } return instruments; } struct CommonVars { Calendar calendar; BusinessDayConvention convention; Date evaluationDate; Period observationLag; DayCounter dayCounter; boost::shared_ptr<USCPI> ii; RelinkableHandle<YieldTermStructure> yTS; RelinkableHandle<ZeroInflationTermStructure> cpiTS; // setup CommonVars() { // usual setup calendar = UnitedStates(); convention = ModifiedFollowing; Date today(25, Oct, 2015); evaluationDate = calendar.adjust(today); Settings::instance().evaluationDate() = evaluationDate; dayCounter = ActualActual(); Date from(20, Jun, 2013); Date to(20, Oct, 2015); Schedule rpiSchedule = MakeSchedule().from(from).to(to) .withTenor(1 * Months) .withCalendar(UnitedStates()) .withConvention(ModifiedFollowing); bool interp = false; ii = boost::shared_ptr<USCPI>(new USCPI(interp, cpiTS)); Real 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 /* 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945, 237.945 */ }; for (Size i = 0; i < sizeof(fixData) / sizeof(Real); ++i) { ii->addFixing(rpiSchedule[i], fixData[i]); } yTS.linkTo(boost::shared_ptr<YieldTermStructure>(new FlatForward(evaluationDate, 0.0075, dayCounter))); // now build the zero inflation curve observationLag = Period(2, Months); Datum zciisData[] = { { Date(25, November, 2010), 0.010 }, { Date(25, November, 2011), 0.020 }, { Date(26, November, 2012), 0.030 }, { Date(25, November, 2013), 0.040 }, { Date(25, November, 2014), 0.050 }, { Date(25, November, 2015), 0.500 }, { Date(25, November, 2016), 0.800 }, { Date(25, November, 2017), 1.100 }, { Date(25, November, 2018), 1.500 }, { Date(25, November, 2019), 1.800 }, { Date(25, November, 2021), 2.033 }, { Date(25, November, 2024), 2.133 }, { Date(26, November, 2029), 2.300 }, { Date(27, November, 2034), 2.467 }, { Date(25, November, 2039), 2.633 }, { Date(25, November, 2049), 2.967 }, { Date(25, November, 2059), 3.000 }, }; std::vector<boost::shared_ptr<Helper> > helpers = makeHelpers(zciisData, sizeof(zciisData) / sizeof(Datum), ii, observationLag, calendar, convention, dayCounter); Rate baseZeroRate = zciisData[0].rate / 100.0; cpiTS.linkTo( boost::shared_ptr<ZeroInflationTermStructure>( new PiecewiseZeroInflationCurve<Linear>(evaluationDate, calendar, dayCounter, observationLag, ii->frequency(), ii->interpolated(), baseZeroRate, Handle<YieldTermStructure>(yTS), helpers) ) ); } // teardown ~CommonVars() { // break circular references and allow curves to be destroyed cpiTS.linkTo(boost::shared_ptr<ZeroInflationTermStructure>()); } }; } void testInflationCleanPrice() { CommonVars common; Real notional = 100.0; std::vector<Rate> fixedRates(1, 0.02375); DayCounter fixedDayCount = Actual365Fixed(); BusinessDayConvention fixedPaymentConvention = ModifiedFollowing; Calendar fixedPaymentCalendar = UnitedStates(); boost::shared_ptr<ZeroInflationIndex> fixedIndex = common.ii; Period contractObservationLag = Period(1, Months); CPI::InterpolationType observationInterpolation = CPI::Flat; Natural settlementDays = 1; bool growthOnly = true; Real baseCPI = 206.1; // set the schedules Date startDate(15, Jan, 2007); Date endDate(15, Jan, 2017); Schedule fixedSchedule = MakeSchedule().from(startDate).to(endDate) .withTenor(Period(6, Months)) .withCalendar(UnitedStates()) .withConvention(ModifiedFollowing) .backwards(); CPIBond bond(settlementDays, notional, growthOnly, baseCPI, contractObservationLag, fixedIndex, observationInterpolation, fixedSchedule, fixedRates, fixedDayCount, fixedPaymentConvention); boost::shared_ptr<DiscountingBondEngine> engine(new DiscountingBondEngine(common.yTS)); bond.setPricingEngine(engine); Real calculated = bond.cleanPrice(); Real tolerance = 1.0e-8; cout << "NPV: " << bond.NPV() << endl; cout << "Clean price: " << calculated << endl; cout << "Dirty price: " << bond.dirtyPrice() << endl; } |
Apologies for the late reply. It's not exactly my turf, but I'm guessing that the "growthOnly" parameter is causing the bond to pay the appreciation only and discard the notional. When it's set to false, the price is around 107. Luigi On Fri, Oct 30, 2015 at 9:47 PM ian_dfw <[hidden email]> wrote: Hi, -- <http://leanpub.com/implementingquantlib> ------------------------------------------------------------------------------ _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Free forum by Nabble | Edit this page |