/src/quantlib/ql/experimental/barrieroption/vannavolgainterpolation.hpp
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) 2013 Yue Tian |
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 vannavolgainterpolation.hpp |
21 | | \brief Vanna/Volga interpolation between discrete points |
22 | | */ |
23 | | |
24 | | #ifndef quantlib_vanna_volga_interpolation_hpp |
25 | | #define quantlib_vanna_volga_interpolation_hpp |
26 | | |
27 | | #include <ql/math/interpolation.hpp> |
28 | | #include <ql/pricingengines/blackformula.hpp> |
29 | | #include <ql/math/distributions/normaldistribution.hpp> |
30 | | #include <vector> |
31 | | |
32 | | namespace QuantLib { |
33 | | |
34 | | namespace detail { |
35 | | template<class I1, class I2> class VannaVolgaInterpolationImpl; |
36 | | } |
37 | | |
38 | | //! %Vanna Volga interpolation between discrete points |
39 | | class VannaVolgaInterpolation : public Interpolation { |
40 | | public: |
41 | | /*! \pre the \f$ x \f$ values must be sorted. */ |
42 | | template <class I1, class I2> |
43 | | VannaVolgaInterpolation(const I1& xBegin, const I1& xEnd, |
44 | | const I2& yBegin, |
45 | | Real spot, |
46 | | DiscountFactor dDiscount, |
47 | | DiscountFactor fDiscount, |
48 | 0 | Time T) { |
49 | 0 | impl_ = ext::make_shared< |
50 | 0 | detail::VannaVolgaInterpolationImpl<I1,I2> >( |
51 | 0 | xBegin, xEnd, yBegin, |
52 | 0 | spot, dDiscount, fDiscount, T); |
53 | 0 | impl_->update(); |
54 | 0 | } |
55 | | }; |
56 | | |
57 | | //! %VannaVolga-interpolation factory and traits |
58 | | class VannaVolga { |
59 | | public: |
60 | | VannaVolga(Real spot, |
61 | | DiscountFactor dDiscount, |
62 | | DiscountFactor fDiscount, |
63 | | Time T) |
64 | 0 | :spot_(spot), dDiscount_(dDiscount), fDiscount_(fDiscount), T_(T) |
65 | 0 | {} |
66 | | template <class I1, class I2> |
67 | | Interpolation interpolate(const I1& xBegin, const I1& xEnd, |
68 | 0 | const I2& yBegin) const { |
69 | 0 | return VannaVolgaInterpolation(xBegin, xEnd, yBegin, spot_, dDiscount_, fDiscount_, T_); |
70 | 0 | } |
71 | | static const Size requiredPoints = 3; |
72 | | private: |
73 | | Real spot_; |
74 | | DiscountFactor dDiscount_; |
75 | | DiscountFactor fDiscount_; |
76 | | Time T_; |
77 | | }; |
78 | | |
79 | | namespace detail { |
80 | | |
81 | | template <class I1, class I2> |
82 | | class VannaVolgaInterpolationImpl |
83 | | : public Interpolation::templateImpl<I1,I2> { |
84 | | public: |
85 | | VannaVolgaInterpolationImpl(const I1& xBegin, const I1& xEnd, |
86 | | const I2& yBegin, |
87 | | Real spot, |
88 | | DiscountFactor dDiscount, |
89 | | DiscountFactor fDiscount, |
90 | | Time T) |
91 | 0 | : Interpolation::templateImpl<I1,I2>(xBegin, xEnd, yBegin, |
92 | 0 | VannaVolga::requiredPoints), |
93 | 0 | spot_(spot), dDiscount_(dDiscount), fDiscount_(fDiscount), T_(T) { |
94 | 0 | QL_REQUIRE(this->xEnd_-this->xBegin_ == 3, |
95 | 0 | "Vanna Volga Interpolator only interpolates 3 volatilities in strike space"); |
96 | 0 | } |
97 | 0 | void update() override { |
98 | | //atmVol should be the second vol |
99 | 0 | atmVol_ = this->yBegin_[1]; |
100 | 0 | fwd_ = spot_*fDiscount_/dDiscount_; |
101 | 0 | for(Size i = 0; i < 3; i++){ |
102 | 0 | premiaBS.push_back(blackFormula(Option::Call, this->xBegin_[i], fwd_, atmVol_ * std::sqrt(T_), dDiscount_)); |
103 | 0 | premiaMKT.push_back(blackFormula(Option::Call, this->xBegin_[i], fwd_, this->yBegin_[i] * std::sqrt(T_), dDiscount_)); |
104 | 0 | vegas.push_back(vega(this->xBegin_[i])); |
105 | 0 | } |
106 | 0 | } |
107 | 0 | Real value(Real k) const override { |
108 | 0 | Real x1 = vega(k)/vegas[0] |
109 | 0 | * (std::log(this->xBegin_[1]/k) * std::log(this->xBegin_[2]/k)) |
110 | 0 | / (std::log(this->xBegin_[1]/this->xBegin_[0]) * std::log(this->xBegin_[2]/this->xBegin_[0])); |
111 | 0 | Real x2 = vega(k)/vegas[1] |
112 | 0 | * (std::log(k/this->xBegin_[0]) * std::log(this->xBegin_[2]/k)) |
113 | 0 | / (std::log(this->xBegin_[1]/this->xBegin_[0]) * std::log(this->xBegin_[2]/this->xBegin_[1])); |
114 | 0 | Real x3 = vega(k)/vegas[2] |
115 | 0 | * (std::log(k/this->xBegin_[0]) * std::log(k/this->xBegin_[1])) |
116 | 0 | / (std::log(this->xBegin_[2]/this->xBegin_[0]) * std::log(this->xBegin_[2]/this->xBegin_[1])); |
117 | |
|
118 | 0 | Real cBS = blackFormula(Option::Call, k, fwd_, atmVol_ * std::sqrt(T_), dDiscount_); |
119 | 0 | Real c = cBS + x1*(premiaMKT[0] - premiaBS[0]) + x2*(premiaMKT[1] - premiaBS[1]) + x3*(premiaMKT[2] - premiaBS[2]); |
120 | 0 | Real std = blackFormulaImpliedStdDev(Option::Call, k, fwd_, c, dDiscount_); |
121 | 0 | return std / sqrt(T_); |
122 | 0 | } |
123 | 0 | Real primitive(Real) const override { |
124 | 0 | QL_FAIL("Vanna Volga primitive not implemented"); |
125 | 0 | } |
126 | 0 | Real derivative(Real) const override { |
127 | 0 | QL_FAIL("Vanna Volga derivative not implemented"); |
128 | 0 | } |
129 | 0 | Real secondDerivative(Real) const override { |
130 | 0 | QL_FAIL("Vanna Volga secondDerivative not implemented"); |
131 | 0 | } |
132 | | |
133 | | private: |
134 | | std::vector<Real> premiaBS; |
135 | | std::vector<Real> premiaMKT; |
136 | | std::vector<Real> vegas; |
137 | | Real atmVol_; |
138 | | Real spot_; |
139 | | Real fwd_; |
140 | | DiscountFactor dDiscount_; |
141 | | DiscountFactor fDiscount_; |
142 | | Time T_; |
143 | | |
144 | 0 | Real vega(Real k) const { |
145 | 0 | Real d1 = (std::log(fwd_/k) + 0.5 * std::pow(atmVol_, 2.0) * T_)/(atmVol_ * std::sqrt(T_)); |
146 | 0 | NormalDistribution norm; |
147 | 0 | return spot_ * dDiscount_ * std::sqrt(T_) * norm(d1); |
148 | 0 | } |
149 | | }; |
150 | | |
151 | | } |
152 | | |
153 | | } |
154 | | |
155 | | #endif |