|
From: Allen K. <all...@ya...> - 2006-08-01 07:03:30
|
Hi:
I'm trying to build a callable bond class and was wondering what a QL preferred design would be. Two possibilities are below. I liked the economy of the first method but the ConvertibleBond class is designed the second way, so was not sure how to proceed.
Thanks,
Allen
(1)
class CallableBond : public Bond {
public:
CallableBond(const boost::shared_ptr<Bond> bond&
const boost::shared_ptr<PricingEngine>& engine,
const CallabilitySchedule& callability,
);
etc.
}
i.e. first need to construct a FixedCouponBond, FloatingRateBond or ZeroCouponBond and then pass it in to the CallableBond constructor (which then implicitly defines the callable bond). Theoretically, a ConvertibleBond could also be passed into the constructor to make it callable, though some equity/interest rate correlations would have to be handled/modeled within it.
(2)
Analogous to the ConvertibleBond class, we would have three explicit constructors for
each of three types of bonds ( CallableZeroCouponBond , CallableFloatingRateBond ,
CallableFixedCouponBond ). Doing it this way, in the future though, we might need three more constructors for convertible bonds: CallableConvertibleFloatingRateBond,
CallableConvertibleFixedCouponBond, CallableConvertibleZeroCouponBond.
Example below, analogous to ConvertibleBond class:
class CallableBond : public Bond {
public:
CallableBond( .... );
}
class CallableZeroCouponBond : public CallableBond {
public:
CallableZeroCouponBond( .... );
}
class CallableFloatingRateBond : public CallableBond {
public:
CallableFloatingRateBond( .... );
}
class CallableFixedCouponBond : public CallableBond {
public:
CallableFixedCouponBond( .... );
}
---------------------------------
See the all-new, redesigned Yahoo.com. Check it out. |
|
From: Allen K. <zho...@gm...> - 2007-07-14 06:54:55
|
Hi: I built a CallableFixedRateBond and would eventually like to make a contribution to QuantLib. Was wondering if we can we take callability to be a **feature** of a FixedRateBond, rather than developing a new class CallableFixedRateBond (construction of a FixedRateBond without the engine would resort to the original discounted cashflow NPV calculation). If the notion of a Quantlib::FixedRateBond can be expanded to include embedded optionality, class names also become shorter (they are getting long=85..), = e.g. TreeFixedRateBondEngine versus TreeCallableFixedRateBondEngine. I remember seeing this on the discussion thread a while back. If I know the preferred architecture in advance, I can make some adjustments to class names now. Thanks. |
|
From: John M. <jwm...@ya...> - 2007-07-23 12:19:59
|
Allen-
Maybe I'm missing something here, but wouldn't a
callable fixed rate bond be similar to a convertible bond?
All you have to do is make it a European option and then
set the conversion ratio so small that it will never be
converted at the final time.
As for your bond spread issue, if you use a convertible
bond then you can also alter the Black-Scholes process that
goes into the bond to include zero curves.
John
|
|
From: Luigi B. <lui...@gm...> - 2007-08-03 14:47:25
|
On Mon, 2007-07-23 at 12:19 +0000, John Maiden wrote: > Allen- > > Maybe I'm missing something here, but wouldn't a > callable fixed rate bond be similar to a convertible bond? > All you have to do is make it a European option and then > set the conversion ratio so small that it will never be > converted at the final time. Yes, in principle; but the current implementation of convertible bonds builds an equity tree and uses deterministic interest rates. This approximation works if variations in the equity value have a much bigger effect on price than variations in the interest rates. If you take the convertibility away, the assumption breaks down. Later, Luigi -- Greenspun's Tenth Rule of Programming: Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp. |
|
From: Luigi B. <lui...@gm...> - 2007-08-03 14:34:49
|
Hi Allen, apologies for the delay. I hope I'm not discouraging you or others from participating to the project... On Sat, 2007-07-14 at 02:54 -0400, Allen Kuo wrote: > Hi: I built a CallableFixedRateBond and would eventually like to make > a contribution to QuantLib. Was wondering if we can we take > callability to be a *feature* of a FixedRateBond, rather than > developing a new class CallableFixedRateBond (construction of a > FixedRateBond without the engine would resort to the original > discounted cashflow NPV calculation). As a gut feeling, I'd keep it a separate class. > If the notion of a Quantlib::FixedRateBond can be expanded to > include embedded optionality, class names also become shorter (they > are getting long…..), e.g. TreeFixedRateBondEngine versus > TreeCallableFixedRateBondEngine. True, but I would also keep the vanilla bonds simple---new users have enough difficulties already... also, I'm thinking of the possibility of having callable zero-coupon or floating-rate bonds too. Keeping it separate might help abstracting out the code for callability, so that part of it might be reused between such bonds. Later, Luigi -- The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" but "That's funny..." -- Isaac Asimov |
|
From: Luigi B. <lui...@gm...> - 2006-08-03 09:50:19
|
On 08/01/2006 09:03:20 AM, Allen Kuo wrote:
> I'm trying to build a callable bond class and was wondering what a
> QL preferred design would be. Two possibilities are below. I liked =20
> the economy of the first method but the ConvertibleBond class is =20
> designed the second way, so was not sure how to proceed.
>=20
> (1)
> class CallableBond : public Bond {
> public:
> CallableBond(const boost::shared_ptr<Bond> bond&
> const boost::shared_ptr<PricingEngine>& engine,
> const CallabilitySchedule& callability,
> );
> etc.
> }
I like this one, but the problem is that the engine should know what =20
kind of bond it's being passed---or at least what kind of coupons it =20
contains. I.e., if you choose a tree engine, fixed-rate and =20
floating-rate coupons will be discounted in a different way on the =20
tree. Therefore, the above mightn't be as generic as it seems.
> (2)
> Analogous to the ConvertibleBond class, we would have three =20
> explicit constructors for each of three types of bonds ( =20
> CallableZeroCouponBond , CallableFloatingRateBond , =20
> CallableFixedCouponBond ).
This might be less nice, but it has the advantage of specifying the =20
kind of bond to be called. I would go for this one first; after the =20
code is done, we might try some refactoring to bring it closer to the =20
first design.
> Doing it this way, in the future though, we
> might need three more constructors for convertible bonds:
No, convertible bonds manage callability already. (By the way, you can =20
look at the relevant classes---Callability and such---so that you can =20
reuse them.)
Later,
Luigi
----------------------------------------
Cogito ergo I'm right and you're wrong.
-- Blair Houghton
|
|
From: tibbar <tib...@gm...> - 2008-03-07 19:56:34
|
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-tp15903645p15903645.html Sent from the quantlib-dev mailing list archive at Nabble.com. |
|
From: tibbar <tib...@gm...> - 2008-03-08 01:54:42
|
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.
|
|
From: Zhonghua G. <zho...@gm...> - 2008-03-08 02:12:21
|
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
qua...@li... ?
GZH
On 3/8/08, tibbar <tib...@gm...> 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
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>
|
|
From: tibbar <tib...@gm...> - 2008-03-08 09:45:27
|
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
> qua...@li... ?
>
> GZH
>
>
>
>
>
> On 3/8/08, tibbar <tib...@gm...> 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
>> Qua...@li...
>> 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
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>
>
--
View this message in context: http://www.nabble.com/callable-bonds-tp15903645p15912808.html
Sent from the quantlib-dev mailing list archive at Nabble.com.
|
|
From: tibbar <tib...@gm...> - 2008-03-08 13:05:22
|
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
> qua...@li... ?
>
> GZH
>
>
>
>
>
> On 3/8/08, tibbar <tib...@gm...> 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
>> Qua...@li...
>> 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
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-dev
>
>
--
View this message in context: http://www.nabble.com/callable-bonds-tp15903645p15912878.html
Sent from the quantlib-dev mailing list archive at Nabble.com.
|
|
From: Luigi B. <lui...@gm...> - 2008-03-10 17:06:42
|
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" |