/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  |  | }  |