Coverage Report

Created: 2025-11-04 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/pricingengines/vanilla/analyticeuropeanvasicekengine.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2020 Lew Wei Hao
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/exercise.hpp>
21
#include <ql/math/distributions/normaldistribution.hpp>
22
#include <ql/math/integrals/simpsonintegral.hpp>
23
#include <ql/pricingengines/vanilla/analyticeuropeanvasicekengine.hpp>
24
#include <utility>
25
26
namespace QuantLib {
27
28
    namespace {
29
30
0
        Real g_k(Real t, Real kappa){
31
0
            return (1 - std::exp(- kappa * t )) / kappa;
32
0
        }
33
34
        class integrand_vasicek {
35
          private:
36
            const Real sigma_s_;
37
            const Real sigma_r_;
38
            const Real correlation_;
39
            const Real kappa_;
40
            const Real T_;
41
          public:
42
            integrand_vasicek(Real sigma_s, Real sigma_r, Real correlation, Real kappa, Real T)
43
0
            : sigma_s_(sigma_s), sigma_r_(sigma_r), correlation_(correlation), kappa_(kappa), T_(T){}
44
0
            Real operator()(Real u) const {
45
0
                Real g = g_k(T_ - u, kappa_);
46
0
                return (sigma_s_ * sigma_s_) + (2 * correlation_ * sigma_s_ * sigma_r_ * g) + (sigma_r_ * sigma_r_ * g * g);
47
0
            }
48
        };
49
50
    }
51
52
    AnalyticBlackVasicekEngine::AnalyticBlackVasicekEngine(
53
        ext::shared_ptr<GeneralizedBlackScholesProcess> blackProcess,
54
        ext::shared_ptr<Vasicek> vasicekProcess,
55
        Real correlation)
56
0
    : blackProcess_(std::move(blackProcess)), vasicekProcess_(std::move(vasicekProcess)),
57
0
      simpsonIntegral_(new SimpsonIntegral(1e-5, 1000)), correlation_(correlation) {
58
0
        registerWith(blackProcess_);
59
0
        registerWith(vasicekProcess_);
60
0
    }
61
62
0
    void AnalyticBlackVasicekEngine::calculate() const {
63
0
        QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
64
0
                   "not an European option");
65
66
0
        ext::shared_ptr<StrikedTypePayoff> payoff =
67
0
                ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
68
69
0
        QL_REQUIRE(payoff, "non-striked payoff given");
70
71
0
        CumulativeNormalDistribution f;
72
73
0
        Real t = 0;
74
0
        Real T = blackProcess_->riskFreeRate()->dayCounter().yearFraction(blackProcess_->riskFreeRate().currentLink()->referenceDate(),arguments_.exercise->lastDate());
75
0
        Real kappa = vasicekProcess_->a();
76
0
        Real S_t = blackProcess_->x0();
77
0
        Real K = payoff->strike();
78
0
        Real sigma_s = blackProcess_->blackVolatility()->blackVol(t, K);
79
0
        Real sigma_r = vasicekProcess_->sigma();
80
0
        Real r_t = vasicekProcess_->r0();
81
82
0
        Real zcb = vasicekProcess_->discountBond(t, T, r_t);
83
0
        Real epsilon = payoff->optionType() == Option::Call ? 1 : -1;
84
0
        Real upsilon = (*simpsonIntegral_)(integrand_vasicek(sigma_s, sigma_r, correlation_, kappa, T), t, T);
85
0
        Real d_positive = (std::log((S_t / K) / zcb) + upsilon / 2) / std::sqrt(upsilon);
86
0
        Real d_negative = (std::log((S_t / K) / zcb) - upsilon / 2) / std::sqrt(upsilon);
87
0
        Real n_d1 = f(epsilon * d_positive);
88
0
        Real n_d2 = f(epsilon * d_negative);
89
90
0
        results_.value = epsilon * ((S_t * n_d1) - (zcb * K * n_d2));
91
0
    }
92
93
}
94