qunatlib us treasury true yield

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

qunatlib us treasury true yield

aexhg
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?

Reply | Threaded
Open this post in threaded view
|

Re: qunatlib us treasury true yield

Luigi Ballabio
Hi,
    apologies for the delay.  May you provide some code that
reproduces the problem?

Luigi

On Thu, Oct 18, 2012 at 1:29 PM, aexhg <[hidden email]> 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?
>
>
> --
> View this message in context: http://old.nabble.com/qunatlib-us-treasury-true-yield-tp34572445p34572445.html
> Sent from the quantlib-users mailing list archive at Nabble.com.
>
>
> ------------------------------------------------------------------------------
> Everyone hates slow websites. So do we.
> Make your web apps faster with AppDynamics
> Download AppDynamics Lite for free today:
> http://p.sf.net/sfu/appdyn_sfd2d_oct
> _______________________________________________
> QuantLib-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-users

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: qunatlib us treasury true yield

aexhg
In reply to this post by aexhg
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?
Reply | Threaded
Open this post in threaded view
|

Re: qunatlib us treasury true yield

Luigi Ballabio
Hi,
    you're right, the current implementation doesn't take into account
the reference period.

The changes at <https://github.com/lballabio/quantlib-mods/commit/7403bbe72c1278a55ca605ecd8b1a32e1ecfe3ea>
fix this and bring QuantLib numbers in accord with the quoted ones
(the diffs are not that clear, so you might want to look at the
resulting file at
<https://github.com/lballabio/quantlib-mods/blob/7403bbe72c1278a55ca605ecd8b1a32e1ecfe3ea/QuantLib/ql/cashflows/cashflows.cpp>
instead).

May someone else validate this before I check it in?

Thanks,
     Luigi


On Thu, Nov 1, 2012 at 12:28 PM, aexhg <[hidden email]> wrote:

>
> 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?
>>
>>
>>
>
> --
> View this message in context: http://old.nabble.com/qunatlib-us-treasury-true-yield-tp34572445p34628075.html
> Sent from the quantlib-users mailing list archive at Nabble.com.
>
>
> ------------------------------------------------------------------------------
> LogMeIn Central: Instant, anywhere, Remote PC access and management.
> Stay in control, update software, and manage PCs from one command center
> Diagnose problems and improve visibility into emerging IT issues
> Automate, monitor and manage. Do more in less time with Central
> http://p.sf.net/sfu/logmein12331_d2d
> _______________________________________________
> QuantLib-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-users

------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: qunatlib us treasury true yield

Luigi Ballabio
Henri,
    I've added the fix to the repository. Thanks for the heads-up.

Luigi


On Mon, Nov 19, 2012 at 10:45 AM, Luigi Ballabio
<[hidden email]> wrote:

> Hi,
>     you're right, the current implementation doesn't take into account
> the reference period.
>
> The changes at <https://github.com/lballabio/quantlib-mods/commit/7403bbe72c1278a55ca605ecd8b1a32e1ecfe3ea>
> fix this and bring QuantLib numbers in accord with the quoted ones
> (the diffs are not that clear, so you might want to look at the
> resulting file at
> <https://github.com/lballabio/quantlib-mods/blob/7403bbe72c1278a55ca605ecd8b1a32e1ecfe3ea/QuantLib/ql/cashflows/cashflows.cpp>
> instead).
>
> May someone else validate this before I check it in?
>
> Thanks,
>      Luigi
>
>
> On Thu, Nov 1, 2012 at 12:28 PM, aexhg <[hidden email]> wrote:
>>
>> 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?
>>>
>>>
>>>
>>
>> --
>> View this message in context: http://old.nabble.com/qunatlib-us-treasury-true-yield-tp34572445p34628075.html
>> Sent from the quantlib-users mailing list archive at Nabble.com.
>>
>>
>> ------------------------------------------------------------------------------
>> LogMeIn Central: Instant, anywhere, Remote PC access and management.
>> Stay in control, update software, and manage PCs from one command center
>> Diagnose problems and improve visibility into emerging IT issues
>> Automate, monitor and manage. Do more in less time with Central
>> http://p.sf.net/sfu/logmein12331_d2d
>> _______________________________________________
>> QuantLib-users mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/quantlib-users

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users