QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
analyticcompoundoptionengine.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2009 Dimitri Reiswich
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#include <ql/pricingengines/exotic/analyticcompoundoptionengine.hpp>
21#include <ql/math/solvers1d/brent.hpp>
22#include <ql/pricingengines/blackformula.hpp>
23#include <utility>
24
25namespace QuantLib {
26
27 namespace {
28
29 // Helper Class needed to solve an implicit problem of finding a
30 // spot to a corresponding option price.
31 class ImpliedSpotHelper {
32 public:
33 ImpliedSpotHelper(DiscountFactor dividendDiscount,
34 DiscountFactor riskFreeDiscount,
35 Real standardDeviation,
36 ext::shared_ptr<PlainVanillaPayoff> payoff,
37 Real strike)
38 : dividendDiscount_(dividendDiscount), riskFreeDiscount_(riskFreeDiscount),
39 standardDeviation_(standardDeviation), strike_(strike), payoff_(std::move(payoff)) {}
40 Real operator()(Real spot) const {
41 Real forwardPrice = spot*dividendDiscount_/riskFreeDiscount_;
42 Real value = blackFormula(payoff_, forwardPrice,
43 standardDeviation_,riskFreeDiscount_);
44 return value - strike_;
45 }
46 private:
47 DiscountFactor dividendDiscount_;
48 DiscountFactor riskFreeDiscount_;
49 Real standardDeviation_;
50 Real strike_;
51 ext::shared_ptr<PlainVanillaPayoff> payoff_;
52 };
53
54 }
55
57 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
58 : process_(std::move(process)) {
60 }
61
63
64 QL_REQUIRE(strikeDaughter()>0.0,
65 "Daughter strike must be positive");
66
67 QL_REQUIRE(strikeMother()>0.0,
68 "Mother strike must be positive");
69
70 QL_REQUIRE(spot() > 0.0, "negative or null underlying given");
71
72 /* Solver Setup ***************************************************/
73 Date helpDate(process_->riskFreeRate()->referenceDate());
74 Date helpMaturity=helpDate+(maturityDaughter()-maturityMother())*Days;
75 Real vol =process_->blackVolatility()->blackVol(helpMaturity,
77
78 Time helpTimeToMat=process_->time(helpMaturity);
79 vol=vol*std::sqrt(helpTimeToMat);
80
81 DiscountFactor dividendDiscount =
82 process_->dividendYield()->discount(helpMaturity);
83
84 DiscountFactor riskFreeDiscount =
85 process_->riskFreeRate()->discount(helpMaturity);
86
87
88 ext::shared_ptr<ImpliedSpotHelper> f(
89 new ImpliedSpotHelper(dividendDiscount, riskFreeDiscount,
90 vol, payoffDaughter(), strikeMother()));
91
92 Brent solver;
93 solver.setMaxEvaluations(1000);
94 Real accuracy = 1.0e-6;
95
96 Real sSolved=solver.solve(*f, accuracy, strikeDaughter(), 1.0e-6, strikeDaughter()*1000.0);
97 Real X=transformX(sSolved); // transform stock to return as in Wystup's book
98 /* Solver Setup Finished*****************************************/
99
100 Real phi=typeDaughter(); // -1 or 1
101 Real w=typeMother(); // -1 or 1
102
105
108 //DiscountFactor ddM=dividendDiscountMother();
110
111 Real XmSM=X-stdDeviationMother();
112 Real S=spot();
113 Real dP=dPlus();
114 Real dPT12=dPlusTau12(sSolved);
116
117 Real dM=dMinus();
118 Real strD=strikeDaughter();
119 Real strM=strikeMother();
122
125
126 Real N2XmSM=N2(-phi*w*XmSM,phi*dP);
127 Real N2X=N2(-phi*w*X,phi*dM);
128 Real NeX=N_(-phi*w*e(X));
129 Real NX=N_(-phi*w*X);
130 Real NT12=N_(phi*dPT12);
131 Real ndP=n_(dP);
132 Real nXm=n_(XmSM);
133 Real invMTime=1/std::sqrt(rTM);
134 Real invDTime=1/std::sqrt(rTD);
135
136 Real tempRes=phi*w*S*ddD*N2XmSM-phi*w*strD*rdD*N2X-w*strM*rdM*NX;
137 Real tempDelta=phi*w*ddD*N2XmSM;
138 Real tempGamma=(ddD/(vD*S))*(invMTime*nXm*NT12+w*invDTime*ndP*NeX);
139 Real tempVega=ddD*S*((1/invMTime)*nXm*NT12+w*(1/invDTime)*ndP*NeX);
140 Real tempTheta=phi*w*dD*S*ddD*N2XmSM-phi*w*rD*strD*rdD*N2X-w*rD*strM*rdM*NX;
141 tempTheta-=0.5*vD*S*ddD*(invMTime*nXm*NT12+w*invDTime*ndP*NeX);
142
143 results_.value=tempRes;
144 results_.delta=tempDelta;
145 results_.gamma=tempGamma;
146 results_.vega=tempVega;
147 results_.theta=tempTheta;
148 }
149
151 // returns -1 or 1 according to put or call
152 return (Real) payoffDaughter()->optionType();
153 }
154
156 return (Real) payoffMother()->optionType();
157 }
158
160 return arguments_.daughterExercise->lastDate();
161 }
162
164 return arguments_.exercise->lastDate();
165 }
166
168 return process_->time(maturityDaughter());
169 }
170
172 return process_->time(maturityMother());
173 }
174
177 }
178
179
181 return process_->blackVolatility()->blackVol(maturityDaughter(),
183 }
184
185
187 return process_->blackVolatility()->blackVol(maturityMother(),
188 strikeMother());
189 }
190
192 return volatilityDaughter()*std::sqrt(residualTimeDaughter());
193 }
194
196 return volatilityMother()*std::sqrt(residualTimeMother());
197 }
198
199
200 ext::shared_ptr<PlainVanillaPayoff>
202 ext::shared_ptr<PlainVanillaPayoff> dPayoff =
203 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
205 QL_REQUIRE(dPayoff, "non-plain payoff given");
206 return dPayoff;
207 }
208
209 ext::shared_ptr<PlainVanillaPayoff>
211 ext::shared_ptr<PlainVanillaPayoff> mPayoff =
212 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
213 QL_REQUIRE(mPayoff, "non-plain payoff given");
214 return mPayoff;
215 }
216
218 return payoffMother()->strike();
219 }
220
222 return payoffDaughter()->strike();
223 }
224
226 return process_->riskFreeRate()->discount(residualTimeDaughter());
227 }
228
230 return process_->riskFreeRate()->discount(residualTimeMother());
231 }
232
234 return process_->riskFreeRate()->discount(residualTimeMotherDaughter());
235 }
236
238 return process_->dividendYield()->discount(residualTimeDaughter());
239 }
240
242 return process_->dividendYield()->discount(residualTimeMother());
243 }
244
246 return process_->dividendYield()->discount(residualTimeMotherDaughter());
247 }
248
252 return std::log(forward/strikeDaughter())/sd+0.5*sd;
253 }
254
256 return dPlus()-stdDeviationDaughter();
257 }
258
262 return std::log(forward/strikeDaughter())/sd+0.5*sd;
263 }
264
266 return process_->x0();
267 }
268
270 return process_->riskFreeRate()->zeroRate(residualTimeDaughter(),
273 }
274
276 return process_->dividendYield()->zeroRate(residualTimeDaughter(),
279 }
280
282
285 resX=resX*std::exp(0.5*sd*sd);
286 resX=std::log(resX);
287
288 return resX/sd;
289 }
290
294
295 return (X*std::sqrt(rtD)+std::sqrt(rtM)*dMinus())/std::sqrt(rtD-rtM);
296 }
297
298}
ext::shared_ptr< PlainVanillaPayoff > payoffDaughter() const
AnalyticCompoundOptionEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
ext::shared_ptr< PlainVanillaPayoff > payoffMother() const
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Cumulative bivariate normal distribution function.
Brent 1-D solver
Definition: brent.hpp:37
ext::shared_ptr< Exercise > daughterExercise
ext::shared_ptr< StrikedTypePayoff > daughterPayoff
Concrete date class.
Definition: date.hpp:125
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
void setMaxEvaluations(Size evaluations)
Definition: solver1d.hpp:238
Real solve(const F &f, Real accuracy, Real guess, Real step) const
Definition: solver1d.hpp:84
@ 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
Definition: any.hpp:35
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)
STL namespace.