Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
blackvariancesurfacestddevs.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <cmath>
20#include <ql/quotes/all.hpp>
22
23using namespace std;
24using namespace QuantLib;
25
26namespace QuantExt {
27
29 const Calendar& cal, const Handle<Quote>& spot, const std::vector<Time>& times, const std::vector<Real>& stdDevs,
30 const std::vector<std::vector<Handle<Quote>>>& blackVolMatrix, const DayCounter& dayCounter,
31 const QuantLib::ext::shared_ptr<EqFxIndexBase>& index, bool stickyStrike, bool flatExtrapMoneyness)
32 : BlackVarianceSurfaceMoneyness(cal, spot, times, stdDevs, blackVolMatrix, dayCounter, stickyStrike), index_(index),
33 flatExtrapolateMoneyness_(flatExtrapMoneyness) {
34
35 // set up atm variance curve - maybe just take ATM vols in
36 vector<Real>::const_iterator it = find(stdDevs.begin(), stdDevs.end(), 0.0);
37 QL_REQUIRE(it != stdDevs.end(), "atm D is required."); // this might fail
38 atmVariances_.push_back(Real(0.0));
39 atmTimes_.push_back(0.0);
40 Size atmIndex = distance(stdDevs.begin(), it);
41 for (Size i = 0; i < times.size(); i++) {
42 atmVariances_.push_back(blackVolMatrix[atmIndex][i]->value() * blackVolMatrix[atmIndex][i]->value() * times[i]);
43 atmTimes_.push_back(times[i]);
44 }
45 atmVarCurve_ = Linear().interpolate(atmTimes_.begin(), atmTimes_.end(), atmVariances_.begin());
46
47 if (!stickyStrike) {
48 QL_REQUIRE(index_ != nullptr, "index required for vol surface");
49 registerWith(index_);
50 } else {
51 for (Size i = 0; i < times_.size(); i++) {
52 Time t = times_[i];
53 Real fwd = index_->forecastFixing(t);
54 forwards_.push_back(fwd);
55 }
56 forwardCurve_ = Linear().interpolate(times_.begin(), times_.end(), forwards_.begin());
57 }
58}
59
60Real BlackVarianceSurfaceStdDevs::moneyness(Time t, Real strike) const {
61 Real fwd;
62 Real reqD; // for flat extrapolation
63 Real atmVolAtT;
64 if (t == 0) {
65 atmVolAtT = 0;
66 } else {
67 atmVolAtT = sqrt(atmVarCurve_(t, true) / t);
68 }
69
70 if (strike == Null<Real>() || strike == 0) {
71 return 0.0;
72 } else {
73 if (stickyStrike_)
74 fwd = forwardCurve_(t, true);
75 else
76 fwd = index_->forecastFixing(t);
77 Real num = log(strike / fwd);
78 Real denom = atmVolAtT * sqrt(t);
79 reqD = num / denom;
80
82 if (reqD < moneyness_.front()) {
83 reqD = moneyness_.front();
84 } else if (reqD > moneyness_.back()) {
85 reqD = moneyness_.back();
86 }
87 }
88 return reqD;
89 }
90}
91
93 const QuantLib::Handle<QuantLib::BlackVolTermStructure>& termStructre,
94 vector<vector<Handle<Quote>>>& quotesToPopulate, const std::vector<Real>& times,
95 const std::vector<Real>& stdDevPoints, const QuantLib::Interpolation& forwardCurve,
96 const QuantLib::Interpolation atmVolCurve) {
97
98 // check that quotesToPopulate container has the correct dimensions
99
100 QL_REQUIRE(quotesToPopulate.size() == stdDevPoints.size(),
101 "BlackVarianceSurfaceStdDevs::populateVolMatrix(): quotesToPopulate size ("
102 << quotesToPopulate.size() << ") does not match stdDevPoints size (" << stdDevPoints.size() << ")");
103 for (Size i = 0; i < stdDevPoints.size(); ++i) {
104 QL_REQUIRE(quotesToPopulate[i].size() == times.size(),
105 "BlackVarianceSurfaceStdDevs::populateVolMatrix(): quotesToPopulate["
106 << i << "] size (" << quotesToPopulate[i].size() << ") does not match times size ("
107 << times.size() << ")");
108 }
109
110 // populate quotesToPopulate container
111
112 for (Size j = 0; j < times.size(); j++) {
113 for (Size i = 0; i < stdDevPoints.size(); i++) {
114 Real tmpStrike = forwardCurve(times[j]) * exp(atmVolCurve(times[j]) * sqrt(times[j]) * stdDevPoints[i]);
115 Volatility vol = termStructre->blackVol(times[j], tmpStrike, true);
116 QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> q(new SimpleQuote(vol));
117 quotesToPopulate[i][j] = Handle<Quote>(q);
118 }
119 }
120}
121
122} // namespace QuantExt
Black volatility surface modeled as variance surface.
Abstract Black volatility surface based on moneyness (moneyness defined in subclasses)
std::vector< QuantLib::Real > moneyness() const
BlackVarianceSurfaceStdDevs(const Calendar &cal, const Handle< Quote > &spot, const std::vector< Time > &times, const std::vector< Real > &stdDevs, const std::vector< std::vector< Handle< Quote > > > &blackVolMatrix, const DayCounter &dayCounter, const QuantLib::ext::shared_ptr< EqFxIndexBase > &index, bool stickyStrike=false, bool flatExtrapMoneyness=false)
QuantLib::ext::shared_ptr< EqFxIndexBase > index_
static void populateVolMatrix(const QuantLib::Handle< QuantLib::BlackVolTermStructure > &termStructre, std::vector< std::vector< Handle< QuantLib::Quote > > > &quotesToPopulate, const std::vector< Real > &times, const std::vector< Real > &stdDevPoints, const QuantLib::Interpolation &forwardCurve, const QuantLib::Interpolation atmVolCurve)
RandomVariable sqrt(RandomVariable x)
CompiledFormula exp(CompiledFormula x)
CompiledFormula log(CompiledFormula x)