Re: qunatlib us treasury true yield

Posted by aexhg on
URL: http://quantlib.414.s1.nabble.com/qunatlib-us-treasury-true-yield-tp8100p8101.html

Hi,

Here's an example for two treasury bonds. The difference between the yields is small but this can have a larger impact on the risk calcualtion.


#include <iostream>
#include <ql\quantlib.hpp>
#include <string>
#include <boost\function.hpp>
#include <boost\bind.hpp>
using namespace QuantLib;



Real treasuryDirtyPrice(const Bond & bond, const Date & settlementDate,Real yield)
{
        Leg leg  = bond.cashflows();
        Real npv = 0.0;
        Real discount = 1.0;
        Date lastDate = settlementDate;
        Integer n     = leg.size();

        for(Integer i = 0; i < n; ++i)
        {
                boost::shared_ptr<CashFlow> cf = leg[i];
                Date paydate = cf->date();

                if(paydate > settlementDate)
                {
                        Real amount = cf->amount();
                        if(i != n - 1)
                        {
                                boost::shared_ptr<FixedRateCoupon> coupon = boost::dynamic_pointer_cast<FixedRateCoupon>(cf);
                                if(cf)
                                {
                                        Date accStart = coupon->accrualStartDate();
                                        Date accEnd   = coupon->accrualEndDate();
                                        DayCounter dc = coupon->dayCounter();
                                        Real tau      = dc.yearFraction(lastDate,paydate,accStart,accEnd);
                                        discount     *= 1.0 / std::pow(( 1.0 + yield *0.5) ,tau * 2.0);
                                        lastDate      = paydate;
                                }
                        }
                        npv += discount * amount;
                }
       
        }
        return npv / bond.notional(settlementDate) * 100.0;

}

Real objFunc(const Bond & bond, const Date & settlementDate, Real mktDirtyPrice, Real yield)
{
        return mktDirtyPrice - treasuryDirtyPrice(bond,settlementDate,yield);
}

Real semiAnnualTreasuryYield(const Bond & bond, const Date & settlementDate, Real cleanPrice)
{
        Real dirtyPrice = cleanPrice + bond.accruedAmount(settlementDate);
        Secant solver;

        boost::function<Real (Real)> f(boost::bind(objFunc,bond,settlementDate,dirtyPrice,_1));

    solver.setMaxEvaluations(100);
        return solver.solve(f, 1E-10, 0.05,0.005);
}

int main() {

        const int nBonds = 2;
        const std::string isins []  = { "US912810FB99" , "US912828TN08"};
        const Date issueDates []  = { Date(17,Nov,1997) , Date(31,Aug,2012) };
        const Date maturityDates [] = { Date(15,Nov,2027) , Date(31,Aug,2019) };
        const Date firstCouponDates [] = { Date(15,May,1998) , Date(31,Aug,2012) };
        const Integer eom [] = {0, 1};
        const Real coupons [] = { 0.06125 , 0.01};
        const Real mktPrices [] = { 149.703125,99.199853 };
        const Real streetYields [] = { 2.2194243 , 1.220000};
        const Real trueYields [] = { 2.2193023 , 1.120670 };

        Calendar calendar     = UnitedStates(UnitedStates::GovernmentBond);
        DayCounter dayCounter = ActualActual(ActualActual::ISMA);
        Date today        = Date(31,Oct,2012);
        Date settle       = calendar.advance(today,1,Days);

       
        std::cout << std::setw(15) << "Bond ISIN"     << "|"
                          << std::setw(12) << "QL Yield"      << "|"
                          << std::setw(12) << "my Yield"      << "|"
                          << std::setw(12) << "str. Yield"    << "|"
                          << std:: setw(12)<< "true Yield"    << "|"
                          << std::endl;



        for(int i = 0; i < nBonds; ++i)
        {
                Schedule sched    = Schedule(issueDates[i],maturityDates[i],Period(6,TimeUnit::Months),calendar,
                                                                        Unadjusted,Unadjusted,DateGeneration::Backward,eom[i],firstCouponDates[i]);
                FixedRateBond bond(1,100.0,sched,std::vector<Rate>(1,coupons[i]),
                                                        dayCounter,Following,100.0,
                                                    issueDates[i],calendar);

                Real yld          = BondFunctions::yield(bond,mktPrices[i],dayCounter,Compounded,Semiannual,settle) * 100.0;
                Real myyld        = semiAnnualTreasuryYield(bond,settle,mktPrices[i]) * 100.0;
                Real streetYld    = streetYields[i];
                Real trueYld      = trueYields[i];
                std::cout<< std::setw(15) << isins[i] << "|"
                                 << std::setw(12) << yld   << std::setprecision(8) << "|"
                             << std::setw(12) << myyld << std::setprecision(8) << "|"
                                 << std::setw(12) << streetYld << std::setprecision(8) << "|"
                                 << std::setw(12) << trueYld   << std::setprecision(8) << "|"
                                 << std::endl;

        }

         
        std::cin.get();
        return 0;

}

and the output I get is:

          Bond ISIN|    QL Yield|      my Yield|     str. Yield|  true Yield|
   US912810FB99|     2.21942|   2.2193023|   2.2194243|   2.2193023|
   US912828TN08|   1.1219999|    1.120655|           1.22|     1.12067|

Thanks.
aexhg wrote
Hi,
I'm trying to match up the true yield calculation of us treasury (bbg) with quantlib. It seems to me that the cashflows::npv() does not take into account the coupon referencePeriodBegin & referencePeriodEnd, so for us treasuries with bad days, specifying a daycount convention of ISMA, I'll never quite match the quoted bbg yield.  I was just wondering if I'm missing something or if there's a workaround?