Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
AnalyticOutperformanceOptionEngine Class Reference

Pricing engine for European outperformance options using analytical formulae. More...

#include <qle/pricingengines/analyticoutperformanceoptionengine.hpp>

+ Inheritance diagram for AnalyticOutperformanceOptionEngine:
+ Collaboration diagram for AnalyticOutperformanceOptionEngine:

Public Member Functions

 AnalyticOutperformanceOptionEngine (const ext::shared_ptr< GeneralizedBlackScholesProcess > &process1, const ext::shared_ptr< GeneralizedBlackScholesProcess > &process2, const Handle< CorrelationTermStructure > &correlation, QuantLib::Size integrationPoints)
 
void calculate () const override
 

Private Member Functions

Real correlation (Time t, Real strike=1) const
 
Real rho (Time t) const
 
Real integrand (const Real x, Real phi, Real k, Real m1, Real m2, Real v1, Real v2, Real s1, Real s2, Real i1, Real i2, Real fixingTime) const
 
Real getTodaysFxConversionRate (const QuantLib::ext::shared_ptr< QuantExt::FxIndex > &fxIndex) const
 

Private Attributes

ext::shared_ptr< GeneralizedBlackScholesProcess > process1_
 
ext::shared_ptr< GeneralizedBlackScholesProcess > process2_
 
Handle< CorrelationTermStructurecorrelationCurve_
 
QuantLib::Size integrationPoints_
 

Friends

class integrand_f
 

Detailed Description

Pricing engine for European outperformance options using analytical formulae.

Definition at line 35 of file analyticoutperformanceoptionengine.hpp.

Constructor & Destructor Documentation

◆ AnalyticOutperformanceOptionEngine()

AnalyticOutperformanceOptionEngine ( const ext::shared_ptr< GeneralizedBlackScholesProcess > &  process1,
const ext::shared_ptr< GeneralizedBlackScholesProcess > &  process2,
const Handle< CorrelationTermStructure > &  correlation,
QuantLib::Size  integrationPoints 
)

Definition at line 47 of file analyticoutperformanceoptionengine.cpp.

51 : process1_(process1), process2_(process2), correlationCurve_(correlation), integrationPoints_(integrationPoints) {
52 registerWith(process1_);
53 registerWith(process2_);
54}
ext::shared_ptr< GeneralizedBlackScholesProcess > process2_
ext::shared_ptr< GeneralizedBlackScholesProcess > process1_

Member Function Documentation

◆ calculate()

void calculate ( ) const
override

Definition at line 114 of file analyticoutperformanceoptionengine.cpp.

114 {
115
116 QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "not an European option");
117
118 Option::Type optionType = arguments_.optionType;
119 Real phi = optionType == Option::Call ? 1.0 : -1.0;
120
121 Real strike = arguments_.strikeReturn;
122 QL_REQUIRE(strike >= 0, "non-negative strike expected");
123
124 Time fixingTime = process1_->time(arguments_.exercise->lastDate());
125
126 Real fx1 = arguments_.fxIndex1 ? getTodaysFxConversionRate(arguments_.fxIndex1) : 1.0;
127 Real fx2 = arguments_.fxIndex2 ? getTodaysFxConversionRate(arguments_.fxIndex2) : 1.0;
128
129 Real s1 = process1_->stateVariable()->value();
130 Real s2 = process2_->stateVariable()->value();
131 Real i1 = arguments_.initialValue1 * fx1;
132 Real i2 = arguments_.initialValue2 * fx2;
133
134 Real v1 = process1_->blackVolatility()->blackVol(
135 arguments_.exercise->lastDate(), s1);
136 Real v2 = process2_->blackVolatility()->blackVol(
137 arguments_.exercise->lastDate(), s2);
138
139 Real riskFreeRate1 = process1_->riskFreeRate()->zeroRate(
140 arguments_.exercise->lastDate(),
141 process1_->riskFreeRate()->dayCounter(),
142 Continuous, NoFrequency);
143 Real riskFreeRate2 = process2_->riskFreeRate()->zeroRate(
144 arguments_.exercise->lastDate(),
145 process2_->riskFreeRate()->dayCounter(),
146 Continuous, NoFrequency);
147 Real dividendYield1 = process1_->dividendYield()->zeroRate(
148 arguments_.exercise->lastDate(),
149 process1_->dividendYield()->dayCounter(),
150 Continuous, NoFrequency);
151 Real dividendYield2 = process2_->dividendYield()->zeroRate(
152 arguments_.exercise->lastDate(),
153 process2_->dividendYield()->dayCounter(),
154 Continuous, NoFrequency);
155
156 Real m1 = riskFreeRate1 - dividendYield1;
157 Real m2 = riskFreeRate2 - dividendYield2;
158
159 Real k = strike;
160
161 Real res = 0.0;
162
163 bool hasBarrier = (arguments_.knockInPrice != Null<Real>()) || (arguments_.knockOutPrice != Null<Real>());
164 Real integral = 0;
165 if (hasBarrier) {
166 Real my = (m2 - 0.5 * v2 * v2) * fixingTime;
167 Real vy = v2 * std::sqrt(fixingTime);
168
169 Real precision = 1.0e-6;
170
171 Real upperBound = Null<Real>();
172 Real lowerBound = Null<Real>();
173 if (arguments_.knockOutPrice != Null<Real>()) {
174 Real koPrice = fx2 * arguments_.knockOutPrice;
175 // for the integration variable y : upperBound = log( knockOutPrice / initialPrice2)
176 // in Brigo the variable change v = (y - my) / vy is made
177 // we make a further variable change x = v / sqrt(2)
178 upperBound = (std::log(koPrice / s2) - my) / ( vy * M_SQRT2);
179
180 if (arguments_.knockInPrice == Null<Real>()) {
181 // we estimate the infinite boundary
182 lowerBound = -2 * std::fabs(upperBound);
183 while(integrand(lowerBound, phi, k, m1, m2, v1, v2, s1, s2, i1, i2, fixingTime) > precision)
184 lowerBound *=2.0;
185 }
186 }
187
188 if (arguments_.knockInPrice != Null<Real>()) {
189 Real kiPrice = fx2 * arguments_.knockInPrice;
190 // for the integration variable y : lowerBound = log( knockInPrice / initialPrice2)
191 // in Brigo the variable change v = (y - my) / vy is made
192 // we make a further variable change x = v / sqrt(2)
193 lowerBound = (std::log(kiPrice / s2) - my) / ( vy * M_SQRT2);
194
195 if (arguments_.knockOutPrice == Null<Real>()) {
196 // we estimate the infinite boundary
197 upperBound = 2 * std::fabs(lowerBound);
198 while(integrand(upperBound, phi, k, m1, m2, v1, v2, s1, s2, i1, i2, fixingTime) > precision)
199 upperBound *=2.0;
200 }
201 }
202
203 QuantLib::ext::shared_ptr<Integrator> integratorBounded = QuantLib::ext::make_shared<GaussKronrodNonAdaptive>(precision, 1000000, 1.0);
204
205 QL_REQUIRE(upperBound != Null<Real>(), "AnalyticOutperformanceOptionEngine: expected valid upper bound.");
206 QL_REQUIRE(lowerBound != Null<Real>(), "AnalyticOutperformanceOptionEngine: expected valid lower bound.");
207 QL_REQUIRE(upperBound > lowerBound, "incorrect knock in levels provided");
208 integral += (*integratorBounded)(integrand_f(this, phi, k, m1, m2, v1, v2, s1, s2, i1, i2, fixingTime), lowerBound, upperBound);
209
210 } else {
211 QuantLib::ext::shared_ptr<GaussianQuadrature> integrator = QuantLib::ext::make_shared<GaussHermiteIntegration>(integrationPoints_);
212 integral +=
213 (*integrator)(integrand_f(this, phi, k, m1, m2, v1, v2, s1, s2, i1, i2, fixingTime));
214 }
215
216 res += (integral / M_SQRTPI);
217 DiscountFactor riskFreeDiscount =
218 process1_->riskFreeRate()->discount(arguments_.exercise->lastDate());
219
220 results_.value = res * riskFreeDiscount * arguments_.notional;
221
222 Real variance1 = process1_->blackVolatility()->blackVariance(
223 arguments_.exercise->lastDate(), s1);
224 Real variance2 = process2_->blackVolatility()->blackVariance(
225 arguments_.exercise->lastDate(), s2);
226 Real variance = variance1 + variance2 - 2 * rho(fixingTime) * std::sqrt(variance1)*std::sqrt(variance2);
227 Real stdDev = std::sqrt(variance);
228 results_.standardDeviation = stdDev;
229
230 results_.additionalResults["spot1"] = s1;
231 results_.additionalResults["spot2"] = s2;
232 results_.additionalResults["fx1"] = fx1;
233 results_.additionalResults["fx2"] = fx2;
234 results_.additionalResults["blackVol1"] = v1;
235 results_.additionalResults["blackVol2"] = v2;
236 results_.additionalResults["correlation"] = rho(fixingTime);
237 results_.additionalResults["strike"] = strike;
238 results_.additionalResults["residualTime"] = fixingTime;
239 results_.additionalResults["riskFreeRate1"] = riskFreeRate1;
240 results_.additionalResults["riskFreeRate2"] = riskFreeRate2;
241 results_.additionalResults["dividendYield1"] = dividendYield1;
242 results_.additionalResults["dividendYield2"] = dividendYield2;
243
244} // calculate
const Instrument::results * results_
Definition: cdsoption.cpp:81
Real getTodaysFxConversionRate(const QuantLib::ext::shared_ptr< QuantExt::FxIndex > &fxIndex) const
Real integrand(const Real x, Real phi, Real k, Real m1, Real m2, Real v1, Real v2, Real s1, Real s2, Real i1, Real i2, Real fixingTime) const
Real integral(const CrossAssetModel &model, const E &e, const Real a, const Real b)
RandomVariable variance(const RandomVariable &r)
Swap::arguments * arguments_
+ Here is the call graph for this function:

◆ correlation()

Real correlation ( Time  t,
Real  strike = 1 
) const
private

Definition at line 43 of file analyticoutperformanceoptionengine.hpp.

43{ return correlationCurve_->correlation(t, strike); }
+ Here is the caller graph for this function:

◆ rho()

Real rho ( Time  t) const
private

Definition at line 44 of file analyticoutperformanceoptionengine.hpp.

44{ return std::max(std::min(correlation(t), 0.9999), -0.9999); }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ integrand()

Real integrand ( const Real  x,
Real  phi,
Real  k,
Real  m1,
Real  m2,
Real  v1,
Real  v2,
Real  s1,
Real  s2,
Real  i1,
Real  i2,
Real  fixingTime 
) const
private

Definition at line 80 of file analyticoutperformanceoptionengine.cpp.

80 {
81
82 // this is Brigo, 13.16.2 with x = v / sqrt(2)
83 Real v = M_SQRT2 * x;
84
85 //a positive real number 'a', a negative real number 'b'
86 Real a = 1 / i1;
87 Real b = -1 / i2;
88
89 CumulativeNormalDistribution cnd;
90
91 Real h =
92 k - b * s2 * std::exp((m2 - 0.5 * v2 * v2) * fixingTime +
93 v2 * std::sqrt(fixingTime) * v);
94 Real phi1, phi2;
95 phi1 = cnd(
96 phi * (std::log(a * s1 / h) +
97 (m1 + (0.5 - rho(fixingTime) * rho(fixingTime)) * v1 * v1) * fixingTime +
98 rho(fixingTime) * v1 * std::sqrt(fixingTime) * v) /
99 (v1 * std::sqrt(fixingTime * (1.0 - rho(fixingTime) * rho(fixingTime)))));
100 phi2 = cnd(
101 phi * (std::log(a * s1 / h) +
102 (m1 - 0.5 * v1 * v1) * fixingTime +
103 rho(fixingTime) * v1 * std::sqrt(fixingTime) * v) /
104 (v1 * std::sqrt(fixingTime * (1.0 - rho(fixingTime) * rho(fixingTime)))));
105 Real f = a * phi * s1 *
106 std::exp(m1 * fixingTime -
107 0.5 * rho(fixingTime) * rho(fixingTime) * v1 * v1 * fixingTime +
108 rho(fixingTime) * v1 * std::sqrt(fixingTime) * v) *
109 phi1 -
110 phi * h * phi2;
111 return std::exp(-x * x) * f;
112}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getTodaysFxConversionRate()

Real getTodaysFxConversionRate ( const QuantLib::ext::shared_ptr< QuantExt::FxIndex > &  fxIndex) const
private

Definition at line 31 of file analyticoutperformanceoptionengine.cpp.

31 {
32 // The fx conversion rate as of today should always be taken from the market data, i.e. we should not use a
33 // historical fixing, even if it exists, because we should generate sensitivities to market fx spot rate changes.
34 // Furthermore, we can get the fx spot rate from the market data even if today is not a valid fixing date for the
35 // fx index, that is why we should not use Index::fixing(today, true).
36 Real tmp;
37 if (fxIndex->useQuote()) {
38 tmp = fxIndex->fxQuote()->value();
39 } else {
40 tmp = ExchangeRateManager::instance()
41 .lookup(fxIndex->sourceCurrency(), fxIndex->targetCurrency())
42 .rate();
43 }
44 return tmp;
45}
+ Here is the caller graph for this function:

Friends And Related Function Documentation

◆ integrand_f

friend class integrand_f
friend

Definition at line 49 of file analyticoutperformanceoptionengine.hpp.

Member Data Documentation

◆ process1_

ext::shared_ptr<GeneralizedBlackScholesProcess> process1_
private

Definition at line 51 of file analyticoutperformanceoptionengine.hpp.

◆ process2_

ext::shared_ptr<GeneralizedBlackScholesProcess> process2_
private

Definition at line 52 of file analyticoutperformanceoptionengine.hpp.

◆ correlationCurve_

Handle<CorrelationTermStructure> correlationCurve_
private

Definition at line 54 of file analyticoutperformanceoptionengine.hpp.

◆ integrationPoints_

QuantLib::Size integrationPoints_
private

Definition at line 55 of file analyticoutperformanceoptionengine.hpp.