Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/methods/finitedifferences/utilities/fdmhestongreensfct.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) 2014 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 fdmhestongreenfct.cpp
21
    \brief Heston Fokker-Planck Green's function
22
*/
23
24
#include <ql/math/functional.hpp>
25
#include <ql/methods/finitedifferences/meshers/fdmmesher.hpp>
26
#include <ql/methods/finitedifferences/operators/fdmlinearopiterator.hpp>
27
#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
28
#include <ql/methods/finitedifferences/utilities/fdmhestongreensfct.hpp>
29
#include <ql/methods/finitedifferences/utilities/squarerootprocessrndcalculator.hpp>
30
#include <ql/processes/hestonprocess.hpp>
31
#include <utility>
32
33
namespace QuantLib {
34
35
    FdmHestonGreensFct::FdmHestonGreensFct(ext::shared_ptr<FdmMesher> mesher,
36
                                           ext::shared_ptr<HestonProcess> process,
37
                                           FdmSquareRootFwdOp::TransformationType trafoType_,
38
                                           const Real l0)
39
0
    : l0_(l0), mesher_(std::move(mesher)), process_(std::move(process)), trafoType_(trafoType_) {}
40
41
0
    Array FdmHestonGreensFct::get(Time t, Algorithm algorithm) const {
42
43
0
        const Rate r = process_->riskFreeRate()->forwardRate(0, t, Continuous);
44
0
        const Rate q = process_->dividendYield()->forwardRate(0,t, Continuous);
45
46
0
        const Real s0    = process_->s0()->value();
47
0
        const Real v0    = process_->v0();
48
0
        const Real x0    = std::log(s0) + (r-q-0.5*v0*l0_*l0_)*t;
49
50
0
          const Real rho   = process_->rho();
51
0
        const Real theta = process_->theta();
52
0
        const Real kappa = process_->kappa();
53
0
        const Real sigma = process_->sigma();
54
55
0
        Array p(mesher_->layout()->size());
56
0
        for (const auto& iter : *mesher_->layout()) {
57
0
            const Real x = mesher_->location(iter, 0);
58
0
            const Real v = (trafoType_ != FdmSquareRootFwdOp::Log)
59
0
                ? mesher_->location(iter, 1)
60
0
                : std::exp(mesher_->location(iter, 1));
61
62
0
            Real retVal;
63
0
            switch (algorithm) {
64
0
              case ZeroCorrelation:
65
0
              {
66
0
                const Real sd_x = l0_*std::sqrt(v0*t);
67
0
                  const Real p_x = M_1_SQRTPI*M_SQRT1_2/sd_x
68
0
                          * std::exp(-0.5*squared((x - x0)/sd_x));
69
0
                  const Real p_v = SquareRootProcessRNDCalculator(
70
0
                      v0, kappa, theta, sigma).pdf(v, t);
71
72
0
                  retVal = p_v*p_x;
73
0
              }
74
0
              break;
75
0
              case SemiAnalytical:
76
0
                retVal = process_->pdf(x, v, t, 1e-4);
77
0
              break;
78
0
              case Gaussian:
79
0
              {
80
0
                const Real sd_x = l0_*std::sqrt(v0*t);
81
0
                const Real sd_v = sigma*std::sqrt(v0*t);
82
0
                const Real z0 = v0 + kappa*(theta - v0)*t;
83
0
                retVal = 1.0/(M_TWOPI*sd_x*sd_v*std::sqrt(1-rho*rho))
84
0
                    *std::exp(-(  squared((x-x0)/sd_x)
85
0
                                + squared((v-z0)/sd_v)
86
0
                                - 2*rho*(x-x0)*(v-z0)/(sd_x*sd_v))
87
0
                              /(2*(1-rho*rho)) );
88
0
              }
89
0
              break;
90
0
              default:
91
0
                QL_FAIL("unknown algorithm");
92
0
            }
93
94
0
            switch (trafoType_) {
95
0
              case FdmSquareRootFwdOp::Log:
96
0
                retVal*=v;
97
0
                break;
98
0
              case FdmSquareRootFwdOp::Plain:
99
0
                break;
100
0
              case FdmSquareRootFwdOp::Power:
101
0
                retVal*=std::pow(v, 1.0 - 2*kappa*theta/(sigma*sigma));
102
0
                break;
103
0
              default:
104
0
                QL_FAIL("unknown transformation type");
105
0
            }
106
107
0
            p[iter.index()] = retVal;
108
0
        }
109
110
0
        return p;
111
0
    }
112
}