Coverage Report

Created: 2026-09-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/processes/extendedornsteinuhlenbeckprocess.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
#include <ql/experimental/processes/extendedornsteinuhlenbeckprocess.hpp>
21
#include <ql/math/integrals/gausslobattointegral.hpp>
22
#include <ql/processes/ornsteinuhlenbeckprocess.hpp>
23
#include <utility>
24
25
namespace QuantLib {
26
27
    namespace {
28
29
        class integrand {
30
            std::function<Real (Real)> b;
31
            Real speed;
32
          public:
33
0
            integrand(std::function<Real(Real)> b, Real speed) : b(std::move(b)), speed(speed) {}
34
0
            Real operator()(Real x) const {
35
0
                return b(x) * std::exp(speed*x);
36
0
            }
37
        };
38
39
    }
40
41
    ExtendedOrnsteinUhlenbeckProcess::ExtendedOrnsteinUhlenbeckProcess(
42
        Real speed,
43
        Volatility vol,
44
        Real x0,
45
        std::function<Real(Real)> b,
46
        Discretization discretization,
47
        Real intEps)
48
0
    : speed_(speed), vol_(vol), b_(std::move(b)), intEps_(intEps),
49
0
      ouProcess_(new OrnsteinUhlenbeckProcess(speed, vol, x0)), discretization_(discretization) {
50
0
        QL_REQUIRE(speed_ >= 0.0, "negative a given");
51
0
        QL_REQUIRE(vol_ >= 0.0, "negative volatility given");
52
0
    }
53
54
0
    Real ExtendedOrnsteinUhlenbeckProcess::x0() const {
55
0
        return ouProcess_->x0();
56
0
    }
57
    
58
0
    Real ExtendedOrnsteinUhlenbeckProcess::drift(Time t, Real x) const {
59
0
        return ouProcess_->drift(t, x) + speed_*b_(t);
60
0
    }
61
62
0
    Real ExtendedOrnsteinUhlenbeckProcess::diffusion(Time t, Real x) const{
63
0
        return ouProcess_->diffusion(t, x);
64
0
    }
65
66
    Real ExtendedOrnsteinUhlenbeckProcess::stdDeviation(
67
0
                                           Time t0, Real x0, Time dt) const{
68
0
        return ouProcess_->stdDeviation(t0, x0, dt);
69
0
    }
70
71
    Real ExtendedOrnsteinUhlenbeckProcess::variance(
72
0
                                           Time t0, Real x0, Time dt) const{
73
0
        return ouProcess_->variance(t0, x0, dt);
74
0
    }
75
76
0
    Real ExtendedOrnsteinUhlenbeckProcess::speed() const {
77
0
        return speed_;
78
0
    }
79
80
0
    Real ExtendedOrnsteinUhlenbeckProcess::volatility() const {
81
0
        return vol_;
82
0
    }
83
84
    Real ExtendedOrnsteinUhlenbeckProcess::expectation(
85
0
                                          Time t0, Real x0, Time dt) const {
86
0
        switch (discretization_) {
87
0
          case MidPoint:
88
0
            return ouProcess_->expectation(t0, x0, dt)
89
0
                    + b_(t0+0.5*dt)*(1.0 - std::exp(-speed_*dt));
90
0
          case Trapezodial:
91
0
            {
92
0
              const Time t = t0+dt;
93
0
              const Time u = t0;
94
0
              const Real bt = b_(t);
95
0
              const Real bu = b_(u);
96
0
              const Real ex = std::exp(-speed_*dt);
97
98
0
              return ouProcess_->expectation(t0, x0, dt)
99
0
                    + bt-ex*bu - (bt-bu)/(speed_*dt)*(1-ex);
100
0
            }
101
0
          case GaussLobatto:
102
0
              return ouProcess_->expectation(t0, x0, dt)
103
0
                  + speed_*std::exp(-speed_*(t0+dt))
104
0
                  * GaussLobattoIntegral(100000, intEps_)(integrand(b_, speed_),
105
0
                                                          t0, t0+dt);
106
0
          default:
107
            QL_FAIL("unknown discretization scheme");
108
0
        }
109
0
    }
110
}
111