/src/quantlib/ql/experimental/barrieroption/vannavolgabarrierengine.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2013 Yue Tian |
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/experimental/barrieroption/vannavolgabarrierengine.hpp> |
21 | | #include <ql/experimental/barrieroption/vannavolgainterpolation.hpp> |
22 | | #include <ql/experimental/fx/blackdeltacalculator.hpp> |
23 | | #include <ql/math/matrix.hpp> |
24 | | #include <ql/pricingengines/barrier/analyticbarrierengine.hpp> |
25 | | #include <ql/pricingengines/blackformula.hpp> |
26 | | #include <ql/quotes/simplequote.hpp> |
27 | | #include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp> |
28 | | #include <ql/time/calendars/nullcalendar.hpp> |
29 | | #include <utility> |
30 | | |
31 | | using std::pow; |
32 | | using std::log; |
33 | | using std::sqrt; |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | VannaVolgaBarrierEngine::VannaVolgaBarrierEngine(Handle<DeltaVolQuote> atmVol, |
38 | | Handle<DeltaVolQuote> vol25Put, |
39 | | Handle<DeltaVolQuote> vol25Call, |
40 | | Handle<Quote> spotFX, |
41 | | Handle<YieldTermStructure> domesticTS, |
42 | | Handle<YieldTermStructure> foreignTS, |
43 | | const bool adaptVanDelta, |
44 | | const Real bsPriceWithSmile) |
45 | 0 | : atmVol_(std::move(atmVol)), vol25Put_(std::move(vol25Put)), vol25Call_(std::move(vol25Call)), |
46 | 0 | T_(atmVol_->maturity()), spotFX_(std::move(spotFX)), domesticTS_(std::move(domesticTS)), |
47 | 0 | foreignTS_(std::move(foreignTS)), adaptVanDelta_(adaptVanDelta), |
48 | 0 | bsPriceWithSmile_(bsPriceWithSmile) { |
49 | 0 | QL_REQUIRE(vol25Put_->delta() == -0.25, "25 delta put is required by vanna volga method"); |
50 | 0 | QL_REQUIRE(vol25Call_->delta() == 0.25, "25 delta call is required by vanna volga method"); |
51 | | |
52 | 0 | QL_REQUIRE(vol25Put_->maturity() == vol25Call_->maturity() && |
53 | 0 | vol25Put_->maturity() == atmVol_->maturity(), |
54 | 0 | "Maturity of 3 vols are not the same"); |
55 | | |
56 | 0 | QL_REQUIRE(!domesticTS_.empty(), "domestic yield curve is not defined"); |
57 | 0 | QL_REQUIRE(!foreignTS_.empty(), "foreign yield curve is not defined"); |
58 | | |
59 | 0 | registerWith(atmVol_); |
60 | 0 | registerWith(vol25Put_); |
61 | 0 | registerWith(vol25Call_); |
62 | 0 | registerWith(spotFX_); |
63 | 0 | registerWith(domesticTS_); |
64 | 0 | registerWith(foreignTS_); |
65 | 0 | } |
66 | | |
67 | 0 | void VannaVolgaBarrierEngine::calculate() const { |
68 | |
|
69 | 0 | QL_REQUIRE(arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut || |
70 | 0 | arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::DownOut, |
71 | 0 | "Invalid barrier type"); |
72 | | |
73 | 0 | const Real sigmaShift_vega = 0.0001; |
74 | 0 | const Real sigmaShift_volga = 0.0001; |
75 | 0 | const Real spotShift_delta = 0.0001 * spotFX_->value(); |
76 | 0 | const Real sigmaShift_vanna = 0.0001; |
77 | |
|
78 | 0 | Handle<Quote> x0Quote( |
79 | 0 | ext::make_shared<SimpleQuote>(spotFX_->value())); //used for shift |
80 | 0 | Handle<Quote> atmVolQuote( |
81 | 0 | ext::make_shared<SimpleQuote>(atmVol_->value())); //used for shift |
82 | |
|
83 | 0 | ext::shared_ptr<BlackVolTermStructure> blackVolTS = |
84 | 0 | ext::make_shared<BlackConstantVol>( |
85 | 0 | Settings::instance().evaluationDate(), |
86 | 0 | NullCalendar(), atmVolQuote, Actual365Fixed()); |
87 | 0 | ext::shared_ptr<BlackScholesMertonProcess> stochProcess = |
88 | 0 | ext::make_shared<BlackScholesMertonProcess>( |
89 | 0 | x0Quote, |
90 | 0 | foreignTS_, |
91 | 0 | domesticTS_, |
92 | 0 | Handle<BlackVolTermStructure>(blackVolTS)); |
93 | |
|
94 | 0 | ext::shared_ptr<PricingEngine> engineBS = |
95 | 0 | ext::make_shared<AnalyticBarrierEngine>(stochProcess); |
96 | |
|
97 | 0 | BlackDeltaCalculator blackDeltaCalculatorAtm( |
98 | 0 | Option::Call, atmVol_->deltaType(), x0Quote->value(), |
99 | 0 | domesticTS_->discount(T_), foreignTS_->discount(T_), |
100 | 0 | atmVol_->value() * sqrt(T_)); |
101 | 0 | Real atmStrike = blackDeltaCalculatorAtm.atmStrike(atmVol_->atmType()); |
102 | |
|
103 | 0 | Real call25Vol = vol25Call_->value(); |
104 | 0 | Real put25Vol = vol25Put_->value(); |
105 | |
|
106 | 0 | BlackDeltaCalculator blackDeltaCalculatorPut25(Option::Put, vol25Put_->deltaType(), x0Quote->value(), |
107 | 0 | domesticTS_->discount(T_), foreignTS_->discount(T_), |
108 | 0 | put25Vol * sqrt(T_)); |
109 | 0 | Real put25Strike = blackDeltaCalculatorPut25.strikeFromDelta(-0.25); |
110 | 0 | BlackDeltaCalculator blackDeltaCalculatorCall25(Option::Call, vol25Call_->deltaType(), x0Quote->value(), |
111 | 0 | domesticTS_->discount(T_), foreignTS_->discount(T_), |
112 | 0 | call25Vol * sqrt(T_)); |
113 | 0 | Real call25Strike = blackDeltaCalculatorCall25.strikeFromDelta(0.25); |
114 | | |
115 | | |
116 | | //here use vanna volga interpolated smile to price vanilla |
117 | 0 | std::vector<Real> strikes; |
118 | 0 | std::vector<Real> vols; |
119 | 0 | strikes.push_back(put25Strike); |
120 | 0 | vols.push_back(put25Vol); |
121 | 0 | strikes.push_back(atmStrike); |
122 | 0 | vols.push_back(atmVol_->value()); |
123 | 0 | strikes.push_back(call25Strike); |
124 | 0 | vols.push_back(call25Vol); |
125 | 0 | VannaVolga vannaVolga(x0Quote->value(), domesticTS_->discount(T_), foreignTS_->discount(T_), T_); |
126 | 0 | Interpolation interpolation = vannaVolga.interpolate(strikes.begin(), strikes.end(), vols.begin()); |
127 | 0 | interpolation.enableExtrapolation(); |
128 | 0 | const ext::shared_ptr<StrikedTypePayoff> payoff = |
129 | 0 | ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); |
130 | 0 | Real strikeVol = interpolation(payoff->strike()); |
131 | | |
132 | | //vanilla option price |
133 | 0 | Real forward = x0Quote->value() * foreignTS_->discount(T_) / domesticTS_->discount(T_); |
134 | 0 | Real vanillaOption = blackFormula(payoff->optionType(), payoff->strike(), |
135 | 0 | forward, |
136 | 0 | strikeVol * sqrt(T_), |
137 | 0 | domesticTS_->discount(T_)); |
138 | 0 | results_.additionalResults["Forward"] = forward; |
139 | 0 | results_.additionalResults["StrikeVol"] = strikeVol; |
140 | | |
141 | | //spot > barrier up&out 0 |
142 | 0 | if(x0Quote->value() >= arguments_.barrier && arguments_.barrierType == Barrier::UpOut){ |
143 | 0 | results_.value = 0.0; |
144 | 0 | results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
145 | 0 | results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
146 | 0 | results_.additionalResults["BarrierOutPrice"] = Real(0.0); |
147 | 0 | } |
148 | | //spot > barrier up&in vanilla |
149 | 0 | else if(x0Quote->value() >= arguments_.barrier && arguments_.barrierType == Barrier::UpIn){ |
150 | 0 | results_.value = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
151 | 0 | results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
152 | 0 | results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
153 | 0 | results_.additionalResults["BarrierOutPrice"] = Real(0.0); |
154 | 0 | } |
155 | | //spot < barrier down&out 0 |
156 | 0 | else if(x0Quote->value() <= arguments_.barrier && arguments_.barrierType == Barrier::DownOut){ |
157 | 0 | results_.value = 0.0; |
158 | 0 | results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
159 | 0 | results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
160 | 0 | results_.additionalResults["BarrierOutPrice"] = Real(0.0); |
161 | 0 | } |
162 | | //spot < barrier down&in vanilla |
163 | 0 | else if(x0Quote->value() <= arguments_.barrier && arguments_.barrierType == Barrier::DownIn){ |
164 | 0 | results_.value = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
165 | 0 | results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
166 | 0 | results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; |
167 | 0 | results_.additionalResults["BarrierOutPrice"] = Real(0.0); |
168 | 0 | } |
169 | 0 | else{ |
170 | | |
171 | | //set up BS barrier option pricing |
172 | | //only calculate out barrier option price |
173 | | // in barrier price = vanilla - out barrier |
174 | 0 | Barrier::Type barrierType; |
175 | 0 | if(arguments_.barrierType == Barrier::UpOut) |
176 | 0 | barrierType = arguments_.barrierType; |
177 | 0 | else if(arguments_.barrierType == Barrier::UpIn) |
178 | 0 | barrierType = Barrier::UpOut; |
179 | 0 | else if(arguments_.barrierType == Barrier::DownOut) |
180 | 0 | barrierType = arguments_.barrierType; |
181 | 0 | else |
182 | 0 | barrierType = Barrier::DownOut; |
183 | |
|
184 | 0 | BarrierOption barrierOption(barrierType, |
185 | 0 | arguments_.barrier, |
186 | 0 | arguments_.rebate, |
187 | 0 | ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff), |
188 | 0 | arguments_.exercise); |
189 | |
|
190 | 0 | barrierOption.setPricingEngine(engineBS); |
191 | | |
192 | | //BS price with atm vol |
193 | 0 | Real priceBS = barrierOption.NPV(); |
194 | |
|
195 | 0 | Real priceAtmCallBS = blackFormula(Option::Call,atmStrike, |
196 | 0 | forward, |
197 | 0 | atmVol_->value() * sqrt(T_), |
198 | 0 | domesticTS_->discount(T_)); |
199 | 0 | Real price25CallBS = blackFormula(Option::Call,call25Strike, |
200 | 0 | forward, |
201 | 0 | atmVol_->value() * sqrt(T_), |
202 | 0 | domesticTS_->discount(T_)); |
203 | 0 | Real price25PutBS = blackFormula(Option::Put,put25Strike, |
204 | 0 | forward, |
205 | 0 | atmVol_->value() * sqrt(T_), |
206 | 0 | domesticTS_->discount(T_)); |
207 | | |
208 | | //market price |
209 | 0 | Real priceAtmCallMkt = blackFormula(Option::Call,atmStrike, |
210 | 0 | forward, |
211 | 0 | atmVol_->value() * sqrt(T_), |
212 | 0 | domesticTS_->discount(T_)); |
213 | |
|
214 | 0 | Real price25CallMkt = blackFormula(Option::Call,call25Strike, |
215 | 0 | forward, |
216 | 0 | call25Vol * sqrt(T_), |
217 | 0 | domesticTS_->discount(T_)); |
218 | 0 | Real price25PutMkt = blackFormula(Option::Put,put25Strike, |
219 | 0 | forward, |
220 | 0 | put25Vol * sqrt(T_), |
221 | 0 | domesticTS_->discount(T_)); |
222 | | |
223 | | |
224 | | //Analytical Black Scholes formula for vanilla option |
225 | 0 | NormalDistribution norm; |
226 | 0 | Real d1atm = (std::log(forward/atmStrike) |
227 | 0 | + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); |
228 | 0 | Real vegaAtm_Analytical = x0Quote->value() * norm(d1atm) * sqrt(T_) * foreignTS_->discount(T_); |
229 | 0 | Real vannaAtm_Analytical = vegaAtm_Analytical/x0Quote->value() *(1.0 - d1atm/(atmVolQuote->value()*sqrt(T_))); |
230 | 0 | Real volgaAtm_Analytical = vegaAtm_Analytical * d1atm * (d1atm - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); |
231 | |
|
232 | 0 | Real d125call = (std::log(forward/call25Strike) |
233 | 0 | + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); |
234 | 0 | Real vega25Call_Analytical = x0Quote->value() * norm(d125call) * sqrt(T_) * foreignTS_->discount(T_); |
235 | 0 | Real vanna25Call_Analytical = vega25Call_Analytical/x0Quote->value() *(1.0 - d125call/(atmVolQuote->value()*sqrt(T_))); |
236 | 0 | Real volga25Call_Analytical = vega25Call_Analytical * d125call * (d125call - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); |
237 | |
|
238 | 0 | Real d125Put = (std::log(forward/put25Strike) |
239 | 0 | + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); |
240 | 0 | Real vega25Put_Analytical = x0Quote->value() * norm(d125Put) * sqrt(T_) * foreignTS_->discount(T_); |
241 | 0 | Real vanna25Put_Analytical = vega25Put_Analytical/x0Quote->value() *(1.0 - d125Put/(atmVolQuote->value()*sqrt(T_))); |
242 | 0 | Real volga25Put_Analytical = vega25Put_Analytical * d125Put * (d125Put - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); |
243 | | |
244 | | |
245 | | //BS vega |
246 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vega); |
247 | 0 | barrierOption.recalculate(); |
248 | 0 | Real vegaBarBS = (barrierOption.NPV() - priceBS)/sigmaShift_vega; |
249 | |
|
250 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() - sigmaShift_vega);//setback |
251 | | |
252 | | //BS volga |
253 | | |
254 | | //vegaBar2 |
255 | | //base NPV |
256 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_volga); |
257 | 0 | barrierOption.recalculate(); |
258 | 0 | Real priceBS2 = barrierOption.NPV(); |
259 | | |
260 | | //shifted npv |
261 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vega); |
262 | 0 | barrierOption.recalculate(); |
263 | 0 | Real vegaBarBS2 = (barrierOption.NPV() - priceBS2)/sigmaShift_vega; |
264 | 0 | Real volgaBarBS = (vegaBarBS2 - vegaBarBS)/sigmaShift_volga; |
265 | |
|
266 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() |
267 | 0 | - sigmaShift_volga |
268 | 0 | - sigmaShift_vega);//setback |
269 | | |
270 | | //BS Delta |
271 | | //base delta |
272 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//shift forth |
273 | 0 | barrierOption.recalculate(); |
274 | 0 | Real priceBS_delta1 = barrierOption.NPV(); |
275 | |
|
276 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() - 2 * spotShift_delta);//shift back |
277 | 0 | barrierOption.recalculate(); |
278 | 0 | Real priceBS_delta2 = barrierOption.NPV(); |
279 | |
|
280 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//set back |
281 | 0 | Real deltaBar1 = (priceBS_delta1 - priceBS_delta2)/(2.0*spotShift_delta); |
282 | | |
283 | | //shifted delta |
284 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vanna);//shift sigma |
285 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//shift forth |
286 | 0 | barrierOption.recalculate(); |
287 | 0 | priceBS_delta1 = barrierOption.NPV(); |
288 | |
|
289 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() - 2 * spotShift_delta);//shift back |
290 | 0 | barrierOption.recalculate(); |
291 | 0 | priceBS_delta2 = barrierOption.NPV(); |
292 | |
|
293 | 0 | ext::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//set back |
294 | 0 | Real deltaBar2 = (priceBS_delta1 - priceBS_delta2)/(2.0*spotShift_delta); |
295 | |
|
296 | 0 | Real vannaBarBS = (deltaBar2 - deltaBar1)/sigmaShift_vanna; |
297 | |
|
298 | 0 | ext::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() - sigmaShift_vanna);//set back |
299 | | |
300 | | //Matrix |
301 | 0 | Matrix A(3,3,0.0); |
302 | | |
303 | | //analytical |
304 | 0 | A[0][0] = vegaAtm_Analytical; |
305 | 0 | A[0][1] = vega25Call_Analytical; |
306 | 0 | A[0][2] = vega25Put_Analytical; |
307 | 0 | A[1][0] = vannaAtm_Analytical; |
308 | 0 | A[1][1] = vanna25Call_Analytical; |
309 | 0 | A[1][2] = vanna25Put_Analytical; |
310 | 0 | A[2][0] = volgaAtm_Analytical; |
311 | 0 | A[2][1] = volga25Call_Analytical; |
312 | 0 | A[2][2] = volga25Put_Analytical; |
313 | |
|
314 | 0 | Array b(3,0.0); |
315 | 0 | b[0] = vegaBarBS; |
316 | 0 | b[1] = vannaBarBS; |
317 | 0 | b[2] = volgaBarBS; |
318 | |
|
319 | 0 | Array q = inverse(A) * b; |
320 | | |
321 | | //touch probability |
322 | 0 | CumulativeNormalDistribution cnd; |
323 | 0 | Real mu = domesticTS_->zeroRate(T_, Continuous).rate() - foreignTS_->zeroRate(T_, Continuous).rate() - pow(atmVol_->value(), 2.0)/2.0; |
324 | 0 | Real h2 = (log(arguments_.barrier/x0Quote->value()) + mu*T_)/(atmVol_->value()*sqrt(T_)); |
325 | 0 | Real h2Prime = (log(x0Quote->value()/arguments_.barrier) + mu*T_)/(atmVol_->value()*sqrt(T_)); |
326 | 0 | Real probTouch = 0.0; |
327 | 0 | if(arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut) |
328 | 0 | probTouch = cnd(h2Prime) + pow(arguments_.barrier/x0Quote->value(), 2.0*mu/pow(atmVol_->value(), 2.0))*cnd(-h2); |
329 | 0 | else |
330 | 0 | probTouch = cnd(-h2Prime) + pow(arguments_.barrier/x0Quote->value(), 2.0*mu/pow(atmVol_->value(), 2.0))*cnd(h2); |
331 | 0 | Real p_survival = 1.0 - probTouch; |
332 | |
|
333 | 0 | Real lambda = p_survival ; |
334 | 0 | Real adjust = q[0]*(priceAtmCallMkt - priceAtmCallBS) |
335 | 0 | + q[1]*(price25CallMkt - price25CallBS) |
336 | 0 | + q[2]*(price25PutMkt - price25PutBS); |
337 | 0 | Real outPrice = priceBS + lambda*adjust;// |
338 | 0 | Real inPrice; |
339 | | |
340 | | //adapt Vanilla delta |
341 | 0 | if (adaptVanDelta_) { |
342 | 0 | outPrice += lambda*(bsPriceWithSmile_ - vanillaOption); |
343 | | //capfloored by (0, vanilla) |
344 | 0 | outPrice = std::max(0.0, std::min(bsPriceWithSmile_, outPrice)); |
345 | 0 | inPrice = bsPriceWithSmile_ - outPrice; |
346 | 0 | } |
347 | 0 | else{ |
348 | | //capfloored by (0, vanilla) |
349 | 0 | outPrice = std::max(0.0, std::min(vanillaOption, outPrice)); |
350 | 0 | inPrice = vanillaOption - outPrice; |
351 | 0 | } |
352 | |
|
353 | 0 | if(arguments_.barrierType == Barrier::DownOut || arguments_.barrierType == Barrier::UpOut) |
354 | 0 | results_.value = outPrice; |
355 | 0 | else |
356 | 0 | results_.value = inPrice; |
357 | 0 | results_.additionalResults["VanillaPrice"] = vanillaOption; |
358 | 0 | results_.additionalResults["BarrierInPrice"] = inPrice; |
359 | 0 | results_.additionalResults["BarrierOutPrice"] = outPrice; |
360 | 0 | results_.additionalResults["lambda"] = lambda; |
361 | 0 | } |
362 | 0 | } |
363 | | } |