FixedCouponBond pricing wrong?

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

FixedCouponBond pricing wrong?

Feng Ning
I am new to QuantLib. Hope sb. can help me this out.

See the test_suite/bonds.cpp, testCachedYield() function.
For bond1, the marketPrice1=99.203125.
However, my caculation on scratch paper shows the price
p = c*(u+u^2+u^3+u^4) + 1*u^4 = 98.41
where c = 0.025, u =1/(1+y/2)

The two results differ. I realize that I use a different calendar and
daycounting scheme. So I hack the bonds.cpp code to use
Calandar bondCalendar = TARGET();
DayCounter bondDayCount = OneDayCounter();

then, the program computes the price = 95.91, still differ!

Anybody knows why?


Reply | Threaded
Open this post in threaded view
|

Re: FixedCouponBond pricing wrong?

Luigi Ballabio
On 04/22/05 01:09:04, Feng Ning wrote:
>
> See the test_suite/bonds.cpp, testCachedYield() function.
> For bond1, the marketPrice1=99.203125.
> However, my caculation on scratch paper shows the price
> p = c*(u+u^2+u^3+u^4) + 1*u^4 = 98.41
> where c = 0.025, u =1/(1+y/2)

What figures did you put into your calculation? The formula is correct (and  
the calendar and day counter used in testCachedYield are consistent with  
it,) but I get
c = 0.025/2 = 0.0125
y = 0.02925
u = 1/(1+y/2) = 0.98559
p = c*(u+u^2+u^3+u^4) + 1*u^4 = 99.18  (not 98.41)

There's still a difference, but it is due to the fact that your formula  
gives you the price at the issue date. The test calculates the bond price  
on November 22nd, 2004---22 days after. The difference is the discount  
factor between the two dates. If one edits the test and writes
Date today(30,October,2004);
the result is consistent with the formula.

Later,
        Luigi

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

Barker's Proof:
        Proofreading is more effective after publication.



Reply | Threaded
Open this post in threaded view
|

Re: FixedCouponBond pricing wrong?

Feng Ning
In reply to this post by Feng Ning
Thanks to Luigi for his reply. But the problem persist.
1) I am not clear what it means:
Date today(30, October, 2004);

I assume it means we should set the evaluation date, so I use:
   
Settings::instance().setEvaluationDate(Date(31,October,2004));
It turns out: calculated clean price=95.92, dirty price = 98.42.

2) my computation differs from Luigi's bcoz I feel that the coupon is
semiannual value, so I use c=0.025/2, instead of c=0.025.
I verify this by printing out the cashflows as in the code.

The complete code is below:
// bond-tester.cpp
#include <iostream>
#include <ql/quantlib.hpp>
using namespace QuantLib;

int main() {
    Settings::instance().setEvaluationDate(Date(31,October,2004));
    std::cout << "today date: "<< Date::todaysDate() << std::endl;
 
    Calendar bondCalendar = nullCalendar();
 
    DayCounter bondDayCount = OneDayCounter();
    Integer settlementDays = 1;

        // actual market values from the evaluation date

        FixedCouponBond bond1(Date(1,November,2004),
                          Date(31,October,2004),
                          Date(31,October,2006),
                          settlementDays,
                          0.025, Semiannual,
                          bondDayCount, bondCalendar,
                          Unadjusted, 100.0);

             
             
        Real marketPrice1 = 99.203125;
        Rate marketYield1 = 0.02925;
   
        // check
        Real tolerance = 1.0e-6;
        Real price, dprice, yield;
      // calculated values

        Real cachedPrice1 = 99.204505;
       Rate cachedYield1 = 0.029257;    
   
        price = bond1.cleanPrice(marketYield1);
        dprice = bond1.dirtyPrice(marketYield1);
   
        std::cout <<  "    calculated clean price: "
                   << DecimalFormatter::toString(price,6) << "\n"
           << "    calculated dirty price: "
           << DecimalFormatter::toString(dprice,6) << "\n"
                   << "    expected:   "
                   << DecimalFormatter::toString(cachedPrice1,6) << "\n"
                   << "    error:      "
                   << DecimalFormatter::toString(price-cachedPrice1,6)
<< std::endl;
       
    std::cout << " Show cashflow: \n";
    std::vector<boost::shared_ptr<CashFlow> > cashflows = bond1.cashflows();
     
    for (Size i=0; i<cashflows.size(); ++i) {
        std::cout << cashflows[i]->date() << ": " <<
cashflows[i]->amount() <<"\n";
    }
   
    return 0;
} //main




Reply | Threaded
Open this post in threaded view
|

RE: FixedCouponBond pricing wrong?

Jeffrey-J.Yu
In reply to this post by Feng Ning
Ning,

I think you present one extreme condition in the way you use FixedCouponBond:

1. the issue date is 11/1/04;
2. the settlement date is 11/1/04;

In reality, I dont know if you can do this.  However, you make a case that the
price/yield calculation should consider this, or prevent further calculation because of
the invalid entry.  Let me think about how this should be addressed.

You can certainly put in some more realistic inputs to test it out.

Cheers,
Jeff

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]]On Behalf Of Feng
Ning
Sent: Friday, April 22, 2005 10:23 AM
To: [hidden email]
Cc: [hidden email]
Subject: Re: [Quantlib-users] FixedCouponBond pricing wrong?


Thanks to Luigi for his reply. But the problem persist.
1) I am not clear what it means:
Date today(30, October, 2004);

I assume it means we should set the evaluation date, so I use:
   
Settings::instance().setEvaluationDate(Date(31,October,2004));
It turns out: calculated clean price=95.92, dirty price = 98.42.

2) my computation differs from Luigi's bcoz I feel that the coupon is
semiannual value, so I use c=0.025/2, instead of c=0.025.
I verify this by printing out the cashflows as in the code.

The complete code is below:
// bond-tester.cpp
#include <iostream>
#include <ql/quantlib.hpp>
using namespace QuantLib;

int main() {
    Settings::instance().setEvaluationDate(Date(31,October,2004));
    std::cout << "today date: "<< Date::todaysDate() << std::endl;
 
    Calendar bondCalendar = nullCalendar();
 
    DayCounter bondDayCount = OneDayCounter();
    Integer settlementDays = 1;

        // actual market values from the evaluation date

        FixedCouponBond bond1(Date(1,November,2004),
                          Date(31,October,2004),
                          Date(31,October,2006),
                          settlementDays,
                          0.025, Semiannual,
                          bondDayCount, bondCalendar,
                          Unadjusted, 100.0);

             
             
        Real marketPrice1 = 99.203125;
        Rate marketYield1 = 0.02925;
   
        // check
        Real tolerance = 1.0e-6;
        Real price, dprice, yield;
      // calculated values

        Real cachedPrice1 = 99.204505;
       Rate cachedYield1 = 0.029257;    
   
        price = bond1.cleanPrice(marketYield1);
        dprice = bond1.dirtyPrice(marketYield1);
   
        std::cout <<  "    calculated clean price: "
                   << DecimalFormatter::toString(price,6) << "\n"
           << "    calculated dirty price: "
           << DecimalFormatter::toString(dprice,6) << "\n"
                   << "    expected:   "
                   << DecimalFormatter::toString(cachedPrice1,6) << "\n"
                   << "    error:      "
                   << DecimalFormatter::toString(price-cachedPrice1,6)
<< std::endl;
       
    std::cout << " Show cashflow: \n";
    std::vector<boost::shared_ptr<CashFlow> > cashflows = bond1.cashflows();
     
    for (Size i=0; i<cashflows.size(); ++i) {
        std::cout << cashflows[i]->date() << ": " <<
cashflows[i]->amount() <<"\n";
    }
   
    return 0;
} //main




-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Quantlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users

Visit our website at http://www.ubs.com

This message contains confidential information and is intended only
for the individual named.  If you are not the named addressee you
should not disseminate, distribute or copy this e-mail.  Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses.  The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission.  If
verification is required please request a hard-copy version.  This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.



Reply | Threaded
Open this post in threaded view
|

Re: FixedCouponBond pricing wrong?

Luigi Ballabio
In reply to this post by Feng Ning
On Apr 22, 2005, at 4:23 PM, Feng Ning wrote:

> Thanks to Luigi for his reply. But the problem persist.
> 1) I am not clear what it means:
> Date today(30, October, 2004);
>
> I assume it means we should set the evaluation date, so I use:
>   Settings::instance().setEvaluationDate(Date(31,October,2004));

That is correct. In the test code there was:
Date today(...);
Settings::instance().setEvaluationDate(today);
which does the same thing.

> 2) my computation differs from Luigi's bcoz I feel that the coupon is
> semiannual value, so I use c=0.025/2, instead of c=0.025.

So did I. As I wrote in my previous mail,
c = 0.025/2 = 0.0125 (as you do correctly)
y = 0.02925
u = 1/(1+y/2) = 0.98559
p = c*(u+u^2+u^3+u^4) + 1*u^4 = 99.18  (not the 98.41 you mentioned.)
Can you check your sketch calculation against the above?

> The complete code is below:
> // bond-tester.cpp
> #include <iostream>
> #include <ql/quantlib.hpp>
> using namespace QuantLib;
>
> int main() {
>    Settings::instance().setEvaluationDate(Date(31,October,2004));
>    std::cout << "today date: "<< Date::todaysDate() << std::endl;
>    Calendar bondCalendar = nullCalendar();
>     DayCounter bondDayCount = OneDayCounter();

OneDayCounter is wrong. The ActualActual(ActualActual::ISMA) in the
test was correct; use that one. Alternatively, you can try
SimpleDayCounter().


>    Integer settlementDays = 1;
>
>        // actual market values from the evaluation date
>
>        FixedCouponBond bond1(Date(1,November,2004),
>                          Date(31,October,2004),
>                          Date(31,October,2006),
>                          settlementDays,
>                          0.025, Semiannual,                          
> bondDayCount, bondCalendar,
>                          Unadjusted, 100.0);
>
>                                Real marketPrice1 = 99.203125;        
> Rate marketYield1 = 0.02925;
>          // check
>        Real tolerance = 1.0e-6;
>        Real price, dprice, yield;
>      // calculated values
>
>        Real cachedPrice1 = 99.204505;

This is expected for evaluation date = November 22nd. For October 30
you should get 99.18 due to discounting between the two dates.


>       Rate cachedYield1 = 0.029257;             price =
> bond1.cleanPrice(marketYield1);
>        dprice = bond1.dirtyPrice(marketYield1);
>          std::cout <<  "    calculated clean price: "
>                   << DecimalFormatter::toString(price,6) << "\n"
>           << "    calculated dirty price: "
>           << DecimalFormatter::toString(dprice,6) << "\n"
>                   << "    expected:   "
>                   << DecimalFormatter::toString(cachedPrice1,6) << "\n"
>                   << "    error:      "
>                   << DecimalFormatter::toString(price-cachedPrice1,6)
> << std::endl;
>          std::cout << " Show cashflow: \n";
>    std::vector<boost::shared_ptr<CashFlow> > cashflows =
> bond1.cashflows();
>        for (Size i=0; i<cashflows.size(); ++i) {
>        std::cout << cashflows[i]->date() << ": " <<
> cashflows[i]->amount() <<"\n";
>    }
>      return 0;
> } //main

Later,
        Luigi



Reply | Threaded
Open this post in threaded view
|

Re: FixedCouponBond pricing wrong?

Luigi Ballabio
In reply to this post by Jeffrey-J.Yu
On Apr 22, 2005, at 4:38 PM, [hidden email] wrote:

> Ning,
>
> I think you present one extreme condition in the way you use
> FixedCouponBond:
>
> 1. the issue date is 11/1/04;
> 2. the settlement date is 11/1/04;
>
> In reality, I dont know if you can do this.

I don't know if you can in the real world, the calculation should work
correctly. At least it does on my machine with the latest code.

Luigi



Reply | Threaded
Open this post in threaded view
|

RE: FixedCouponBond pricing wrong?

Jeffrey-J.Yu
In reply to this post by Feng Ning
The dated date is when the interest start accrued.  In Ning's test code,
he is saying that the bond was traded before the issue date, so it can be
settled on the issue date (given the settlement convention he set is T+1.).

The cash flow is what determines the price/yield.  I am afraid this is a kind
of special case, in which the accrued day is 0.  Well, I suggest Ning pick a
different date in his test drive, at the same time we can think about how to
handle this.

When the trade date is prior to the issue date, the bond is quoted in yield,
instead of price.  When it is settled, the price would then be derived from the yield.






-----Original Message-----
From: Luigi Ballabio [mailto:[hidden email]]
Sent: Friday, April 22, 2005 3:55 PM
To: Yu, Jeffrey-J
Cc: [hidden email]; [hidden email]
Subject: Re: [Quantlib-users] FixedCouponBond pricing wrong?



On Apr 22, 2005, at 4:38 PM, [hidden email] wrote:

> Ning,
>
> I think you present one extreme condition in the way you use
> FixedCouponBond:
>
> 1. the issue date is 11/1/04;
> 2. the settlement date is 11/1/04;
>
> In reality, I dont know if you can do this.

I don't know if you can in the real world, the calculation should work
correctly. At least it does on my machine with the latest code.

Luigi


Visit our website at http://www.ubs.com

This message contains confidential information and is intended only
for the individual named.  If you are not the named addressee you
should not disseminate, distribute or copy this e-mail.  Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses.  The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission.  If
verification is required please request a hard-copy version.  This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.



Reply | Threaded
Open this post in threaded view
|

Re: FixedCouponBond pricing wrong?

Luigi Ballabio
On Apr 22, 2005, at 10:06 PM, [hidden email] wrote:

> The dated date is when the interest start accrued.  In Ning's test
> code,
> he is saying that the bond was traded before the issue date, so it can
> be
> settled on the issue date (given the settlement convention he set is
> T+1.).
>
> I am afraid this is a kind of special case, in which the accrued day
> is 0.

I agree. But this special case is exactly what you need for reproducing
Ning's back-of-the-envelope calculation. And indeed, the result is
consistent with the formula.

Later,
        Luigi