CPIBond to price US Treasury TIPS

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

CPIBond to price US Treasury TIPS

ian_dfw
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;


}
Reply | Threaded
Open this post in threaded view
|

Re: CPIBond to price US Treasury TIPS

Luigi Ballabio
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,
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&lt;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&lt;Helper>> instruments;

            for (Size i = 0; i < N; i++)
            {
                Date maturity = iiData[i].date;

                Handle quote(boost::shared_ptr(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&lt;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;


}




--
View this message in context: http://quantlib.10058.n7.nabble.com/CPIBond-to-price-US-Treasury-TIPS-tp17011.html
Sent from the quantlib-users mailing list archive at Nabble.com.

------------------------------------------------------------------------------
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
--

------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: CPIBond to price US Treasury TIPS

ian_dfw
Thank you very much, sir.