Coverage Report

Created: 2025-10-14 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/pricingengines/vanilla/fdcirvanillaengine.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
21
#include <ql/methods/finitedifferences/meshers/fdmblackscholesmesher.hpp>
22
#include <ql/methods/finitedifferences/meshers/fdmmeshercomposite.hpp>
23
#include <ql/methods/finitedifferences/meshers/fdmsimpleprocess1dmesher.hpp>
24
#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
25
#include <ql/methods/finitedifferences/solvers/fdmcirsolver.hpp>
26
#include <ql/methods/finitedifferences/stepconditions/fdmstepconditioncomposite.hpp>
27
#include <ql/methods/finitedifferences/utilities/fdminnervaluecalculator.hpp>
28
#include <ql/pricingengines/vanilla/fdcirvanillaengine.hpp>
29
#include <ql/processes/blackscholesprocess.hpp>
30
#include <ql/processes/coxingersollrossprocess.hpp>
31
#include <utility>
32
33
namespace QuantLib {
34
35
    FdCIRVanillaEngine::FdCIRVanillaEngine(
36
        ext::shared_ptr<CoxIngersollRossProcess> cirProcess,
37
        ext::shared_ptr<GeneralizedBlackScholesProcess> bsProcess,
38
        Size tGrid,
39
        Size xGrid,
40
        Size rGrid,
41
        Size dampingSteps,
42
        const Real rho,
43
        const FdmSchemeDesc& schemeDesc,
44
        ext::shared_ptr<FdmQuantoHelper> quantoHelper)
45
0
    :  bsProcess_(std::move(bsProcess)), cirProcess_(std::move(cirProcess)),
46
0
       quantoHelper_(std::move(quantoHelper)),
47
0
       tGrid_(tGrid), xGrid_(xGrid), rGrid_(rGrid), dampingSteps_(dampingSteps),
48
0
       rho_(rho), schemeDesc_(schemeDesc) {}
49
50
    FdCIRVanillaEngine::FdCIRVanillaEngine(
51
        ext::shared_ptr<CoxIngersollRossProcess> cirProcess,
52
        ext::shared_ptr<GeneralizedBlackScholesProcess> bsProcess,
53
        DividendSchedule dividends,
54
        Size tGrid,
55
        Size xGrid,
56
        Size rGrid,
57
        Size dampingSteps,
58
        const Real rho,
59
        const FdmSchemeDesc& schemeDesc,
60
        ext::shared_ptr<FdmQuantoHelper> quantoHelper)
61
0
    : bsProcess_(std::move(bsProcess)), cirProcess_(std::move(cirProcess)),
62
0
      quantoHelper_(std::move(quantoHelper)), dividends_(std::move(dividends)),
63
0
      tGrid_(tGrid), xGrid_(xGrid), rGrid_(rGrid), dampingSteps_(dampingSteps), rho_(rho),
64
0
      schemeDesc_(schemeDesc) {}
65
66
0
    FdmSolverDesc FdCIRVanillaEngine::getSolverDesc(Real) const {
67
68
0
        const ext::shared_ptr<StrikedTypePayoff> payoff =
69
0
            ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
70
0
        const Time maturity = bsProcess_->time(arguments_.exercise->lastDate());
71
72
        // The short rate mesher
73
0
        const ext::shared_ptr<Fdm1dMesher> shortRateMesher(
74
0
            new FdmSimpleProcess1dMesher(rGrid_, cirProcess_, maturity, tGrid_));
75
76
        // The equity mesher
77
0
        const ext::shared_ptr<Fdm1dMesher> equityMesher(
78
0
            new FdmBlackScholesMesher(
79
0
                xGrid_, bsProcess_, maturity, payoff->strike(),
80
0
                Null<Real>(), Null<Real>(), 0.0001, 1.5,
81
0
                std::pair<Real, Real>(payoff->strike(), 0.1),
82
0
                dividends_, quantoHelper_,
83
0
                0.0));
84
        
85
0
        const ext::shared_ptr<FdmMesher> mesher(
86
0
            new FdmMesherComposite(equityMesher, shortRateMesher));
87
88
        // Calculator
89
0
        const ext::shared_ptr<FdmInnerValueCalculator> calculator(
90
0
                          new FdmLogInnerValue(arguments_.payoff, mesher, 0));
91
92
        // Step conditions
93
0
        const ext::shared_ptr<FdmStepConditionComposite> conditions = 
94
0
             FdmStepConditionComposite::vanillaComposite(
95
0
                                 dividends_, arguments_.exercise, 
96
0
                                 mesher, calculator,
97
0
                                 bsProcess_->riskFreeRate()->referenceDate(),
98
0
                                 bsProcess_->riskFreeRate()->dayCounter());
99
100
        // Boundary conditions
101
0
        const FdmBoundaryConditionSet boundaries;
102
103
        // Solver
104
0
        FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
105
0
                                     calculator, maturity,
106
0
                                     tGrid_, dampingSteps_ };
107
108
0
        return solverDesc;
109
0
    }
110
111
0
    void FdCIRVanillaEngine::calculate() const {
112
0
        const ext::shared_ptr<StrikedTypePayoff> payoff =
113
0
            ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
114
115
0
        ext::shared_ptr<FdmCIRSolver> solver(new FdmCIRSolver(
116
0
                    Handle<CoxIngersollRossProcess>(cirProcess_),
117
0
                    Handle<GeneralizedBlackScholesProcess>(bsProcess_),
118
0
                    getSolverDesc(1.5), schemeDesc_,
119
0
                    rho_, payoff->strike()));
120
121
0
        const Real r0   = cirProcess_->x0();
122
0
        const Real spot = bsProcess_->x0();
123
124
0
        results_.value = solver->valueAt(spot, r0);
125
0
        results_.delta = solver->deltaAt(spot, r0);
126
0
        results_.gamma = solver->gammaAt(spot, r0);
127
0
        results_.theta = solver->thetaAt(spot, r0);
128
0
    }
129
130
    MakeFdCIRVanillaEngine::MakeFdCIRVanillaEngine(
131
        ext::shared_ptr<CoxIngersollRossProcess> cirProcess,
132
        ext::shared_ptr<GeneralizedBlackScholesProcess> bsProcess,
133
        const Real rho)
134
0
    : cirProcess_(std::move(cirProcess)), bsProcess_(std::move(bsProcess)), rho_(rho),
135
0
      schemeDesc_(ext::make_shared<FdmSchemeDesc>(FdmSchemeDesc::ModifiedHundsdorfer())) {}
136
137
    MakeFdCIRVanillaEngine& MakeFdCIRVanillaEngine::withQuantoHelper(
138
0
        const ext::shared_ptr<FdmQuantoHelper>& quantoHelper) {
139
0
        quantoHelper_ = quantoHelper;
140
0
        return *this;
141
0
    }
142
143
    MakeFdCIRVanillaEngine&
144
0
    MakeFdCIRVanillaEngine::withTGrid(Size tGrid) {
145
0
        tGrid_ = tGrid;
146
0
        return *this;
147
0
    }
148
149
    MakeFdCIRVanillaEngine&
150
0
    MakeFdCIRVanillaEngine::withXGrid(Size xGrid) {
151
0
        xGrid_ = xGrid;
152
0
        return *this;
153
0
    }
154
155
    MakeFdCIRVanillaEngine&
156
0
    MakeFdCIRVanillaEngine::withRGrid(Size rGrid) {
157
0
        rGrid_ = rGrid;
158
0
        return *this;
159
0
    }
160
161
    MakeFdCIRVanillaEngine&
162
0
    MakeFdCIRVanillaEngine::withDampingSteps(Size dampingSteps) {
163
0
        dampingSteps_ = dampingSteps;
164
0
        return *this;
165
0
    }
166
167
    MakeFdCIRVanillaEngine&
168
    MakeFdCIRVanillaEngine::withFdmSchemeDesc(
169
0
        const FdmSchemeDesc& schemeDesc) {
170
0
        schemeDesc_ = ext::make_shared<FdmSchemeDesc>(schemeDesc);
171
0
        return *this;
172
0
    }
173
174
    MakeFdCIRVanillaEngine&
175
    MakeFdCIRVanillaEngine::withCashDividends(
176
            const std::vector<Date>& dividendDates,
177
0
            const std::vector<Real>& dividendAmounts) {
178
0
        dividends_ = DividendVector(dividendDates, dividendAmounts);
179
0
        return *this;
180
0
    }
181
182
    MakeFdCIRVanillaEngine::operator
183
0
    ext::shared_ptr<PricingEngine>() const {
184
0
        return ext::make_shared<FdCIRVanillaEngine>(
185
0
                cirProcess_,
186
0
                bsProcess_,
187
0
                dividends_,
188
0
                tGrid_, xGrid_, rGrid_, dampingSteps_,
189
0
                rho_,
190
0
                *schemeDesc_,
191
0
                quantoHelper_);
192
0
    }
193
194
}