Coverage Report

Created: 2025-10-14 06:32

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 ext::shared_ptr<FdmHestonLocalVolatilityVarianceMesher> vMesher
63
0
            = ext::make_shared<FdmHestonLocalVolatilityVarianceMesher>(
64
0
                  vGrid_, process, leverageFct_, maturity, tGridAvgSteps, 0.0001, mixingFactor_);
65
66
        // 1.2 The equity mesher
67
0
        const ext::shared_ptr<StrikedTypePayoff> payoff =
68
0
            ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
69
70
0
        Real xMin = std::log(arguments_.barrier_lo);
71
0
        Real xMax = std::log(arguments_.barrier_hi);
72
73
0
        const ext::shared_ptr<Fdm1dMesher> equityMesher(
74
0
            new FdmBlackScholesMesher(
75
0
                xGrid_,
76
0
                FdmBlackScholesMesher::processHelper(
77
0
                    process->s0(), process->dividendYield(),
78
0
                    process->riskFreeRate(), vMesher->volaEstimate()),
79
0
                maturity, payoff->strike(), xMin, xMax));
80
81
0
        const ext::shared_ptr<FdmMesher> mesher (
82
0
            new FdmMesherComposite(equityMesher, vMesher));
83
84
        // 2. Calculator
85
0
        const ext::shared_ptr<FdmInnerValueCalculator> calculator(
86
0
                                new FdmLogInnerValue(payoff, mesher, 0));
87
88
        // 3. Step conditions
89
0
        std::list<ext::shared_ptr<StepCondition<Array> > > stepConditions;
90
0
        std::list<std::vector<Time> > stoppingTimes;
91
92
0
        QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
93
0
                   "only european style option are supported");
94
95
0
        ext::shared_ptr<FdmStepConditionComposite> conditions(
96
0
                new FdmStepConditionComposite(stoppingTimes, stepConditions));
97
98
        // 4. Boundary conditions
99
0
        FdmBoundaryConditionSet boundaries;
100
0
        boundaries.push_back(FdmBoundaryConditionSet::value_type(
101
0
            new FdmDirichletBoundary(mesher, arguments_.rebate, 0,
102
0
                                     FdmDirichletBoundary::Lower)));
103
104
0
        boundaries.push_back(FdmBoundaryConditionSet::value_type(
105
0
            new FdmDirichletBoundary(mesher, arguments_.rebate, 0,
106
0
                                     FdmDirichletBoundary::Upper)));
107
108
        // 5. Solver
109
0
        FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
110
0
                                     calculator, maturity,
111
0
                                     tGrid_, dampingSteps_ };
112
113
0
        ext::shared_ptr<FdmHestonSolver> solver(new FdmHestonSolver(
114
0
                    Handle<HestonProcess>(process), solverDesc, schemeDesc_,
115
0
                    Handle<FdmQuantoHelper>(), leverageFct_, mixingFactor_));
116
117
0
        const Real spot = process->s0()->value();
118
0
        results_.value = solver->valueAt(spot, process->v0());
119
0
        results_.delta = solver->deltaAt(spot, process->v0());
120
0
        results_.gamma = solver->gammaAt(spot, process->v0());
121
0
        results_.theta = solver->thetaAt(spot, process->v0());
122
0
    }
123
}