QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
replicatingvarianceswapengine.hpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006 Warren Chou
5 Copyright (C) 2007, 2008 StatPro Italia srl
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 replicatingvarianceswapengine.hpp
22 \brief Replicating engine for variance swaps
23*/
24
25#ifndef quantlib_replicating_varianceswap_engine_hpp
26#define quantlib_replicating_varianceswap_engine_hpp
27
28#include <ql/exercise.hpp>
32#include <utility>
33
34namespace QuantLib {
35
36 //! Variance-swap pricing engine using replicating cost,
37 /*! as described in Demeterfi, Derman, Kamal & Zou,
38 "A Guide to Volatility and Variance Swaps", 1999
39
40 \ingroup forwardengines
41
42 \test returned variances verified against results from literature
43 */
45 public:
46 typedef std::vector<std::pair<
47 ext::shared_ptr<StrikedTypePayoff>, Real> > weights_type;
48 // constructor
49 ReplicatingVarianceSwapEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process,
50 Real dk = 5.0,
51 const std::vector<Real>& callStrikes = std::vector<Real>(),
52 const std::vector<Real>& putStrikes = std::vector<Real>());
53 void calculate() const override;
54
55 protected:
56 // helper methods
57 void computeOptionWeights(const std::vector<Real>&,
59 weights_type& optionWeights) const;
62 const weights_type& optionWeights) const;
63 Rate riskFreeRate() const;
65 Real underlying() const;
66 Time residualTime() const;
67 private:
68 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
70 std::vector<Real> callStrikes_, putStrikes_;
71 };
72
73
74 // inline definitions
75
77 ext::shared_ptr<GeneralizedBlackScholesProcess> process,
78 Real dk,
79 const std::vector<Real>& callStrikes,
80 const std::vector<Real>& putStrikes)
81 : process_(std::move(process)), dk_(dk), callStrikes_(callStrikes), putStrikes_(putStrikes) {
82
83 QL_REQUIRE(process_, "no process given");
84 QL_REQUIRE(!callStrikes.empty() && !putStrikes.empty(),
85 "no strike(s) given");
86 QL_REQUIRE(*std::min_element(putStrikes.begin(),putStrikes.end())>0.0,
87 "min put strike must be positive");
88 QL_REQUIRE(*std::min_element(callStrikes.begin(), callStrikes.end())==
89 *std::max_element(putStrikes.begin(), putStrikes.end()),
90 "min call and max put strikes differ");
91 }
92
93
95 const std::vector<Real>& availStrikes,
96 const Option::Type type,
97 weights_type& optionWeights) const {
98 if (availStrikes.empty())
99 return;
100
101 std::vector<Real> strikes = availStrikes;
102
103 // add end-strike for piecewise approximation
104 switch (type) {
105 case Option::Call:
106 std::sort(strikes.begin(), strikes.end());
107 strikes.push_back(strikes.back() + dk_);
108 break;
109 case Option::Put:
110 std::sort(strikes.begin(), strikes.end(), std::greater<>());
111 strikes.push_back(std::max(strikes.back() - dk_, 0.0));
112 break;
113 default:
114 QL_FAIL("invalid option type");
115 }
116
117 // remove duplicate strikes
118 auto last = std::unique(strikes.begin(), strikes.end());
119 strikes.erase(last, strikes.end());
120
121 // compute weights
122 Real f = strikes.front();
123 Real slope, prevSlope = 0.0;
124
125
126
127
128 for (std::vector<Real>::const_iterator k=strikes.begin();
129 // added end-strike discarded
130 k<strikes.end()-1;
131 ++k) {
132 slope = std::fabs((computeLogPayoff(*(k+1), f) -
133 computeLogPayoff(*k, f))/
134 (*(k+1) - *k));
135 ext::shared_ptr<StrikedTypePayoff> payoff(
136 new PlainVanillaPayoff(type, *k));
137 if ( k == strikes.begin() )
138 optionWeights.emplace_back(payoff,slope);
139 else
140 optionWeights.emplace_back(payoff, slope - prevSlope);
141 prevSlope = slope;
142 }
143 }
144
145
147 const Real strike,
148 const Real callPutStrikeBoundary) const {
149 Real f = callPutStrikeBoundary;
150 return (2.0/residualTime()) * (((strike - f)/f) - std::log(strike/f));
151 }
152
153
154 inline
156 const weights_type& optionWeights) const {
157
158 ext::shared_ptr<Exercise> exercise(
160 ext::shared_ptr<PricingEngine> optionEngine(
162 Real optionsValue = 0.0;
163
164 for (auto i = optionWeights.begin(); i < optionWeights.end(); ++i) {
165 ext::shared_ptr<StrikedTypePayoff> payoff = i->first;
166 EuropeanOption option(payoff, exercise);
167 option.setPricingEngine(optionEngine);
168 Real weight = i->second;
169 optionsValue += option.NPV() * weight;
170 }
171
172 Real f = optionWeights.front().first->strike();
173 return 2.0 * riskFreeRate() -
174 2.0/residualTime() *
175 (((underlying()/riskFreeDiscount() - f)/f) +
176 std::log(f/underlying())) +
177 optionsValue/riskFreeDiscount();
178 }
179
180
181 // calculate variance via replicating portfolio
183 weights_type optionWeigths;
186
188
190 process_->riskFreeRate()->discount(arguments_.maturityDate);
191 Real multiplier;
192 switch (arguments_.position) {
193 case Position::Long:
194 multiplier = 1.0;
195 break;
196 case Position::Short:
197 multiplier = -1.0;
198 break;
199 default:
200 QL_FAIL("Unknown position");
201 }
204
205 results_.additionalResults["optionWeights"] = optionWeigths;
206 }
207
208
210 return process_->x0();
211 }
212
213
215 return process_->time(arguments_.maturityDate);
216 }
217
218
220 return process_->riskFreeRate()->zeroRate(residualTime(), Continuous,
221 NoFrequency, true);
222 }
223
224
225 inline
227 return process_->riskFreeRate()->discount(residualTime());
228 }
229
230}
231
232
233#endif
Analytic European engine.
Pricing engine for European vanilla options using analytical formulae.
European exercise.
Definition: exercise.hpp:96
European option on a single asset.
std::map< std::string, ext::any > additionalResults
Definition: instrument.hpp:123
Real NPV() const
returns the net present value of the instrument.
Definition: instrument.hpp:167
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
Definition: instrument.cpp:35
Plain-vanilla payoff.
Definition: payoffs.hpp:105
Variance-swap pricing engine using replicating cost,.
std::vector< std::pair< ext::shared_ptr< StrikedTypePayoff >, Real > > weights_type
void computeOptionWeights(const std::vector< Real > &, Option::Type, weights_type &optionWeights) const
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
ReplicatingVarianceSwapEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process, Real dk=5.0, const std::vector< Real > &callStrikes=std::vector< Real >(), const std::vector< Real > &putStrikes=std::vector< Real >())
Real computeReplicatingPortfolio(const weights_type &optionWeights) const
base class for variance-swap engines
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
European option on a single asset.
Option exercise classes and payoff function.
@ NoFrequency
null frequency
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
Real Rate
interest rates
Definition: types.hpp:70
ext::shared_ptr< QuantLib::Payoff > payoff
Definition: any.hpp:35
STL namespace.
Variance swap.