22#include <ql/methods/lattices/binomialtree.hpp>
28 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
const Handle<YieldTermStructure>& referenceCurve,
29 const Handle<Quote>& creditSpread,
const Handle<DefaultProbabilityTermStructure>& defaultCurve,
30 const Handle<Quote>& recoveryRate, Size timeSteps)
31 : process_(process), referenceCurve_(referenceCurve), creditSpread_(creditSpread), defaultCurve_(defaultCurve),
32 recoveryRate_(recoveryRate), timeSteps_(timeSteps) {
34 QL_REQUIRE(timeSteps > 0,
"timeSteps must be positive, " << timeSteps <<
" not allowed");
43 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
44 DayCounter divdc = process_->dividendYield()->dayCounter();
45 DayCounter voldc = process_->blackVolatility()->dayCounter();
46 Calendar volcal = process_->blackVolatility()->calendar();
48 Real s0 = process_->x0();
49 QL_REQUIRE(s0 > 0.0,
"negative or null underlying");
50 Volatility v = process_->blackVolatility()->blackVol(
arguments_.maturityDate, s0);
52 Rate riskFreeRate = process_->riskFreeRate()->zeroRate(maturityDate, rfdc, Continuous, NoFrequency);
53 Rate q = process_->dividendYield()->zeroRate(maturityDate, divdc, Continuous, NoFrequency);
54 Date referenceDate = process_->riskFreeRate()->referenceDate();
58 for (i = 0; i <
arguments_.dividends.size(); i++) {
59 if (
arguments_.dividends[i]->date() >= referenceDate)
61 arguments_.dividends[i]->amount() * process_->riskFreeRate()->discount(
arguments_.dividends[i]->date());
63 QL_REQUIRE(s0 > 0.0,
"negative value after subtracting dividends");
65 results_.additionalResults[
"securitySpread"] = creditSpread_.empty() ? 0.0 : creditSpread_->value();
66 results_.additionalResults[
"maturityTime"] = process_->riskFreeRate()->timeFromReference(maturityDate);
67 results_.additionalResults[
"riskFreeRate"] = riskFreeRate;
68 results_.additionalResults[
"dividendYield"] = q;
69 results_.additionalResults[
"equitySpot"] = s0;
70 results_.additionalResults[
"equityVol"] = v;
71 if (maturityDate > referenceCurve_->referenceDate()) {
72 results_.additionalResults[
"maturityDiscountFactor"] = referenceCurve_->discount(maturityDate);
73 results_.additionalResults[
"maturitySurvivalProbability"] =
74 defaultCurve_.empty() ? 1.0 : defaultCurve_->survivalProbability(maturityDate);
78 Handle<Quote> underlying(QuantLib::ext::shared_ptr<Quote>(
new SimpleQuote(s0)));
79 Handle<YieldTermStructure> flatRiskFree(
80 QuantLib::ext::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, riskFreeRate, rfdc)));
81 Handle<YieldTermStructure> flatDividends(
82 QuantLib::ext::shared_ptr<YieldTermStructure>(
new FlatForward(referenceDate, q, divdc)));
83 Handle<BlackVolTermStructure> flatVol(
84 QuantLib::ext::shared_ptr<BlackVolTermStructure>(
new BlackConstantVol(referenceDate, volcal, v, voldc)));
86 QuantLib::ext::shared_ptr<PlainVanillaPayoff> payoff = QuantLib::ext::dynamic_pointer_cast<PlainVanillaPayoff>(
arguments_.payoff);
87 QL_REQUIRE(payoff,
"non-plain payoff given");
89 Time maturity = rfdc.yearFraction(
arguments_.settlementDate, maturityDate);
91 QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess> bs(
92 new GeneralizedBlackScholesProcess(underlying, flatDividends, flatRiskFree, flatVol));
93 QuantLib::ext::shared_ptr<T> tree(
new T(bs, maturity, timeSteps_, payoff->strike()));
100 QL_REQUIRE(!referenceCurve_.empty(),
"BinomialConvertibleEngine::calculate(): empty reference curve");
101 Real referenceCurveRate = referenceCurve_->zeroRate(maturityDate, rfdc, Continuous, NoFrequency);
102 Real defaultRate = 0.0, creditRate = 0.0, recRate = 0.0;
103 if (!defaultCurve_.empty()) {
105 defaultRate = -std::log(defaultCurve_->survivalProbability(maturityDate)) /
106 rfdc.yearFraction(defaultCurve_->referenceDate(), maturityDate);
108 if (!creditSpread_.empty()) {
110 creditRate = creditSpread_->value();
112 if (!recoveryRate_.empty()) {
114 recRate = recoveryRate_->value();
117 Real creditSpread = creditRate + (referenceCurveRate - riskFreeRate) + defaultRate * (1.0 - recRate);
119 QuantLib::ext::shared_ptr<Lattice> lattice(
123 arguments_, bs, Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(creditSpread)), TimeGrid(maturity, timeSteps_));
125 convertible.initialize(lattice, maturity);
126 convertible.rollback(0.0);
127 results_.value = convertible.presentValue();
128 QL_ENSURE(
results_.value < std::numeric_limits<Real>::max(),
"floating-point overflow on tree grid");
binomial engine for convertible bonds
const Instrument::results * results_
Binomial Tsiveriotis-Fernandes engine for convertible bonds.
Handle< YieldTermStructure > referenceCurve_
void calculate() const override
BinomialConvertibleEngine(const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process, const Handle< YieldTermStructure > &referenceCurve, const Handle< Quote > &creditSpread, const Handle< DefaultProbabilityTermStructure > &defaultCurve, const Handle< Quote > &recoveryRate, Size timeSteps)
QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Handle< DefaultProbabilityTermStructure > defaultCurve_
Handle< Quote > creditSpread_
Binomial lattice approximating the Tsiveriotis-Fernandes model.
Swap::arguments * arguments_