Coverage Report

Created: 2026-09-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/pricingengines/barrier/fdhestondoublebarrierengine.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2016 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/methods/finitedifferences/meshers/fdmblackscholesmesher.hpp>
21
#include <ql/methods/finitedifferences/meshers/fdmhestonvariancemesher.hpp>
22
#include <ql/methods/finitedifferences/meshers/fdmmeshercomposite.hpp>
23
#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
24
#include <ql/methods/finitedifferences/stepconditions/fdmstepconditioncomposite.hpp>
25
#include <ql/methods/finitedifferences/utilities/fdmdirichletboundary.hpp>
26
#include <ql/methods/finitedifferences/utilities/fdmdividendhandler.hpp>
27
#include <ql/methods/finitedifferences/utilities/fdminnervaluecalculator.hpp>
28
#include <ql/pricingengines/barrier/fdhestonrebateengine.hpp>
29
#include <ql/pricingengines/barrier/fdhestondoublebarrierengine.hpp>
30
#include <ql/pricingengines/vanilla/fdhestonvanillaengine.hpp>
31
#include <utility>
32
33
namespace QuantLib {
34
35
    FdHestonDoubleBarrierEngine::FdHestonDoubleBarrierEngine(
36
        const ext::shared_ptr<HestonModel>& model,
37
        Size tGrid,
38
        Size xGrid,
39
        Size vGrid,
40
        Size dampingSteps,
41
        const FdmSchemeDesc& schemeDesc,
42
        ext::shared_ptr<LocalVolTermStructure> leverageFct,
43
        const Real mixingFactor)
44
0
    : GenericModelEngine<HestonModel, DoubleBarrierOption::arguments, DoubleBarrierOption::results>(
45
0
          model),
46
0
      tGrid_(tGrid), xGrid_(xGrid), vGrid_(vGrid), dampingSteps_(dampingSteps),
47
0
      schemeDesc_(schemeDesc), leverageFct_(std::move(leverageFct)), mixingFactor_(mixingFactor) {}
48
49
0
    void FdHestonDoubleBarrierEngine::calculate() const {
50
51
0
        QL_REQUIRE(arguments_.barrierType == DoubleBarrier::KnockOut,
52
0
                "only Knock-Out double barrier options are supported");
53
54
        // 1. Mesher
55
0
        const ext::shared_ptr<HestonProcess>& process = model_->process();
56
0
        const Time maturity = process->time(arguments_.exercise->lastDate());
57
58
        // 1.1 The variance mesher
59
0
        const Size tGridMin = 5;
60
0
        const Size tGridAvgSteps = std::max(tGridMin, tGrid_/50);
61
62
0
        const auto vMesher = ext::make_shared<FdmHestonLocalVolatilityVarianceMesher>(
63
0
                  vGrid_, process, leverageFct_, maturity, tGridAvgSteps, 0.0001, mixingFactor_);
64
65
        // 1.2 The equity mesher
66
0
        const ext::shared_ptr<StrikedTypePayoff> payoff =
67
0
            ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
68
69
0
        Real xMin = std::log(arguments_.barrier_lo);
70
0
        Real xMax = std::log(arguments_.barrier_hi);
71
72
0
        const auto equityMesher = ext::make_shared<FdmBlackScholesMesher>(
73
0
                xGrid_,
74
0
                FdmBlackScholesMesher::processHelper(
75
0
                    process->s0(), process->dividendYield(),
76
0
                    process->riskFreeRate(), vMesher->volaEstimate()),
77
0
                maturity, payoff->strike(), xMin, xMax);
78
79
0
        const auto mesher = ext::make_shared<FdmMesherComposite>(equityMesher, vMesher);
80
81
        // 2. Calculator
82
0
        const auto calculator = ext::make_shared<FdmLogInnerValue>(payoff, mesher, 0);
83
84
        // 3. Step conditions
85
0
        std::list<ext::shared_ptr<StepCondition<Array> > > stepConditions;
86
0
        std::list<std::vector<Time> > stoppingTimes;
87
88
0
        QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
89
0
                   "only european style option are supported");
90
91
0
        auto conditions = ext::make_shared<FdmStepConditionComposite>(stoppingTimes, stepConditions);
92
93
        // 4. Boundary conditions
94
0
        FdmBoundaryConditionSet boundaries;
95
0
        boundaries.push_back(ext::make_shared<FdmDirichletBoundary>(
96
0
            mesher, arguments_.rebate, 0, FdmDirichletBoundary::Lower));
97
98
0
        boundaries.push_back(ext::make_shared<FdmDirichletBoundary>(
99
0
            mesher, arguments_.rebate, 0, FdmDirichletBoundary::Upper));
100
101
        // 5. Solver
102
0
        FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
103
0
                                     calculator, maturity,
104
0
                                     tGrid_, dampingSteps_ };
105
106
0
        auto solver = ext::make_shared<FdmHestonSolver>(
107
0
                    Handle<HestonProcess>(process), solverDesc, schemeDesc_,
108
0
                    Handle<FdmQuantoHelper>(), leverageFct_, mixingFactor_);
109
110
0
        const Real spot = process->s0()->value();
111
0
        results_.value = solver->valueAt(spot, process->v0());
112
0
        results_.delta = solver->deltaAt(spot, process->v0());
113
0
        results_.gamma = solver->gammaAt(spot, process->v0());
114
0
        results_.theta = solver->thetaAt(spot, process->v0());
115
0
    }
116
}