Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/methods/finitedifferences/operators/fdmbatesop.cpp
Line
Count
Source
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
 <https://www.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
              batesProcess->s0(),
54
0
              batesProcess->v0(),
55
0
              batesProcess->kappa(),
56
0
              batesProcess->theta(),
57
0
              batesProcess->sigma(),
58
0
              batesProcess->rho()),
59
0
          quantoHelper)) {}
60
61
    FdmBatesOp::IntegroIntegrand::IntegroIntegrand(
62
                    const ext::shared_ptr<LinearInterpolation>& interpl,
63
                    const FdmBoundaryConditionSet& bcSet,
64
                    Real x, Real delta, Real nu)
65
0
    : x_(x), delta_(delta), nu_(nu), 
66
0
      bcSet_(bcSet), interpl_(interpl) { }
67
                    
68
0
    Real FdmBatesOp::IntegroIntegrand::operator()(Real y) const {
69
0
        const Real x = x_ + M_SQRT2*delta_*y + nu_;
70
0
        Real valueOfDerivative = (*interpl_)(x, true);
71
72
0
        for (auto iter = bcSet_.begin(); iter < bcSet_.end(); ++iter) {
73
74
0
            const ext::shared_ptr<FdmDirichletBoundary> dirichlet
75
0
                = ext::dynamic_pointer_cast<FdmDirichletBoundary>(*iter);
76
77
0
            QL_REQUIRE(dirichlet, "FdmBatesOp can only deal with Dirichlet "
78
0
                                  "boundary conditions.");
79
80
0
            valueOfDerivative
81
0
                = dirichlet->applyAfterApplying(x, valueOfDerivative);
82
0
        }
83
84
0
        return std::exp(-y*y)*valueOfDerivative;
85
0
    }
86
    
87
0
    Array FdmBatesOp::integro(const Array& r) const {
88
0
        QL_REQUIRE(mesher_->layout()->dim().size() == 2, "invalid layout dimension");
89
90
0
        Array x(mesher_->layout()->dim()[0]);
91
0
        Matrix f(mesher_->layout()->dim()[1], mesher_->layout()->dim()[0]);
92
        
93
0
        for (const auto& iter : *mesher_->layout()) {
94
0
            const Size i = iter.coordinates()[0];
95
0
            const Size j = iter.coordinates()[1];
96
            
97
0
            x[i]    = mesher_->location(iter, 0);
98
0
            f[j][i] = r[iter.index()];
99
            
100
0
        }
101
0
        std::vector<ext::shared_ptr<LinearInterpolation> > interpl(f.rows());
102
0
        for (Size i=0; i < f.rows(); ++i) {
103
0
            interpl[i] = ext::make_shared<LinearInterpolation>(
104
0
                x.begin(), x.end(), f.row_begin(i));
105
0
        }
106
        
107
0
        Array integral(r.size());
108
0
        for (const auto& iter : *mesher_->layout()) {
109
0
            const Size i = iter.coordinates()[0];
110
0
            const Size j = iter.coordinates()[1];
111
112
0
            integral[iter.index()] = M_1_SQRTPI* 
113
0
                gaussHermiteIntegration_(
114
0
                      IntegroIntegrand(interpl[j], bcSet_, x[i], delta_, nu_));
115
0
        }
116
117
0
        return lambda_*(integral-r);
118
0
    }
119
120
0
    std::vector<SparseMatrix> FdmBatesOp::toMatrixDecomp() const {
121
        QL_FAIL("not implemented");
122
0
    }
123
124
}