callable bonds

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

callable bonds

tibbar
Could anyone give me some ideas of how to price callable bonds in quantlib?

Bond features are:

- initial deferred period where the bond is not callable
- seperate strike price for exercise in each remaining year of the bond's life.

I've seen some discussions that the convertible bond class should be used, but as a newbee I'm a little intimidated by the quantlib terminology.

What I'd really need to know is what changes to make to the standard convertible sample code:

http://quantlib.org/reference/_convertible_bonds_8cpp-example.html

Many thanks.
Reply | Threaded
Open this post in threaded view
|

Re: callable bonds

tibbar
Here's where I've got to.

I started with the convertible bond example and:

- set conversion ratio to 0.0000001
- removed dividends
- removed the puttable bit
- set my callable terms

But, it seems the market value of the callable bond is unaffected by the choice of strike prices... (I tried high and low values).

My program is below, I also have some specific questions on syntax:

- what is the 1.20 for in:
SoftCallability(Callability::Price(
                                                   callPrices[i],
                                                   Callability::Price::Clean),
                                           schedule.date(callLength[i]),
                                           1.20)));

- why do I get time to maturity as 4.00822 in the output, when i set it to 4?  If I set it to 3, then the output says 3 exactly...

- what is the 1 for in the coupon definition: std::vector<Real> coupons(1, 0.065)?  Is this frequency of coupons per annum?

I'll be grateful for any feedback.

//// CODE SNIPPET/////
        boost::timer timer;
        std::cout << std::endl;

                Option::Type type(Option::Call);
        Real underlying = 36.0;
        Real spreadRate = 0.;//0.005;

        Spread dividendYield = 0.; //0.02;
        Rate riskFreeRate = 0.05;
        Volatility volatility = 0.10;

        Integer settlementDays = 0;
        Integer length = 4;
        Real redemption = 100.0;
        Real conversionRatio = 0.0000001; //redemption/underlying; // at the money

        // set up dates/schedules
        Calendar calendar = TARGET();
        Date today = calendar.adjust(Date::todaysDate());

        Settings::instance().evaluationDate() = today;
        Date settlementDate = calendar.advance(today, settlementDays, Days);
        Date exerciseDate = calendar.advance(settlementDate, length, Years);
        Date issueDate = calendar.advance(exerciseDate, -length, Years);

        BusinessDayConvention convention = ModifiedFollowing;

        Frequency frequency = Annual;

        Schedule schedule(issueDate, exerciseDate,
                          Period(frequency), calendar,
                          convention, convention,
                          DateGeneration::Backward, false);

        DividendSchedule dividends;
        CallabilitySchedule callability;

        std::vector<Real> coupons(1, 0.065);

        DayCounter bondDayCount =Actual365Fixed(); // Thirty360();

        Integer callLength[] = { 1, 2, 3 };  // Call dates, years 2, 4.
    //    Integer putLength[] = { 3 }; // Put dates year 3

                // these need to be less than npv of redemption and future coupons at 5% to bite!
        Real callPrices[] = { 140.0, 190.0, 102.0 };
    //    Real putPrices[]= { 105.0 };

        // Load call schedules
        for (Size i=0; i<LENGTH(callLength); i++) {
            callability.push_back(
                   boost::shared_ptr<Callability>(
                       new SoftCallability(Callability::Price(
                                                   callPrices[i],
                                                   Callability::Price::Clean),
                                           schedule.date(callLength[i]),
                                           1.20)));
        }

 /*       for (Size j=0; j<LENGTH(putLength); j++) {
            callability.push_back(
                   boost::shared_ptr<Callability>(
                           new Callability(Callability::Price(
                                                   putPrices[j],
                                                   Callability::Price::Clean),
                                           Callability::Put,
                                           schedule.date(putLength[j]))));
        }
*/

        DayCounter dayCounter = Actual365Fixed();
        Time maturity = dayCounter.yearFraction(settlementDate,
                                                exerciseDate);

        std::cout << "option type = "  << type << std::endl;
        std::cout << "Time to maturity = "        << maturity
                  << std::endl;
        std::cout << "Underlying price = "        << underlying
                  << std::endl;
        std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
                  << std::endl;
        std::cout << "Dividend yield = " << io::rate(dividendYield)
                  << std::endl;
        std::cout << "Volatility = " << io::volatility(volatility)
                  << std::endl;
        std::cout << std::endl;

        std::string method;
        std::cout << std::endl ;

        // write column headings
        Size widths[] = { 35, 14, 14 };
        Size totalWidth = widths[0] + widths[1] + widths[2];
        std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');

        std::cout << dblrule << std::endl;
        std::cout << "Tsiveriotis-Fernandes method" << std::endl;
        std::cout << dblrule << std::endl;
        std::cout << std::setw(widths[0]) << std::left << "Tree type"
                  << std::setw(widths[1]) << std::left << "European"
                  << std::setw(widths[1]) << std::left << "American"
                  << std::endl;
        std::cout << rule << std::endl;

        boost::shared_ptr<Exercise> exercise(
                                          new EuropeanExercise(exerciseDate));
        boost::shared_ptr<Exercise> amExercise(
                                          new AmericanExercise(settlementDate,
                                                               exerciseDate));

        Handle<Quote> underlyingH(
            boost::shared_ptr<Quote>(new SimpleQuote(underlying)));

        Handle<YieldTermStructure> flatTermStructure(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(settlementDate, riskFreeRate, dayCounter)));

        Handle<YieldTermStructure> flatDividendTS(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(settlementDate, dividendYield, dayCounter)));

        Handle<BlackVolTermStructure> flatVolTS(
            boost::shared_ptr<BlackVolTermStructure>(
                new BlackConstantVol(settlementDate, calendar,
                                     volatility, dayCounter)));


        boost::shared_ptr<BlackScholesMertonProcess> stochasticProcess(
                              new BlackScholesMertonProcess(underlyingH,
                                                            flatDividendTS,
                                                            flatTermStructure,
                                                            flatVolTS));

        Size timeSteps = 801;

        Handle<Quote> creditSpread(
                       boost::shared_ptr<Quote>(new SimpleQuote(spreadRate)));

        boost::shared_ptr<Quote> rate(new SimpleQuote(riskFreeRate));

        Handle<YieldTermStructure> discountCurve(
                boost::shared_ptr<YieldTermStructure>(
                    new FlatForward(today, Handle<Quote>(rate), dayCounter)));

        boost::shared_ptr<PricingEngine> engine(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps));

                ConvertibleFixedCouponBond europeanBond(
                            exercise, conversionRatio, dividends, callability,
                            creditSpread, issueDate, settlementDays,
                            coupons, bondDayCount, schedule, redemption);
        europeanBond.setPricingEngine(engine);

        ConvertibleFixedCouponBond americanBond(
                          amExercise, conversionRatio, dividends, callability,
                          creditSpread, issueDate, settlementDays,
                          coupons, bondDayCount, schedule, redemption);
        americanBond.setPricingEngine(engine);

        method = "Jarrow-Rudd";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

 

tibbar wrote
Could anyone give me some ideas of how to price callable bonds in quantlib?

Bond features are:

- initial deferred period where the bond is not callable
- seperate strike price for exercise in each remaining year of the bond's life.

I've seen some discussions that the convertible bond class should be used, but as a newbee I'm a little intimidated by the quantlib terminology.

What I'd really need to know is what changes to make to the standard convertible sample code:

http://quantlib.org/reference/_convertible_bonds_8cpp-example.html

Many thanks.
Reply | Threaded
Open this post in threaded view
|

Re: callable bonds

Allen Kuo
Tibbar: the QL convertible bond doesn't consider stochastic interest
rates, just stochastic stock prices. I think the volatility you
entered below is for the latter, not the former. So I don't think it
will reduce to a callable bond (where the optionality is a function of
interest rate volatility). Nice project would be to integrate this
feature into the convertible bond class- best way, I suppose, is to go
back to the 2-D Black Scholes. Bloomberg also has a 2-D model. I don't
think the TF or Ayache models naturally extend to stochastic interest
rates. Was working on the generic 2-D PDE solver, but I got
sidetracked with work.

Callable bonds should come out in the next release- I can send you the
pre-release code if you want.

Luigi: Can I get this email address added to
[hidden email] ?

GZH





On 3/8/08, tibbar <[hidden email]> wrote:

>
> Here's where I've got to.
>
> I started with the convertible bond example and:
>
> - set conversion ratio to 0.0000001
> - removed dividends
> - removed the puttable bit
> - set my callable terms
>
> But, it seems the market value of the callable bond is unaffected by the
> choice of strike prices... (I tried high and low values).
>
> My program is below, I also have some specific questions on syntax:
>
> - what is the 1.20 for in:
> SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>
> - why do I get time to maturity as 4.00822 in the output, when i set it to
> 4?  If I set it to 3, then the output says 3 exactly...
>
> - what is the 1 for in the coupon definition: std::vector<Real> coupons(1,
> 0.065)?  Is this frequency of coupons per annum?
>
> I'll be grateful for any feedback.
>
> //// CODE SNIPPET/////
>        boost::timer timer;
>        std::cout << std::endl;
>
>                Option::Type type(Option::Call);
>        Real underlying = 36.0;
>        Real spreadRate = 0.;//0.005;
>
>        Spread dividendYield = 0.; //0.02;
>        Rate riskFreeRate = 0.05;
>        Volatility volatility = 0.10;
>
>        Integer settlementDays = 0;
>        Integer length = 4;
>        Real redemption = 100.0;
>        Real conversionRatio = 0.0000001; //redemption/underlying; // at the
> money
>
>        // set up dates/schedules
>        Calendar calendar = TARGET();
>        Date today = calendar.adjust(Date::todaysDate());
>
>        Settings::instance().evaluationDate() = today;
>        Date settlementDate = calendar.advance(today, settlementDays, Days);
>        Date exerciseDate = calendar.advance(settlementDate, length, Years);
>        Date issueDate = calendar.advance(exerciseDate, -length, Years);
>
>        BusinessDayConvention convention = ModifiedFollowing;
>
>        Frequency frequency = Annual;
>
>        Schedule schedule(issueDate, exerciseDate,
>                          Period(frequency), calendar,
>                          convention, convention,
>                          DateGeneration::Backward, false);
>
>        DividendSchedule dividends;
>        CallabilitySchedule callability;
>
>        std::vector<Real> coupons(1, 0.065);
>
>        DayCounter bondDayCount =Actual365Fixed(); // Thirty360();
>
>        Integer callLength[] = { 1, 2, 3 };  // Call dates, years 2, 4.
>    //    Integer putLength[] = { 3 }; // Put dates year 3
>
>                // these need to be less than npv of redemption and future coupons at 5%
> to bite!
>        Real callPrices[] = { 140.0, 190.0, 102.0 };
>    //    Real putPrices[]= { 105.0 };
>
>        // Load call schedules
>        for (Size i=0; i<LENGTH(callLength); i++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                       new SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>        }
>
>  /*       for (Size j=0; j<LENGTH(putLength); j++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                           new Callability(Callability::Price(
>                                                   putPrices[j],
>
> Callability::Price::Clean),
>                                           Callability::Put,
>                                           schedule.date(putLength[j]))));
>        }
> */
>
>        DayCounter dayCounter = Actual365Fixed();
>        Time maturity = dayCounter.yearFraction(settlementDate,
>                                                exerciseDate);
>
>        std::cout << "option type = "  << type << std::endl;
>        std::cout << "Time to maturity = "        << maturity
>                  << std::endl;
>        std::cout << "Underlying price = "        << underlying
>                  << std::endl;
>        std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
>                  << std::endl;
>        std::cout << "Dividend yield = " << io::rate(dividendYield)
>                  << std::endl;
>        std::cout << "Volatility = " << io::volatility(volatility)
>                  << std::endl;
>        std::cout << std::endl;
>
>        std::string method;
>        std::cout << std::endl ;
>
>        // write column headings
>        Size widths[] = { 35, 14, 14 };
>        Size totalWidth = widths[0] + widths[1] + widths[2];
>        std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
>
>        std::cout << dblrule << std::endl;
>        std::cout << "Tsiveriotis-Fernandes method" << std::endl;
>        std::cout << dblrule << std::endl;
>        std::cout << std::setw(widths[0]) << std::left << "Tree type"
>                  << std::setw(widths[1]) << std::left << "European"
>                  << std::setw(widths[1]) << std::left << "American"
>                  << std::endl;
>        std::cout << rule << std::endl;
>
>        boost::shared_ptr<Exercise> exercise(
>                                          new
> EuropeanExercise(exerciseDate));
>        boost::shared_ptr<Exercise> amExercise(
>                                          new
> AmericanExercise(settlementDate,
>
> exerciseDate));
>
>        Handle underlyingH(
>            boost::shared_ptr(new SimpleQuote(underlying)));
>
>        Handle<YieldTermStructure> flatTermStructure(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, riskFreeRate, dayCounter)));
>
>        Handle<YieldTermStructure> flatDividendTS(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, dividendYield,
> dayCounter)));
>
>        Handle<BlackVolTermStructure> flatVolTS(
>            boost::shared_ptr<BlackVolTermStructure>(
>                new BlackConstantVol(settlementDate, calendar,
>                                     volatility, dayCounter)));
>
>
>        boost::shared_ptr<BlackScholesMertonProcess> stochasticProcess(
>                              new BlackScholesMertonProcess(underlyingH,
>                                                            flatDividendTS,
>
> flatTermStructure,
>                                                            flatVolTS));
>
>        Size timeSteps = 801;
>
>        Handle creditSpread(
>                       boost::shared_ptr(new SimpleQuote(spreadRate)));
>
>        boost::shared_ptr rate(new SimpleQuote(riskFreeRate));
>
>        Handle<YieldTermStructure> discountCurve(
>                boost::shared_ptr<YieldTermStructure>(
>                    new FlatForward(today, Handle(rate), dayCounter)));
>
>        boost::shared_ptr<PricingEngine> engine(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps));
>
>                ConvertibleFixedCouponBond europeanBond(
>                            exercise, conversionRatio, dividends,
> callability,
>                            creditSpread, issueDate, settlementDays,
>                            coupons, bondDayCount, schedule, redemption);
>        europeanBond.setPricingEngine(engine);
>
>        ConvertibleFixedCouponBond americanBond(
>                          amExercise, conversionRatio, dividends,
> callability,
>                          creditSpread, issueDate, settlementDays,
>                          coupons, bondDayCount, schedule, redemption);
>        americanBond.setPricingEngine(engine);
>
>        method = "Jarrow-Rudd";
>        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        std::cout << std::setw(widths[0]) << std::left << method
>                  << std::fixed
>                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
>                  << std::setw(widths[2]) << std::left << americanBond.NPV()
>                  << std::endl;
>
>
>
>
> tibbar wrote:
> >
> > Could anyone give me some ideas of how to price callable bonds in
> > quantlib?
> >
> > Bond features are:
> >
> > - initial deferred period where the bond is not callable
> > - seperate strike price for exercise in each remaining year of the bond's
> > life.
> >
> > I've seen some discussions that the convertible bond class should be used,
> > but as a newbee I'm a little intimidated by the quantlib terminology.
> >
> > What I'd really need to know is what changes to make to the standard
> > convertible sample code:
> >
> > http://quantlib.org/reference/_convertible_bonds_8cpp-example.html
> >
> > Many thanks.
> >
>
> --
> View this message in context: http://www.nabble.com/callable-bonds-tp15903645p15910210.html
> Sent from the quantlib-dev mailing list archive at Nabble.com.
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2008.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> QuantLib-dev mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: callable bonds

tibbar
If you could send the code that would be fantastic - I can do some testing to verify the results.

I think ideally as you say, the convertible class should also provide this functionality, as it is only showing part of the option value.

Thanks


Allen Kuo wrote
Tibbar: the QL convertible bond doesn't consider stochastic interest
rates, just stochastic stock prices. I think the volatility you
entered below is for the latter, not the former. So I don't think it
will reduce to a callable bond (where the optionality is a function of
interest rate volatility). Nice project would be to integrate this
feature into the convertible bond class- best way, I suppose, is to go
back to the 2-D Black Scholes. Bloomberg also has a 2-D model. I don't
think the TF or Ayache models naturally extend to stochastic interest
rates. Was working on the generic 2-D PDE solver, but I got
sidetracked with work.

Callable bonds should come out in the next release- I can send you the
pre-release code if you want.

Luigi: Can I get this email address added to
quantlib-dev@lists.sourceforge.net ?

GZH





On 3/8/08, tibbar <tibbar.gso@gmail.com> wrote:
>
> Here's where I've got to.
>
> I started with the convertible bond example and:
>
> - set conversion ratio to 0.0000001
> - removed dividends
> - removed the puttable bit
> - set my callable terms
>
> But, it seems the market value of the callable bond is unaffected by the
> choice of strike prices... (I tried high and low values).
>
> My program is below, I also have some specific questions on syntax:
>
> - what is the 1.20 for in:
> SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>
> - why do I get time to maturity as 4.00822 in the output, when i set it to
> 4?  If I set it to 3, then the output says 3 exactly...
>
> - what is the 1 for in the coupon definition: std::vector<Real> coupons(1,
> 0.065)?  Is this frequency of coupons per annum?
>
> I'll be grateful for any feedback.
>
> //// CODE SNIPPET/////
>        boost::timer timer;
>        std::cout << std::endl;
>
>                Option::Type type(Option::Call);
>        Real underlying = 36.0;
>        Real spreadRate = 0.;//0.005;
>
>        Spread dividendYield = 0.; //0.02;
>        Rate riskFreeRate = 0.05;
>        Volatility volatility = 0.10;
>
>        Integer settlementDays = 0;
>        Integer length = 4;
>        Real redemption = 100.0;
>        Real conversionRatio = 0.0000001; //redemption/underlying; // at the
> money
>
>        // set up dates/schedules
>        Calendar calendar = TARGET();
>        Date today = calendar.adjust(Date::todaysDate());
>
>        Settings::instance().evaluationDate() = today;
>        Date settlementDate = calendar.advance(today, settlementDays, Days);
>        Date exerciseDate = calendar.advance(settlementDate, length, Years);
>        Date issueDate = calendar.advance(exerciseDate, -length, Years);
>
>        BusinessDayConvention convention = ModifiedFollowing;
>
>        Frequency frequency = Annual;
>
>        Schedule schedule(issueDate, exerciseDate,
>                          Period(frequency), calendar,
>                          convention, convention,
>                          DateGeneration::Backward, false);
>
>        DividendSchedule dividends;
>        CallabilitySchedule callability;
>
>        std::vector<Real> coupons(1, 0.065);
>
>        DayCounter bondDayCount =Actual365Fixed(); // Thirty360();
>
>        Integer callLength[] = { 1, 2, 3 };  // Call dates, years 2, 4.
>    //    Integer putLength[] = { 3 }; // Put dates year 3
>
>                // these need to be less than npv of redemption and future coupons at 5%
> to bite!
>        Real callPrices[] = { 140.0, 190.0, 102.0 };
>    //    Real putPrices[]= { 105.0 };
>
>        // Load call schedules
>        for (Size i=0; i<LENGTH(callLength); i++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                       new SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>        }
>
>  /*       for (Size j=0; j<LENGTH(putLength); j++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                           new Callability(Callability::Price(
>                                                   putPrices[j],
>
> Callability::Price::Clean),
>                                           Callability::Put,
>                                           schedule.date(putLength[j]))));
>        }
> */
>
>        DayCounter dayCounter = Actual365Fixed();
>        Time maturity = dayCounter.yearFraction(settlementDate,
>                                                exerciseDate);
>
>        std::cout << "option type = "  << type << std::endl;
>        std::cout << "Time to maturity = "        << maturity
>                  << std::endl;
>        std::cout << "Underlying price = "        << underlying
>                  << std::endl;
>        std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
>                  << std::endl;
>        std::cout << "Dividend yield = " << io::rate(dividendYield)
>                  << std::endl;
>        std::cout << "Volatility = " << io::volatility(volatility)
>                  << std::endl;
>        std::cout << std::endl;
>
>        std::string method;
>        std::cout << std::endl ;
>
>        // write column headings
>        Size widths[] = { 35, 14, 14 };
>        Size totalWidth = widths[0] + widths[1] + widths[2];
>        std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
>
>        std::cout << dblrule << std::endl;
>        std::cout << "Tsiveriotis-Fernandes method" << std::endl;
>        std::cout << dblrule << std::endl;
>        std::cout << std::setw(widths[0]) << std::left << "Tree type"
>                  << std::setw(widths[1]) << std::left << "European"
>                  << std::setw(widths[1]) << std::left << "American"
>                  << std::endl;
>        std::cout << rule << std::endl;
>
>        boost::shared_ptr<Exercise> exercise(
>                                          new
> EuropeanExercise(exerciseDate));
>        boost::shared_ptr<Exercise> amExercise(
>                                          new
> AmericanExercise(settlementDate,
>
> exerciseDate));
>
>        Handle underlyingH(
>            boost::shared_ptr(new SimpleQuote(underlying)));
>
>        Handle<YieldTermStructure> flatTermStructure(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, riskFreeRate, dayCounter)));
>
>        Handle<YieldTermStructure> flatDividendTS(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, dividendYield,
> dayCounter)));
>
>        Handle<BlackVolTermStructure> flatVolTS(
>            boost::shared_ptr<BlackVolTermStructure>(
>                new BlackConstantVol(settlementDate, calendar,
>                                     volatility, dayCounter)));
>
>
>        boost::shared_ptr<BlackScholesMertonProcess> stochasticProcess(
>                              new BlackScholesMertonProcess(underlyingH,
>                                                            flatDividendTS,
>
> flatTermStructure,
>                                                            flatVolTS));
>
>        Size timeSteps = 801;
>
>        Handle creditSpread(
>                       boost::shared_ptr(new SimpleQuote(spreadRate)));
>
>        boost::shared_ptr rate(new SimpleQuote(riskFreeRate));
>
>        Handle<YieldTermStructure> discountCurve(
>                boost::shared_ptr<YieldTermStructure>(
>                    new FlatForward(today, Handle(rate), dayCounter)));
>
>        boost::shared_ptr<PricingEngine> engine(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps));
>
>                ConvertibleFixedCouponBond europeanBond(
>                            exercise, conversionRatio, dividends,
> callability,
>                            creditSpread, issueDate, settlementDays,
>                            coupons, bondDayCount, schedule, redemption);
>        europeanBond.setPricingEngine(engine);
>
>        ConvertibleFixedCouponBond americanBond(
>                          amExercise, conversionRatio, dividends,
> callability,
>                          creditSpread, issueDate, settlementDays,
>                          coupons, bondDayCount, schedule, redemption);
>        americanBond.setPricingEngine(engine);
>
>        method = "Jarrow-Rudd";
>        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        std::cout << std::setw(widths[0]) << std::left << method
>                  << std::fixed
>                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
>                  << std::setw(widths[2]) << std::left << americanBond.NPV()
>                  << std::endl;
>
>
>
>
> tibbar wrote:
> >
> > Could anyone give me some ideas of how to price callable bonds in
> > quantlib?
> >
> > Bond features are:
> >
> > - initial deferred period where the bond is not callable
> > - seperate strike price for exercise in each remaining year of the bond's
> > life.
> >
> > I've seen some discussions that the convertible bond class should be used,
> > but as a newbee I'm a little intimidated by the quantlib terminology.
> >
> > What I'd really need to know is what changes to make to the standard
> > convertible sample code:
> >
> > http://quantlib.org/reference/_convertible_bonds_8cpp-example.html
> >
> > Many thanks.
> >
>
> --
> View this message in context: http://www.nabble.com/callable-bonds-tp15903645p15910210.html
> Sent from the quantlib-dev mailing list archive at Nabble.com.
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2008.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> QuantLib-dev mailing list
> QuantLib-dev@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-dev mailing list
QuantLib-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: callable bonds

tibbar
In reply to this post by Allen Kuo
If you could send the code that would be fantastic - I can do some testing to verify the results.

I think ideally as you say, the convertible class should also provide this functionality, as it is only showing part of the option value.

Thanks


Allen Kuo wrote
Tibbar: the QL convertible bond doesn't consider stochastic interest
rates, just stochastic stock prices. I think the volatility you
entered below is for the latter, not the former. So I don't think it
will reduce to a callable bond (where the optionality is a function of
interest rate volatility). Nice project would be to integrate this
feature into the convertible bond class- best way, I suppose, is to go
back to the 2-D Black Scholes. Bloomberg also has a 2-D model. I don't
think the TF or Ayache models naturally extend to stochastic interest
rates. Was working on the generic 2-D PDE solver, but I got
sidetracked with work.

Callable bonds should come out in the next release- I can send you the
pre-release code if you want.

Luigi: Can I get this email address added to
quantlib-dev@lists.sourceforge.net ?

GZH





On 3/8/08, tibbar <tibbar.gso@gmail.com> wrote:
>
> Here's where I've got to.
>
> I started with the convertible bond example and:
>
> - set conversion ratio to 0.0000001
> - removed dividends
> - removed the puttable bit
> - set my callable terms
>
> But, it seems the market value of the callable bond is unaffected by the
> choice of strike prices... (I tried high and low values).
>
> My program is below, I also have some specific questions on syntax:
>
> - what is the 1.20 for in:
> SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>
> - why do I get time to maturity as 4.00822 in the output, when i set it to
> 4?  If I set it to 3, then the output says 3 exactly...
>
> - what is the 1 for in the coupon definition: std::vector<Real> coupons(1,
> 0.065)?  Is this frequency of coupons per annum?
>
> I'll be grateful for any feedback.
>
> //// CODE SNIPPET/////
>        boost::timer timer;
>        std::cout << std::endl;
>
>                Option::Type type(Option::Call);
>        Real underlying = 36.0;
>        Real spreadRate = 0.;//0.005;
>
>        Spread dividendYield = 0.; //0.02;
>        Rate riskFreeRate = 0.05;
>        Volatility volatility = 0.10;
>
>        Integer settlementDays = 0;
>        Integer length = 4;
>        Real redemption = 100.0;
>        Real conversionRatio = 0.0000001; //redemption/underlying; // at the
> money
>
>        // set up dates/schedules
>        Calendar calendar = TARGET();
>        Date today = calendar.adjust(Date::todaysDate());
>
>        Settings::instance().evaluationDate() = today;
>        Date settlementDate = calendar.advance(today, settlementDays, Days);
>        Date exerciseDate = calendar.advance(settlementDate, length, Years);
>        Date issueDate = calendar.advance(exerciseDate, -length, Years);
>
>        BusinessDayConvention convention = ModifiedFollowing;
>
>        Frequency frequency = Annual;
>
>        Schedule schedule(issueDate, exerciseDate,
>                          Period(frequency), calendar,
>                          convention, convention,
>                          DateGeneration::Backward, false);
>
>        DividendSchedule dividends;
>        CallabilitySchedule callability;
>
>        std::vector<Real> coupons(1, 0.065);
>
>        DayCounter bondDayCount =Actual365Fixed(); // Thirty360();
>
>        Integer callLength[] = { 1, 2, 3 };  // Call dates, years 2, 4.
>    //    Integer putLength[] = { 3 }; // Put dates year 3
>
>                // these need to be less than npv of redemption and future coupons at 5%
> to bite!
>        Real callPrices[] = { 140.0, 190.0, 102.0 };
>    //    Real putPrices[]= { 105.0 };
>
>        // Load call schedules
>        for (Size i=0; i<LENGTH(callLength); i++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                       new SoftCallability(Callability::Price(
>                                                   callPrices[i],
>
> Callability::Price::Clean),
>                                           schedule.date(callLength[i]),
>                                           1.20)));
>        }
>
>  /*       for (Size j=0; j<LENGTH(putLength); j++) {
>            callability.push_back(
>                   boost::shared_ptr<Callability>(
>                           new Callability(Callability::Price(
>                                                   putPrices[j],
>
> Callability::Price::Clean),
>                                           Callability::Put,
>                                           schedule.date(putLength[j]))));
>        }
> */
>
>        DayCounter dayCounter = Actual365Fixed();
>        Time maturity = dayCounter.yearFraction(settlementDate,
>                                                exerciseDate);
>
>        std::cout << "option type = "  << type << std::endl;
>        std::cout << "Time to maturity = "        << maturity
>                  << std::endl;
>        std::cout << "Underlying price = "        << underlying
>                  << std::endl;
>        std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
>                  << std::endl;
>        std::cout << "Dividend yield = " << io::rate(dividendYield)
>                  << std::endl;
>        std::cout << "Volatility = " << io::volatility(volatility)
>                  << std::endl;
>        std::cout << std::endl;
>
>        std::string method;
>        std::cout << std::endl ;
>
>        // write column headings
>        Size widths[] = { 35, 14, 14 };
>        Size totalWidth = widths[0] + widths[1] + widths[2];
>        std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
>
>        std::cout << dblrule << std::endl;
>        std::cout << "Tsiveriotis-Fernandes method" << std::endl;
>        std::cout << dblrule << std::endl;
>        std::cout << std::setw(widths[0]) << std::left << "Tree type"
>                  << std::setw(widths[1]) << std::left << "European"
>                  << std::setw(widths[1]) << std::left << "American"
>                  << std::endl;
>        std::cout << rule << std::endl;
>
>        boost::shared_ptr<Exercise> exercise(
>                                          new
> EuropeanExercise(exerciseDate));
>        boost::shared_ptr<Exercise> amExercise(
>                                          new
> AmericanExercise(settlementDate,
>
> exerciseDate));
>
>        Handle underlyingH(
>            boost::shared_ptr(new SimpleQuote(underlying)));
>
>        Handle<YieldTermStructure> flatTermStructure(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, riskFreeRate, dayCounter)));
>
>        Handle<YieldTermStructure> flatDividendTS(
>            boost::shared_ptr<YieldTermStructure>(
>                new FlatForward(settlementDate, dividendYield,
> dayCounter)));
>
>        Handle<BlackVolTermStructure> flatVolTS(
>            boost::shared_ptr<BlackVolTermStructure>(
>                new BlackConstantVol(settlementDate, calendar,
>                                     volatility, dayCounter)));
>
>
>        boost::shared_ptr<BlackScholesMertonProcess> stochasticProcess(
>                              new BlackScholesMertonProcess(underlyingH,
>                                                            flatDividendTS,
>
> flatTermStructure,
>                                                            flatVolTS));
>
>        Size timeSteps = 801;
>
>        Handle creditSpread(
>                       boost::shared_ptr(new SimpleQuote(spreadRate)));
>
>        boost::shared_ptr rate(new SimpleQuote(riskFreeRate));
>
>        Handle<YieldTermStructure> discountCurve(
>                boost::shared_ptr<YieldTermStructure>(
>                    new FlatForward(today, Handle(rate), dayCounter)));
>
>        boost::shared_ptr<PricingEngine> engine(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps));
>
>                ConvertibleFixedCouponBond europeanBond(
>                            exercise, conversionRatio, dividends,
> callability,
>                            creditSpread, issueDate, settlementDays,
>                            coupons, bondDayCount, schedule, redemption);
>        europeanBond.setPricingEngine(engine);
>
>        ConvertibleFixedCouponBond americanBond(
>                          amExercise, conversionRatio, dividends,
> callability,
>                          creditSpread, issueDate, settlementDays,
>                          coupons, bondDayCount, schedule, redemption);
>        americanBond.setPricingEngine(engine);
>
>        method = "Jarrow-Rudd";
>        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
>                  new
> BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
>                                                            timeSteps)));
>        std::cout << std::setw(widths[0]) << std::left << method
>                  << std::fixed
>                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
>                  << std::setw(widths[2]) << std::left << americanBond.NPV()
>                  << std::endl;
>
>
>
>
> tibbar wrote:
> >
> > Could anyone give me some ideas of how to price callable bonds in
> > quantlib?
> >
> > Bond features are:
> >
> > - initial deferred period where the bond is not callable
> > - seperate strike price for exercise in each remaining year of the bond's
> > life.
> >
> > I've seen some discussions that the convertible bond class should be used,
> > but as a newbee I'm a little intimidated by the quantlib terminology.
> >
> > What I'd really need to know is what changes to make to the standard
> > convertible sample code:
> >
> > http://quantlib.org/reference/_convertible_bonds_8cpp-example.html
> >
> > Many thanks.
> >
>
> --
> View this message in context: http://www.nabble.com/callable-bonds-tp15903645p15910210.html
> Sent from the quantlib-dev mailing list archive at Nabble.com.
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2008.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> QuantLib-dev mailing list
> QuantLib-dev@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-dev mailing list
QuantLib-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: callable bonds

Luigi Ballabio
In reply to this post by tibbar
On Fri, 2008-03-07 at 11:56 -0800, tibbar wrote:

> Could anyone give me some ideas of how to price callable bonds in quantlib?
>
> Bond features are:
>
> - initial deferred period where the bond is not callable
> - seperate strike price for exercise in each remaining year of the bond's
> life.
>
> I've seen some discussions that the convertible bond class should be used,
> but as a newbee I'm a little intimidated by the quantlib terminology.

As already pointed out, the ConvertibleBond class is not the right one
to use.  Instead, I would start from the Swaption class (together with
its TreeSwaptionEngine) and see how it works. You can copy the engine
and modify it so that it takes into account a single sequence of cash
flows, instead of two legs. Feel free to write to the list if you need
any help in understanding the Swaption or TreeSwaptionEngine class.

Later,
        Luigi


--

There is no opinion so absurd that some philosopher will not
express it.
-- Marcus Tullius Cicero, "Ad familiares"



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev