Posted by
John Maiden on
May 25, 2007; 12:27am
URL: http://quantlib.414.s1.nabble.com/Proposed-change-to-Convertible-Bond-model-tp9499.html
Working through and trying to understand the convertible bond model, and came up
with a proposed change. At the moment the model requires fixed cash dividends.
Proposed change to code would allow user to either choose a fixed cash dividend
(through using a FixedDividend) or a fixed percent dividend (through using a
FractionalDividend). Changes would be made to discretizedconvertible.cpp and
binomialconvertibleengine.hpp.
Besides changes to the code below, an additional change might have to
be made to DiscretizedConvertible::DiscretizedConvertible through its
initialization of the Array dividendValues_, though I'm not sure where else (or
how) in the program this array is used.
The code (changes are marked):
//Proposed change to dividends in DiscretizedConvertible.cpp
Disposable<Array> DiscretizedConvertible::adjustedGrid() const {
Time t = time();
Array grid = method()->grid(t);
// add back all dividend amounts in the future
for (Size i=0; i<arguments_.dividends.size(); i++) {
Time dividendTime = arguments_.dividendTimes[i];
if (dividendTime >= t || close(dividendTime,t)) {
const boost::shared_ptr<Dividend>& d = arguments_.dividends[i];
//begin proposed change
boost::shared_ptr<Dividend> testdiv =
boost::dynamic_pointer_cast<FixedDividend>(arguments_.dividends[i]);
if(testdiv){
for (Size j=0; j<grid.size(); j++)
grid[j] += d->amount(grid[j]);
} else {
for (Size j=0; j<grid.size(); j++)
grid[j] *= (1 + d->amount(grid[j]));
}
//end change
//begin original code
/* for (Size j=0; j<grid.size(); j++)
grid[j] += d->amount(grid[j]); */
//end original code
}
}
return grid;
}
//Proposed change to dividends in BinomialConvertibleEngine.hpp
template <class T>
void BinomialConvertibleEngine<T>::calculate() const {
boost::shared_ptr<GeneralizedBlackScholesProcess> process =
boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
this->arguments_.stochasticProcess);
QL_REQUIRE(process, "Black-Scholes process required");
DayCounter rfdc = process->riskFreeRate()->dayCounter();
DayCounter divdc = process->dividendYield()->dayCounter();
DayCounter voldc = process->blackVolatility()->dayCounter();
Real s0 = process->stateVariable()->value();
Volatility v = process->blackVolatility()->blackVol(
arguments_.exercise->lastDate(), s0);
Date maturityDate = arguments_.exercise->lastDate();
Rate riskFreeRate = process->riskFreeRate()->zeroRate(
maturityDate, rfdc, Continuous, NoFrequency);
Rate q = process->dividendYield()->zeroRate(
maturityDate, divdc, Continuous, NoFrequency);
Date referenceDate = process->riskFreeRate()->referenceDate();
// subtract dividends
Size i;
for (i=0; i<arguments_.dividends.size(); i++) {
boost::shared_ptr<Dividend> testdiv =
boost::dynamic_pointer_cast<FixedDividend>(arguments_.dividends[i]);
// begin proposed change
if(testdiv){
if (arguments_.dividends[i]->date() >= referenceDate)
s0 -= arguments_.dividends[i]->amount() *
process->riskFreeRate()->discount(
arguments_.dividends[i]->date());
} else {
if (arguments_.dividends[i]->date() >= referenceDate)
s0 /= (1 + arguments_.dividends[i]->amount()) *
process->riskFreeRate()->discount(
arguments_.dividends[i]->date());
}
//end proposed change
//begin original code
/*
if (arguments_.dividends[i]->date() >= referenceDate)
s0 -= arguments_.dividends[i]->amount() *
process->riskFreeRate()->discount(
arguments_.dividends[i]->date());
*/
//end original code
}
QL_REQUIRE(s0 > 0.0,
"negative value after subtracting dividends");
// binomial trees with constant coefficient
Handle<Quote> underlying(
boost::shared_ptr<Quote>(new SimpleQuote(s0)));
Handle<YieldTermStructure> flatRiskFree(
boost::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, riskFreeRate, rfdc)));
Handle<YieldTermStructure> flatDividends(
boost::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, q, divdc)));
Handle<BlackVolTermStructure> flatVol(
boost::shared_ptr<BlackVolTermStructure>(
new BlackConstantVol(referenceDate, v, voldc)));
boost::shared_ptr<PlainVanillaPayoff> payoff =
boost::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
QL_REQUIRE(payoff, "non-plain payoff given");
Time maturity = rfdc.yearFraction(arguments_.settlementDate,
maturityDate);
boost::shared_ptr<StochasticProcess1D> bs(
new GeneralizedBlackScholesProcess(underlying, flatDividends,
flatRiskFree, flatVol));
boost::shared_ptr<T> tree(new T(bs, maturity, timeSteps_,
payoff->strike()));
Real creditSpread = arguments_.creditSpread->value();
boost::shared_ptr<NumericalMethod> lattice(
new TsiveriotisFernandesLattice<T>(tree,riskFreeRate,maturity,
timeSteps_,creditSpread,v,q));
// adjust times to grid
TimeGrid grid(maturity, timeSteps_);
for (i=0; i<arguments_.couponTimes.size(); i++)
arguments_.couponTimes[i] =
grid.closestTime(arguments_.couponTimes[i]);
for (i=0; i<arguments_.stoppingTimes.size(); i++)
arguments_.stoppingTimes[i] =
grid.closestTime(arguments_.stoppingTimes[i]);
for (i=0; i<arguments_.callabilityTimes.size(); i++)
arguments_.callabilityTimes[i] =
grid.closestTime(arguments_.callabilityTimes[i]);
for (i=0; i<arguments_.dividendTimes.size(); i++)
arguments_.dividendTimes[i] =
grid.closestTime(arguments_.dividendTimes[i]);
DiscretizedConvertible convertible(arguments_);
convertible.initialize(lattice, maturity);
convertible.rollback(0.0);
results_.value = convertible.presentValue();
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev