Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
fdmdefaultableequityjumpdiffusionop.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 Quaternion Risk Management Ltd
3
4 This file is part of ORE, a free-software/open-source library
5 for transparent pricing and risk analysis - http://opensourcerisk.org
6
7 ORE is free software: you can redistribute it and/or modify it
8 under the terms of the Modified BSD License. You should have received a
9 copy of the license along with this program.
10 The license is also available online at <http://opensourcerisk.org>
11
12 This program is distributed on the basis that it will form a useful
13 contribution to risk analytics and model standardisation, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
16*/
17
19
20#include <ql/methods/finitedifferences/meshers/fdmmesher.hpp>
21#include <ql/methods/finitedifferences/operators/secondderivativeop.hpp>
22
23namespace QuantExt {
24
25using namespace QuantLib;
26
28 const QuantLib::ext::shared_ptr<QuantLib::FdmMesher>& mesher,
29 const QuantLib::ext::shared_ptr<DefaultableEquityJumpDiffusionModel>& model, const Size direction,
30 const std::function<Real(Real, Real, Real)>& recovery, const Handle<QuantLib::YieldTermStructure>& discountingCurve,
31 const Handle<QuantLib::Quote>& discountingSpread,
32 const Handle<QuantLib::DefaultProbabilityTermStructure>& addCreditCurve,
33 const std::function<Real(Real, Real, Real)>& addRecovery)
34 : mesher_(mesher), model_(model), direction_(direction), recovery_(recovery), discountingCurve_(discountingCurve),
35 addCreditCurve_(addCreditCurve), addRecovery_(addRecovery), discountingSpread_(discountingSpread),
36 dxMap_(FirstDerivativeOp(direction, mesher)), dxxMap_(SecondDerivativeOp(direction, mesher)),
37 mapT_(direction, mesher), recoveryTerm_(mesher_->locations(direction).size()) {}
38
40
42
43 Size n = mesher_->locations(direction_).size();
44
45 Real r = model_->r(t1);
46 Real q = model_->q(t1);
47 Real v = model_->sigma(t1) * model_->sigma(t1);
48
49 Array h(n);
50 for (Size i = 0; i < h.size(); ++i) {
51 h[i] = model_->h(t1, std::exp(mesher_->locations(direction_)[i]));
52 }
53
54 // overwrite discounting term with external curve and / or add external spread
55
56 Real r_dis = r;
57 if (!discountingCurve_.empty()) {
58 r_dis = discountingCurve_->forwardRate(t1, t2, Continuous);
59 }
60 if (!discountingSpread_.empty()) {
61 r_dis += discountingSpread_->value();
62 }
63
64 // additional credit discounting term
65
66 Array h2(n, 0.0);
67 if (!addCreditCurve_.empty()) {
68 QL_REQUIRE(!close_enough(addCreditCurve_->survivalProbability(t1), 0.0),
69 "FdmDefaultableEquityJumpDiffusionOp: addCreditCurve implies zero survival probability at t = "
70 << t1
71 << ", this can not be handled. Check the credit curve / security spread provided in the market "
72 "data. If this happens during a spread imply, the target price might not be ataainable even "
73 "for high spreads.");
74 Real tmp =
75 -std::log(addCreditCurve_->survivalProbability(t2) / addCreditCurve_->survivalProbability(t1)) / (t2 - t1);
76 std::fill(h2.begin(), h2.end(), tmp);
77 }
78
79 Array drift(n, r - q - 0.5 * v);
80 if (model_->adjustEquityForward())
81 drift += model_->eta() * h;
82 mapT_.axpyb(drift, dxMap_, dxxMap_.mult(Array(n, 0.5 * v)), -(Array(n, r_dis) + h + h2));
83
84 for (Size i = 0; i < n; ++i) {
85 Real S = std::exp(mesher_->locations(direction_)[i]);
86 Real cr = conversionRatio_ ? conversionRatio_(S) : Null<Real>();
87 recoveryTerm_[i] = 0.0;
88 if (recovery_) {
89 recoveryTerm_[i] += recovery_(t1, S, cr) * h[i];
90 }
91 if (addRecovery_) {
92 recoveryTerm_[i] += addRecovery_(t1, S, cr) * h2[i];
93 }
94 }
95}
96
97Array FdmDefaultableEquityJumpDiffusionOp::apply(const Array& r) const {
98 return mapT_.apply(r) + recoveryTerm_;
99}
100
102 Array retVal(r.size(), 0.0);
103 return retVal;
104}
105
106Array FdmDefaultableEquityJumpDiffusionOp::apply_direction(Size direction, const Array& r) const {
107 if (direction == direction_)
108 return mapT_.apply(r);
109 else {
110 Array retVal(r.size(), 0.0);
111 return retVal;
112 }
113}
114
115Array FdmDefaultableEquityJumpDiffusionOp::solve_splitting(Size direction, const Array& r, Real s) const {
116 if (direction == direction_) {
117 return mapT_.solve_splitting(r, s, 1.0);
118 } else {
119 Array retVal(r);
120 return retVal;
121 }
122}
123
124Array FdmDefaultableEquityJumpDiffusionOp::preconditioner(const Array& r, Real s) const {
125 return solve_splitting(direction_, r, s);
126}
127
128#if !defined(QL_NO_UBLAS_SUPPORT)
129std::vector<QuantLib::SparseMatrix> FdmDefaultableEquityJumpDiffusionOp::toMatrixDecomp() const {
130 std::vector<SparseMatrix> retVal(1, mapT_.toMatrix());
131 return retVal;
132}
133#endif
134
135void FdmDefaultableEquityJumpDiffusionOp::setConversionRatio(const std::function<Real(Real)>& conversionRatio) {
136 conversionRatio_ = conversionRatio;
137}
138
139} // namespace QuantExt
Handle< QuantLib::DefaultProbabilityTermStructure > addCreditCurve_
Array apply_direction(Size direction, const Array &r) const override
Array preconditioner(const Array &r, Real s) const override
QuantLib::ext::shared_ptr< QuantLib::FdmMesher > mesher_
std::vector< QuantLib::SparseMatrix > toMatrixDecomp() const override
FdmDefaultableEquityJumpDiffusionOp(const QuantLib::ext::shared_ptr< QuantLib::FdmMesher > &mesher, const QuantLib::ext::shared_ptr< DefaultableEquityJumpDiffusionModel > &model, const Size direction=0, const std::function< Real(Real, Real, Real)> &recovery={}, const Handle< QuantLib::YieldTermStructure > &discountingCurve=Handle< QuantLib::YieldTermStructure >(), const Handle< QuantLib::Quote > &discountingSpread=Handle< QuantLib::Quote >(), const Handle< QuantLib::DefaultProbabilityTermStructure > &addCreditCurve=Handle< QuantLib::DefaultProbabilityTermStructure >(), const std::function< Real(Real, Real, Real)> &addRecovery={})
Array solve_splitting(Size direction, const Array &r, Real s) const override
void setConversionRatio(const std::function< Real(Real)> &conversionRatio)
QuantLib::ext::shared_ptr< DefaultableEquityJumpDiffusionModel > model_
Filter close_enough(const RandomVariable &x, const RandomVariable &y)