Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
binomialconvertibleengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2005, 2006 Theo Boafo
3 Copyright (C) 2006, 2007 StatPro Italia srl
4 Copyright (C) 2020 Quaternion Risk Managment Ltd
5
6 This file is part of ORE, a free-software/open-source library
7 for transparent pricing and risk analysis - http://opensourcerisk.org
8
9 ORE is free software: you can redistribute it and/or modify it
10 under the terms of the Modified BSD License. You should have received a
11 copy of the license along with this program.
12 The license is also available online at <http://opensourcerisk.org>
13
14 This program is distributed on the basis that it will form a useful
15 contribution to risk analytics and model standardisation, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
21
22#include <ql/methods/lattices/binomialtree.hpp>
23
24namespace QuantExt {
25
26template <class T>
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) {
33
34 QL_REQUIRE(timeSteps > 0, "timeSteps must be positive, " << timeSteps << " not allowed");
35 registerWith(process_);
36 registerWith(referenceCurve_);
37 registerWith(creditSpread_);
38 registerWith(defaultCurve_);
39}
40
41template <class T> void BinomialConvertibleEngine<T>::calculate() const {
42
43 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
44 DayCounter divdc = process_->dividendYield()->dayCounter();
45 DayCounter voldc = process_->blackVolatility()->dayCounter();
46 Calendar volcal = process_->blackVolatility()->calendar();
47
48 Real s0 = process_->x0();
49 QL_REQUIRE(s0 > 0.0, "negative or null underlying");
50 Volatility v = process_->blackVolatility()->blackVol(arguments_.maturityDate, s0);
51 Date maturityDate = arguments_.maturityDate;
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();
55
56 // subtract dividends
57 Size i;
58 for (i = 0; i < arguments_.dividends.size(); i++) {
59 if (arguments_.dividends[i]->date() >= referenceDate)
60 s0 -=
61 arguments_.dividends[i]->amount() * process_->riskFreeRate()->discount(arguments_.dividends[i]->date());
62 }
63 QL_REQUIRE(s0 > 0.0, "negative value after subtracting dividends");
64
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);
75 }
76
77 // binomial trees with constant coefficient
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)));
85
86 QuantLib::ext::shared_ptr<PlainVanillaPayoff> payoff = QuantLib::ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
87 QL_REQUIRE(payoff, "non-plain payoff given");
88
89 Time maturity = rfdc.yearFraction(arguments_.settlementDate, maturityDate);
90
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()));
94
95 // the lattice uses the eq process risk free rate, we use a credit spread over this rate which comprises
96 // - the credit spread itself
97 // - the spread between the eq risk free rate and the bond reference curve rate
98 // - an effective spread from the default curve taking into account the recovery via a first order approximation
99
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()) {
104 // default curve is optional
105 defaultRate = -std::log(defaultCurve_->survivalProbability(maturityDate)) /
106 rfdc.yearFraction(defaultCurve_->referenceDate(), maturityDate);
107 }
108 if (!creditSpread_.empty()) {
109 // credit spread is optional
110 creditRate = creditSpread_->value();
111 }
112 if (!recoveryRate_.empty()) {
113 // recovery rate is optional
114 recRate = recoveryRate_->value();
115 }
116
117 Real creditSpread = creditRate + (referenceCurveRate - riskFreeRate) + defaultRate * (1.0 - recRate);
118
119 QuantLib::ext::shared_ptr<Lattice> lattice(
120 new TsiveriotisFernandesLattice<T>(tree, riskFreeRate, maturity, timeSteps_, creditSpread, v, q));
121
123 arguments_, bs, Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(creditSpread)), TimeGrid(maturity, timeSteps_));
124
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");
129}
130
131// template instantiation, add here if you want to use others
132
134
135} // namespace QuantExt
binomial engine for convertible bonds
const Instrument::results * results_
Definition: cdsoption.cpp:81
Binomial Tsiveriotis-Fernandes engine for convertible bonds.
Handle< YieldTermStructure > referenceCurve_
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_
Binomial lattice approximating the Tsiveriotis-Fernandes model.
Definition: tflattice.hpp:34
Swap::arguments * arguments_