Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/termstructures/volatility/equityfx/hestonblackvolsurface.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) 2015 Johannes Göttker-Schnetmann
5
 Copyright (C) 2015 Klaus Spanderen
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <http://quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
/*! \file hestonblackvolsurface.hpp
22
    \brief Black volatility surface back by Heston model
23
*/
24
25
#include <ql/math/functional.hpp>
26
#include <ql/math/solvers1d/brent.hpp>
27
#include <ql/pricingengines/blackformula.hpp>
28
#include <ql/termstructures/volatility/equityfx/hestonblackvolsurface.hpp>
29
#include <ql/time/calendars/nullcalendar.hpp>
30
#include <limits>
31
#include <utility>
32
33
namespace QuantLib {
34
35
    namespace {
36
        Real blackValue(Option::Type optionType, Real strike,
37
                        Real forward, Real maturity,
38
0
                        Volatility vol, Real discount, Real npv) {
39
40
0
            return blackFormula(optionType, strike, forward,
41
0
                                std::max(0.0, vol)*std::sqrt(maturity),
42
0
                                discount)-npv;
43
0
        }
44
    }
45
46
    HestonBlackVolSurface::HestonBlackVolSurface(
47
        const Handle<HestonModel>& hestonModel,
48
        const AnalyticHestonEngine::ComplexLogFormula cpxLogFormula,
49
        AnalyticHestonEngine::Integration integration)
50
0
    : BlackVolTermStructure(hestonModel->process()->riskFreeRate()->referenceDate(),
51
0
                            NullCalendar(),
52
0
                            Following,
53
0
                            hestonModel->process()->riskFreeRate()->dayCounter()),
54
0
      hestonModel_(hestonModel), cpxLogFormula_(cpxLogFormula),
55
0
      integration_(std::move(integration)) {
56
0
        registerWith(hestonModel_);
57
0
    }
Unexecuted instantiation: QuantLib::HestonBlackVolSurface::HestonBlackVolSurface(QuantLib::Handle<QuantLib::HestonModel> const&, QuantLib::AnalyticHestonEngine::ComplexLogFormula, QuantLib::AnalyticHestonEngine::Integration)
Unexecuted instantiation: QuantLib::HestonBlackVolSurface::HestonBlackVolSurface(QuantLib::Handle<QuantLib::HestonModel> const&, QuantLib::AnalyticHestonEngine::ComplexLogFormula, QuantLib::AnalyticHestonEngine::Integration)
58
59
0
    DayCounter HestonBlackVolSurface::dayCounter() const {
60
0
        return hestonModel_->process()->riskFreeRate()->dayCounter();
61
0
    }
62
0
    Date HestonBlackVolSurface::maxDate() const {
63
0
        return Date::maxDate();
64
0
    }
65
0
    Real HestonBlackVolSurface::minStrike() const {
66
0
        return 0.0;
67
0
    }
68
0
    Real HestonBlackVolSurface::maxStrike() const {
69
0
        return std::numeric_limits<Real>::max();
70
0
    }
71
72
0
    Real HestonBlackVolSurface::blackVarianceImpl(Time t, Real strike) const {
73
0
        return squared(blackVolImpl(t, strike))*t;
74
0
    }
75
76
0
    Volatility HestonBlackVolSurface::blackVolImpl(Time t, Real strike) const {
77
0
        AnalyticHestonEngine hestonEngine(
78
0
                    hestonModel_.currentLink(), cpxLogFormula_, integration_);
79
80
0
        const ext::shared_ptr<HestonProcess>& process = hestonModel_->process();
81
82
0
        const DiscountFactor df = process->riskFreeRate()->discount(t, true);
83
84
0
        const Real fwd = process->s0()->value()
85
0
            * process->dividendYield()->discount(t, true) / df;
86
87
0
        const ext::shared_ptr<PlainVanillaPayoff> payoff =
88
0
            ext::make_shared<PlainVanillaPayoff>(
89
0
                            fwd > strike ? Option::Put : Option::Call, strike);
90
91
0
        const Real npv = hestonEngine.priceVanillaPayoff(payoff, t);
92
93
0
        const Real theta = hestonModel_->theta();
94
0
        if (npv <= 0.0) return std::sqrt(theta);
95
96
0
        Brent solver;
97
0
        solver.setMaxEvaluations(10000);
98
0
        const Volatility guess = std::sqrt(theta);
99
0
        constexpr double accuracy = std::numeric_limits<double>::epsilon();
100
101
0
        return solver.solve(
102
0
            [&](Volatility _v) {
103
0
                return blackValue(
104
0
                    payoff->optionType(), strike, fwd, t, _v, df, npv);
105
0
            },
106
0
            accuracy, guess, 0.01
107
0
        );
108
0
    }
109
}