Skip to content

Commit

Permalink
Merge pull request #1220.
Browse files Browse the repository at this point in the history
Move credit spread and dividends to Binomial Convertible Engine
  • Loading branch information
lballabio committed Nov 9, 2021
2 parents 903de0f + 7c3518a commit 8dacf66
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 262 deletions.
52 changes: 19 additions & 33 deletions Examples/ConvertibleBonds/ConvertibleBonds.cpp
Expand Up @@ -193,27 +193,25 @@ int main(int, char* []) {

ext::shared_ptr<PricingEngine> engine(
new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
timeSteps));
timeSteps, creditSpread, dividends));

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

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

method = "Jarrow-Rudd";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -222,11 +220,9 @@ int main(int, char* []) {

method = "Cox-Ross-Rubinstein";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -236,12 +232,10 @@ int main(int, char* []) {
method = "Additive equiprobabilities";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(
stochasticProcess,
timeSteps)));
stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(
stochasticProcess,
timeSteps)));
stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -250,11 +244,9 @@ int main(int, char* []) {

method = "Trigeorgis";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -263,11 +255,9 @@ int main(int, char* []) {

method = "Tian";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Tian>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Tian>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Tian>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Tian>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -276,11 +266,9 @@ int main(int, char* []) {

method = "Leisen-Reimer";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand All @@ -289,11 +277,9 @@ int main(int, char* []) {

method = "Joshi";
europeanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Joshi4>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Joshi4>(stochasticProcess, timeSteps, creditSpread, dividends)));
americanBond.setPricingEngine(ext::shared_ptr<PricingEngine>(
new BinomialConvertibleEngine<Joshi4>(stochasticProcess,
timeSteps)));
new BinomialConvertibleEngine<Joshi4>(stochasticProcess, timeSteps, creditSpread, dividends)));
std::cout << std::setw(widths[0]) << std::left << method
<< std::fixed
<< std::setw(widths[1]) << std::left << europeanBond.NPV()
Expand Down
65 changes: 33 additions & 32 deletions ql/experimental/convertiblebonds/binomialconvertibleengine.hpp
Expand Up @@ -46,18 +46,28 @@ namespace QuantLib {
class BinomialConvertibleEngine : public ConvertibleBond::option::engine {
public:
BinomialConvertibleEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process,
Size timeSteps)
: process_(std::move(process)), timeSteps_(timeSteps) {
Size timeSteps,
const Handle<Quote>& creditSpread,
DividendSchedule dividends)
: process_(std::move(process)), timeSteps_(timeSteps),
dividends_(std::move(dividends)), creditSpread_(creditSpread)
{
QL_REQUIRE(timeSteps>0,
"timeSteps must be positive, " << timeSteps <<
" not allowed");

registerWith(process_);
registerWith(creditSpread);
}
void calculate() const override;
const Handle<Quote>& creditSpread() const { return creditSpread_; }
const DividendSchedule& dividends() const { return dividends_; }

private:
ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
Size timeSteps_;
DividendSchedule dividends_;
Handle<Quote> creditSpread_;
};


Expand All @@ -72,58 +82,49 @@ namespace QuantLib {
Real s0 = process_->x0();
QL_REQUIRE(s0 > 0.0, "negative or null underlying");
Volatility v = process_->blackVolatility()->blackVol(
arguments_.exercise->lastDate(), s0);
arguments_.exercise->lastDate(), s0);
Date maturityDate = arguments_.exercise->lastDate();
Rate riskFreeRate = process_->riskFreeRate()->zeroRate(
maturityDate, rfdc, Continuous, NoFrequency);
maturityDate, rfdc, Continuous, NoFrequency);
Rate q = process_->dividendYield()->zeroRate(
maturityDate, divdc, Continuous, NoFrequency);
maturityDate, divdc, Continuous, NoFrequency);
Date referenceDate = process_->riskFreeRate()->referenceDate();

// subtract dividends
Size i;
for (i=0; i<arguments_.dividends.size(); i++) {
if (arguments_.dividends[i]->date() >= referenceDate)
s0 -= arguments_.dividends[i]->amount() *
process_->riskFreeRate()->discount(
arguments_.dividends[i]->date());
for (i=0; i<dividends_.size(); i++) {
if (dividends_[i]->date() >= referenceDate)
s0 -= dividends_[i]->amount() *
process_->riskFreeRate()->discount(dividends_[i]->date());
}
QL_REQUIRE(s0 > 0.0,
"negative value after subtracting dividends");
"negative value after subtracting dividends");

// binomial trees with constant coefficient
Handle<Quote> underlying(ext::shared_ptr<Quote>(new SimpleQuote(s0)));
Handle<YieldTermStructure> flatRiskFree(
ext::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, riskFreeRate, rfdc)));
Handle<YieldTermStructure> flatRiskFree(ext::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, riskFreeRate, rfdc)));
Handle<YieldTermStructure> flatDividends(
ext::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, q, divdc)));
Handle<BlackVolTermStructure> flatVol(
ext::shared_ptr<BlackVolTermStructure>(
new BlackConstantVol(referenceDate, volcal, v, voldc)));
ext::shared_ptr<YieldTermStructure>(new FlatForward(referenceDate, q, divdc)));
Handle<BlackVolTermStructure> flatVol(ext::shared_ptr<BlackVolTermStructure>(
new BlackConstantVol(referenceDate, volcal, v, voldc)));

ext::shared_ptr<PlainVanillaPayoff> payoff =
ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
QL_REQUIRE(payoff, "non-plain payoff given");

Time maturity = rfdc.yearFraction(arguments_.settlementDate,
maturityDate);
Time maturity = rfdc.yearFraction(arguments_.settlementDate, maturityDate);

ext::shared_ptr<GeneralizedBlackScholesProcess> bs(
new GeneralizedBlackScholesProcess(underlying, flatDividends,
flatRiskFree, flatVol));
ext::shared_ptr<T> tree(new T(bs, maturity, timeSteps_,
payoff->strike()));
new GeneralizedBlackScholesProcess(underlying, flatDividends, flatRiskFree, flatVol));
ext::shared_ptr<T> tree(new T(bs, maturity, timeSteps_, payoff->strike()));

Real creditSpread = arguments_.creditSpread->value();
Real creditSpread = creditSpread_->value();

ext::shared_ptr<Lattice> lattice(
new TsiveriotisFernandesLattice<T>(tree,riskFreeRate,maturity,
timeSteps_,creditSpread,v,q));
ext::shared_ptr<Lattice> lattice(new TsiveriotisFernandesLattice<T>(
tree, riskFreeRate, maturity, timeSteps_, creditSpread, v, q));

DiscretizedConvertible convertible(arguments_, bs,
TimeGrid(maturity, timeSteps_));
DiscretizedConvertible convertible(arguments_, bs, dividends_, creditSpread_, TimeGrid(maturity, timeSteps_));

convertible.initialize(lattice, maturity);
convertible.rollback(0.0);
Expand All @@ -135,4 +136,4 @@ namespace QuantLib {
}


#endif
#endif

0 comments on commit 8dacf66

Please sign in to comment.