/src/quantlib/ql/methods/finitedifferences/operators/fdmbatesop.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2010 Klaus Spanderen |
5 | | |
6 | | This file is part of QuantLib, a free-software/open-source library |
7 | | for financial quantitative analysts and developers - http://quantlib.org/ |
8 | | |
9 | | QuantLib is free software: you can redistribute it and/or modify it |
10 | | under the terms of the QuantLib license. You should have received a |
11 | | copy of the license along with this program; if not, please email |
12 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
13 | | <http://quantlib.org/license.shtml>. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, but WITHOUT |
16 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
17 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
18 | | */ |
19 | | |
20 | | /*! \file fdmbatesop.cpp |
21 | | \brief Bates linear operator |
22 | | */ |
23 | | |
24 | | #include <ql/math/interpolations/linearinterpolation.hpp> |
25 | | #include <ql/math/matrix.hpp> |
26 | | #include <ql/methods/finitedifferences/meshers/fdmmesher.hpp> |
27 | | #include <ql/methods/finitedifferences/operators/fdmbatesop.hpp> |
28 | | #include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp> |
29 | | #include <ql/methods/finitedifferences/utilities/fdmdirichletboundary.hpp> |
30 | | #include <ql/processes/batesprocess.hpp> |
31 | | #include <ql/quotes/simplequote.hpp> |
32 | | #include <ql/termstructures/yield/zerospreadedtermstructure.hpp> |
33 | | #include <utility> |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | FdmBatesOp::FdmBatesOp(const ext::shared_ptr<FdmMesher>& mesher, |
38 | | const ext::shared_ptr<BatesProcess>& batesProcess, |
39 | | FdmBoundaryConditionSet bcSet, |
40 | | const Size integroIntegrationOrder, |
41 | | const ext::shared_ptr<FdmQuantoHelper>& quantoHelper) |
42 | 0 | : lambda_(batesProcess->lambda()), delta_(batesProcess->delta()), nu_(batesProcess->nu()), |
43 | 0 | m_(std::exp(nu_ + 0.5 * delta_ * delta_) - 1.0), |
44 | 0 | gaussHermiteIntegration_(integroIntegrationOrder), mesher_(mesher), bcSet_(std::move(bcSet)), |
45 | 0 | hestonOp_(new FdmHestonOp( |
46 | 0 | mesher, |
47 | 0 | ext::make_shared<HestonProcess>( |
48 | 0 | batesProcess->riskFreeRate(), |
49 | 0 | Handle<YieldTermStructure>(ext::make_shared<ZeroSpreadedTermStructure>( |
50 | 0 | batesProcess->dividendYield(), |
51 | 0 | Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(lambda_ * m_))), |
52 | 0 | Continuous, |
53 | 0 | NoFrequency, |
54 | 0 | batesProcess->dividendYield()->dayCounter())), |
55 | 0 | batesProcess->s0(), |
56 | 0 | batesProcess->v0(), |
57 | 0 | batesProcess->kappa(), |
58 | 0 | batesProcess->theta(), |
59 | 0 | batesProcess->sigma(), |
60 | 0 | batesProcess->rho()), |
61 | 0 | quantoHelper)) {} |
62 | | |
63 | | FdmBatesOp::IntegroIntegrand::IntegroIntegrand( |
64 | | const ext::shared_ptr<LinearInterpolation>& interpl, |
65 | | const FdmBoundaryConditionSet& bcSet, |
66 | | Real x, Real delta, Real nu) |
67 | 0 | : x_(x), delta_(delta), nu_(nu), |
68 | 0 | bcSet_(bcSet), interpl_(interpl) { } |
69 | | |
70 | 0 | Real FdmBatesOp::IntegroIntegrand::operator()(Real y) const { |
71 | 0 | const Real x = x_ + M_SQRT2*delta_*y + nu_; |
72 | 0 | Real valueOfDerivative = (*interpl_)(x, true); |
73 | |
|
74 | 0 | for (auto iter = bcSet_.begin(); iter < bcSet_.end(); ++iter) { |
75 | |
|
76 | 0 | const ext::shared_ptr<FdmDirichletBoundary> dirichlet |
77 | 0 | = ext::dynamic_pointer_cast<FdmDirichletBoundary>(*iter); |
78 | |
|
79 | 0 | QL_REQUIRE(dirichlet, "FdmBatesOp can only deal with Dirichlet " |
80 | 0 | "boundary conditions."); |
81 | | |
82 | 0 | valueOfDerivative |
83 | 0 | = dirichlet->applyAfterApplying(x, valueOfDerivative); |
84 | 0 | } |
85 | | |
86 | 0 | return std::exp(-y*y)*valueOfDerivative; |
87 | 0 | } |
88 | | |
89 | 0 | Array FdmBatesOp::integro(const Array& r) const { |
90 | 0 | QL_REQUIRE(mesher_->layout()->dim().size() == 2, "invalid layout dimension"); |
91 | | |
92 | 0 | Array x(mesher_->layout()->dim()[0]); |
93 | 0 | Matrix f(mesher_->layout()->dim()[1], mesher_->layout()->dim()[0]); |
94 | | |
95 | 0 | for (const auto& iter : *mesher_->layout()) { |
96 | 0 | const Size i = iter.coordinates()[0]; |
97 | 0 | const Size j = iter.coordinates()[1]; |
98 | | |
99 | 0 | x[i] = mesher_->location(iter, 0); |
100 | 0 | f[j][i] = r[iter.index()]; |
101 | | |
102 | 0 | } |
103 | 0 | std::vector<ext::shared_ptr<LinearInterpolation> > interpl(f.rows()); |
104 | 0 | for (Size i=0; i < f.rows(); ++i) { |
105 | 0 | interpl[i] = ext::make_shared<LinearInterpolation>( |
106 | 0 | x.begin(), x.end(), f.row_begin(i)); |
107 | 0 | } |
108 | | |
109 | 0 | Array integral(r.size()); |
110 | 0 | for (const auto& iter : *mesher_->layout()) { |
111 | 0 | const Size i = iter.coordinates()[0]; |
112 | 0 | const Size j = iter.coordinates()[1]; |
113 | |
|
114 | 0 | integral[iter.index()] = M_1_SQRTPI* |
115 | 0 | gaussHermiteIntegration_( |
116 | 0 | IntegroIntegrand(interpl[j], bcSet_, x[i], delta_, nu_)); |
117 | 0 | } |
118 | |
|
119 | 0 | return lambda_*(integral-r); |
120 | 0 | } |
121 | | |
122 | 0 | std::vector<SparseMatrix> FdmBatesOp::toMatrixDecomp() const { |
123 | 0 | QL_FAIL("not implemented"); |
124 | 0 | } |
125 | | |
126 | | } |