Coverage Report

Created: 2025-09-04 07:11

/src/quantlib/ql/pricingengines/vanilla/fdblackscholesshoutengine.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2021 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
/*! \file fdblackscholesshoutengine.cpp
21
*/
22
23
#include <ql/exercise.hpp>
24
#include <ql/methods/finitedifferences/utilities/escroweddividendadjustment.hpp>
25
#include <ql/methods/finitedifferences/meshers/fdmblackscholesmesher.hpp>
26
#include <ql/methods/finitedifferences/meshers/fdmmeshercomposite.hpp>
27
#include <ql/methods/finitedifferences/solvers/fdmblackscholessolver.hpp>
28
#include <ql/methods/finitedifferences/stepconditions/fdmstepconditioncomposite.hpp>
29
#include <ql/methods/finitedifferences/utilities/fdmshoutloginnervaluecalculator.hpp>
30
#include <ql/pricingengines/vanilla/fdblackscholesshoutengine.hpp>
31
#include <ql/processes/blackscholesprocess.hpp>
32
33
namespace QuantLib {
34
35
    FdBlackScholesShoutEngine::FdBlackScholesShoutEngine(
36
        ext::shared_ptr<GeneralizedBlackScholesProcess> process,
37
        Size tGrid,
38
        Size xGrid,
39
        Size dampingSteps,
40
        const FdmSchemeDesc& schemeDesc)
41
0
    : process_(std::move(process)),
42
0
      tGrid_(tGrid), xGrid_(xGrid), dampingSteps_(dampingSteps),
43
0
      schemeDesc_(schemeDesc) {
44
0
        registerWith(process_);
45
0
    }
46
47
    FdBlackScholesShoutEngine::FdBlackScholesShoutEngine(
48
        ext::shared_ptr<GeneralizedBlackScholesProcess> process,
49
        DividendSchedule dividends,
50
        Size tGrid,
51
        Size xGrid,
52
        Size dampingSteps,
53
        const FdmSchemeDesc& schemeDesc)
54
0
    : process_(std::move(process)), dividends_(std::move(dividends)),
55
0
      tGrid_(tGrid), xGrid_(xGrid), dampingSteps_(dampingSteps),
56
0
      schemeDesc_(schemeDesc) {
57
0
        registerWith(process_);
58
0
    }
59
60
0
    void FdBlackScholesShoutEngine::calculate() const {
61
62
0
        const Date exerciseDate = arguments_.exercise->lastDate();
63
0
        const Time maturity = process_->time(exerciseDate);
64
0
        const Date settlementDate = process_->riskFreeRate()->referenceDate();
65
66
0
        const auto escrowedDividendAdj =
67
0
            ext::make_shared<EscrowedDividendAdjustment>(
68
0
                dividends_,
69
0
                process_->riskFreeRate(),
70
0
                process_->dividendYield(),
71
0
                [&](Date d){ return process_->time(d); },
72
0
                maturity);
73
74
0
        const Real divAdj = escrowedDividendAdj
75
0
            ->dividendAdjustment(process_->time(settlementDate));
76
77
0
        QL_REQUIRE(process_->x0() + divAdj > 0.0,
78
0
                            "spot minus dividends becomes negative");
79
80
0
        const auto payoff =
81
0
            ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
82
83
0
        QL_REQUIRE(payoff, "non plain vanilla payoff given");
84
85
0
        const DividendSchedule emptyDividendSchedule;
86
87
0
        const auto mesher = ext::make_shared<FdmMesherComposite>(
88
0
            ext::make_shared<FdmBlackScholesMesher>(
89
0
                xGrid_, process_, maturity, payoff->strike(),
90
0
                Null<Real>(), Null<Real>(), 0.0001, 1.5,
91
0
                std::pair<Real, Real>(payoff->strike(), 0.1),
92
0
                emptyDividendSchedule,
93
0
                ext::shared_ptr<FdmQuantoHelper>(),
94
0
                divAdj));
95
96
0
        const auto innerValuecalculator =
97
0
            ext::make_shared<FdmShoutLogInnerValueCalculator>(
98
0
                process_->blackVolatility(),
99
0
                escrowedDividendAdj, maturity, payoff, mesher, 0);
100
101
0
        DividendSchedule zeroDividendSchedule = DividendSchedule();
102
0
        for (const auto& cf: dividends_)
103
0
            zeroDividendSchedule.push_back(
104
0
                ext::make_shared<FixedDividend>(0.0, cf->date()));
105
106
0
        const auto conditions =
107
0
            FdmStepConditionComposite::vanillaComposite(
108
0
                zeroDividendSchedule,
109
0
                arguments_.exercise, mesher,
110
0
                innerValuecalculator,
111
0
                process_->riskFreeRate()->referenceDate(),
112
0
                process_->riskFreeRate()->dayCounter());
113
114
0
        const FdmSolverDesc solverDesc = {
115
0
            mesher, FdmBoundaryConditionSet(),
116
0
            conditions, innerValuecalculator,
117
0
            maturity, tGrid_, dampingSteps_ };
118
119
0
        const auto solver =
120
0
            ext::make_shared<FdmBlackScholesSolver>(
121
0
                Handle<GeneralizedBlackScholesProcess>(process_),
122
0
                payoff->strike(), solverDesc, schemeDesc_);
123
124
0
        const Real spot = process_->x0() + divAdj;
125
126
0
        results_.value = solver->valueAt(spot);
127
0
        results_.delta = solver->deltaAt(spot);
128
0
        results_.gamma = solver->gammaAt(spot);
129
0
        results_.theta = solver->thetaAt(spot);
130
0
    }
131
}