QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
singlefactorbsmbasketengine.cpp
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) 2024 Klaus Spanderen
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 <http://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 singlefactorbsmbasketengine.cpp
21*/
22
23#include <ql/exercise.hpp>
32
33namespace QuantLib {
34
35 namespace detail {
37 Array a, Array sig, Real K)
38 : a_(std::move(a)), sig_(std::move(sig)), K_(K) {
39 QL_REQUIRE(a_.size() == sig_.size(),
40 "Arrays must have the same size");
41 }
42
44 ++fCtr_;
45
46 Real s = 0.0;
47 for (Size i=0; i < a_.size(); ++i)
48 s += a_[i]*std::exp(sig_[i]*x);
49 return s - K_;
50 }
51
53 ++fPrimeCtr_;
54
55 Real s = 0.0;
56 for (Size i=0; i < a_.size(); ++i)
57 s += a_[i]*sig_[i]*std::exp(sig_[i]*x);
58 return s;
59 }
60
63
64 Real s = 0.0;
65 for (Size i=0; i < a_.size(); ++i)
66 s += a_[i]*squared(sig_[i])*std::exp(sig_[i]*x);
67 return s;
68 }
69
71 return fCtr_;
72 }
73
75 return fPrimeCtr_;
76 }
77
79 return fDoublePrimeCtr_;
80 }
81
83 const Array attr = a_*sig_;
85 std::all_of(
86 attr.begin(), attr.end(),
87 [](Real x) -> bool { return x >= 0.0; }
88 ),
89 "a*sig should not be negative"
90 );
91
92 const bool logProb =
93 std::all_of(
94 a_.begin(), a_.end(),
95 [](Real x) -> bool { return x > 0;}
96 );
97
98 QL_REQUIRE(K_ > 0 || !logProb,
99 "non-positive strikes only allowed for spread options");
100
101 // linear approximation
102 const Real denom = std::accumulate(attr.begin(), attr.end(), Real(0.0));
103 const Real xInit = (std::abs(denom) > 1000*QL_EPSILON)
104 ? std::min(10.0, std::max(-10.0,
105 (K_ - std::accumulate(a_.begin(), a_.end(), Real(0.0)))/denom)
106 )
107 : Real(0.0);
108
109 switch(strategy) {
110 case Brent:
111 return QuantLib::Brent().solve(*this, xTol, xInit, 1.0);
112 case Newton:
113 return QuantLib::Newton().solve(*this, xTol, xInit, 1.0);
114 case Ridder:
115 return QuantLib::Ridder().solve(*this, xTol, xInit, 1.0);
116 case Halley:
117 return QuantLib::Halley().solve(*this, xTol, xInit, 1.0);
118 default:
119 QL_FAIL("unknown strategy type");
120 }
121 }
122 }
123
125 std::vector<ext::shared_ptr<GeneralizedBlackScholesProcess> > p,
126 Real xTol)
127 : xTol_(xTol),
128 n_(p.size()), processes_(std::move(p)) {
129
130 std::for_each(processes_.begin(), processes_.end(),
131 [this](const auto& p) { registerWith(p); });
132 }
133
135 const ext::shared_ptr<AverageBasketPayoff> avgPayoff =
136 ext::dynamic_pointer_cast<AverageBasketPayoff>(arguments_.payoff);
137 QL_REQUIRE(avgPayoff, "average basket payoff expected");
138 const ext::shared_ptr<PlainVanillaPayoff> payoff =
139 ext::dynamic_pointer_cast<PlainVanillaPayoff>(avgPayoff->basePayoff());
140 QL_REQUIRE(payoff, "non-plain vanilla payoff given");
141 const Real strike = payoff->strike();
142
143 const Array weights = avgPayoff->weights();
144 QL_REQUIRE(n_ == weights.size(),
145 "wrong number of weights arguments in payoff");
146
147 const ext::shared_ptr<EuropeanExercise> exercise =
148 ext::dynamic_pointer_cast<EuropeanExercise>(arguments_.exercise);
149 QL_REQUIRE(exercise, "not an European exercise");
150 const Date maturityDate = exercise->lastDate();
151
153 const Array s = pExtractor.getSpot();
154 const Array dq = pExtractor.getDividendYieldDf(maturityDate);
155 const DiscountFactor dr0 = pExtractor.getInterestRateDf(maturityDate);
156
157 const Array stdDev = pExtractor.getBlackStdDev(maturityDate);
158 const Array v = stdDev*stdDev;
159
160 const Array fwdBasket = weights * s * dq /dr0;
161
162 // first check if all vols are zero -> intrinsic case
163 if (std::all_of(
164 stdDev.begin(), stdDev.end(),
165 [](Real x) -> bool { return close_enough(x, 0.0); }
166 )) {
167 results_.value = dr0*payoff->operator()(
168 std::accumulate(fwdBasket.begin(), fwdBasket.end(), Real(0.0)));
169 }
170 else {
172 fwdBasket*Exp(-0.5*v), stdDev, strike)
174
176 const Real cp = (payoff->optionType() == Option::Call) ? 1.0 : -1.0;
177
178 results_.value = cp * dr0 *
179 std::inner_product(
180 fwdBasket.begin(), fwdBasket.end(), stdDev.begin(),
181 Real(-strike*N(cp*d)),
182 std::plus<>(),
183 [d, cp, &N](Real x, Real y) -> Real { return x*N(cp*(d+y)); }
184 );
185
187 }
188 }
189}
190
Brent 1-D solver.
1-D array used in linear algebra.
Definition: array.hpp:52
const_iterator end() const
Definition: array.hpp:499
Size size() const
dimension of the array
Definition: array.hpp:483
const_iterator begin() const
Definition: array.hpp:491
Brent 1-D solver
Definition: brent.hpp:37
Cumulative normal distribution function.
Concrete date class.
Definition: date.hpp:125
Halley 1-D solver
Definition: halley.hpp:41
std::map< std::string, ext::any > additionalResults
Definition: instrument.hpp:123
Newton 1-D solver
Definition: newton.hpp:40
ext::shared_ptr< Exercise > exercise
Definition: option.hpp:65
ext::shared_ptr< Payoff > payoff
Definition: option.hpp:64
Ridder 1-D solver
Definition: ridder.hpp:37
SingleFactorBsmBasketEngine(std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > p, Real xTol=1e4 *QL_EPSILON)
const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
Real solve(const F &f, Real accuracy, Real guess, Real step) const
Definition: solver1d.hpp:84
Real getRoot(Real xTol=1e6 *QL_EPSILON, Strategy strategy=Brent) const
Array getBlackStdDev(const Date &maturityDate) const
Array getDividendYieldDf(const Date &maturityDate) const
DiscountFactor getInterestRateDf(const Date &maturityDate) const
Real a_
#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
Date d
Option exercise classes and payoff function.
#define QL_EPSILON
Definition: qldefines.hpp:178
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
std::size_t Size
size of a container
Definition: types.hpp:58
Halley 1-D solver.
ext::shared_ptr< QuantLib::Payoff > payoff
functionals and combinators not included in the STL
Definition: any.hpp:37
T squared(T x)
Definition: functional.hpp:37
Array Exp(const Array &v)
Definition: array.hpp:863
STL namespace.
Newton 1-D solver.
normal, cumulative and inverse cumulative distributions
ext::shared_ptr< BlackVolTermStructure > v
Ridder 1-D solver.
Basket engine where all underlyings are driven by one stochastic factor.
helper class to extract underlying, volatility etc from a vector of processes