24#ifndef quantlib_vanna_volga_double_barrier_engine_hpp
25#define quantlib_vanna_volga_double_barrier_engine_hpp
47 template <
class DoubleBarrierEngine>
50 DoubleBarrierOption::results> {
59 const bool adaptVanDelta =
false,
60 const Real bsPriceWithSmile = 0.0,
69 "25 delta put is required by vanna volga method");
71 "25 delta call is required by vanna volga method");
75 "Maturity of 3 vols are not the same");
92 const Real sigmaShift_vega = 0.001;
93 const Real sigmaShift_volga = 0.0001;
94 const Real spotShift_delta = 0.0001 *
spotFX_->value();
95 const Real sigmaShift_vanna = 0.0001;
99 "Only same type barrier supported");
102 ext::make_shared<SimpleQuote>(
spotFX_->value()));
104 ext::make_shared<SimpleQuote>(
atmVol_->value()));
106 ext::shared_ptr<BlackVolTermStructure> blackVolTS =
110 ext::shared_ptr<BlackScholesMertonProcess> stochProcess =
111 ext::make_shared<BlackScholesMertonProcess>(
115 ext::shared_ptr<PricingEngine> engineBS =
116 ext::make_shared<DoubleBarrierEngine>(stochProcess,
series_);
136 std::vector<Real> strikes;
137 std::vector<Real> vols;
138 strikes.push_back(put25Strike);
139 vols.push_back(put25Vol);
140 strikes.push_back(atmStrike);
141 vols.push_back(
atmVol_->value());
142 strikes.push_back(call25Strike);
143 vols.push_back(call25Vol);
147 vannaVolga.
interpolate(strikes.begin(), strikes.end(), vols.begin());
149 const ext::shared_ptr<StrikedTypePayoff>
payoff =
150 ext::dynamic_pointer_cast<StrikedTypePayoff>(
arguments_.payoff);
151 Real strikeVol = interpolation(
payoff->strike());
184 ext::shared_ptr<StrikedTypePayoff>
payoff =
185 ext::static_pointer_cast<StrikedTypePayoff>(
arguments_.payoff);
193 Real priceBS = doubleBarrierOption.
NPV();
226 0.5 * std::pow(atmVolQuote->value(), 2.0) *
T_) /
227 (atmVolQuote->value() * sqrt(
T_));
228 Real vegaAtm_Analytical =
229 x0Quote->value() * norm(d1atm) * sqrt(
T_) *
foreignTS_->discount(
T_);
230 Real vannaAtm_Analytical = vegaAtm_Analytical / x0Quote->value() *
231 (1.0 - d1atm / (atmVolQuote->value() * sqrt(
T_)));
232 Real volgaAtm_Analytical = vegaAtm_Analytical * d1atm *
233 (d1atm - atmVolQuote->value() * sqrt(
T_)) /
234 atmVolQuote->value();
238 0.5 * std::pow(atmVolQuote->value(), 2.0) *
T_) /
239 (atmVolQuote->value() * sqrt(
T_));
240 Real vega25Call_Analytical =
241 x0Quote->value() * norm(d125call) * sqrt(
T_) *
foreignTS_->discount(
T_);
242 Real vanna25Call_Analytical =
243 vega25Call_Analytical / x0Quote->value() *
244 (1.0 - d125call / (atmVolQuote->value() * sqrt(
T_)));
245 Real volga25Call_Analytical = vega25Call_Analytical * d125call *
246 (d125call - atmVolQuote->value() * sqrt(
T_)) /
247 atmVolQuote->value();
251 0.5 * std::pow(atmVolQuote->value(), 2.0) *
T_) /
252 (atmVolQuote->value() * sqrt(
T_));
253 Real vega25Put_Analytical =
254 x0Quote->value() * norm(d125Put) * sqrt(
T_) *
foreignTS_->discount(
T_);
255 Real vanna25Put_Analytical =
256 vega25Put_Analytical / x0Quote->value() *
257 (1.0 - d125Put / (atmVolQuote->value() * sqrt(
T_)));
258 Real volga25Put_Analytical = vega25Put_Analytical * d125Put *
259 (d125Put - atmVolQuote->value() * sqrt(
T_)) /
260 atmVolQuote->value();
264 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
265 ->setValue(atmVolQuote->value() + sigmaShift_vega);
267 Real vegaBarBS = (doubleBarrierOption.
NPV() - priceBS) / sigmaShift_vega;
268 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
269 ->setValue(atmVolQuote->value() - sigmaShift_vega);
275 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
276 ->setValue(atmVolQuote->value() + sigmaShift_volga);
278 Real priceBS2 = doubleBarrierOption.
NPV();
281 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
282 ->setValue(atmVolQuote->value() + sigmaShift_vega);
284 Real vegaBarBS2 = (doubleBarrierOption.
NPV() - priceBS2) / sigmaShift_vega;
285 Real volgaBarBS = (vegaBarBS2 - vegaBarBS) / sigmaShift_volga;
286 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
287 ->setValue(atmVolQuote->value() - sigmaShift_volga -
292 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
293 ->setValue(x0Quote->value() + spotShift_delta);
295 Real priceBS_delta1 = doubleBarrierOption.
NPV();
297 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
298 ->setValue(x0Quote->value() - 2 * spotShift_delta);
300 Real priceBS_delta2 = doubleBarrierOption.
NPV();
302 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
303 ->setValue(x0Quote->value() + spotShift_delta);
304 Real deltaBar1 = (priceBS_delta1 - priceBS_delta2) / (2.0 * spotShift_delta);
307 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
308 ->setValue(atmVolQuote->value() + sigmaShift_vanna);
310 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
311 ->setValue(x0Quote->value() + spotShift_delta);
313 priceBS_delta1 = doubleBarrierOption.
NPV();
315 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
316 ->setValue(x0Quote->value() - 2 * spotShift_delta);
318 priceBS_delta2 = doubleBarrierOption.
NPV();
320 ext::static_pointer_cast<SimpleQuote>(x0Quote.
currentLink())
321 ->setValue(x0Quote->value() + spotShift_delta);
322 Real deltaBar2 = (priceBS_delta1 - priceBS_delta2) / (2.0 * spotShift_delta);
324 Real vannaBarBS = (deltaBar2 - deltaBar1) / sigmaShift_vanna;
326 ext::static_pointer_cast<SimpleQuote>(atmVolQuote.
currentLink())
327 ->setValue(atmVolQuote->value() - sigmaShift_vanna);
333 A[0][0] = vegaAtm_Analytical;
334 A[0][1] = vega25Call_Analytical;
335 A[0][2] = vega25Put_Analytical;
336 A[1][0] = vannaAtm_Analytical;
337 A[1][1] = vanna25Call_Analytical;
338 A[1][2] = vanna25Put_Analytical;
339 A[2][0] = volgaAtm_Analytical;
340 A[2][1] = volga25Call_Analytical;
341 A[2][2] = volga25Put_Analytical;
357 1.0 /
atmVol_->value() * std::log(H / x0Quote->value()) / std::sqrt(
T_);
359 1.0 /
atmVol_->value() * std::log(L / x0Quote->value()) / std::sqrt(
T_);
362 Real doubleNoTouch = 0.0;
364 Real e_minus = 2 * j * (h - l) - theta_tilt_minus;
366 std::exp(-2.0 * j * theta_tilt_minus * (h - l)) *
367 (cnd(h + e_minus) - cnd(l + e_minus)) -
368 std::exp(-2.0 * j * theta_tilt_minus * (h - l) +
369 2.0 * theta_tilt_minus * h) *
370 (cnd(h - 2.0 * h + e_minus) - cnd(l - 2.0 * h + e_minus));
373 Real p_survival = doubleNoTouch;
375 Real lambda = p_survival;
376 Real adjust =
q[0] * (priceAtmCallMkt - priceAtmCallBS) +
377 q[1] * (price25CallMkt - price25CallBS) +
378 q[2] * (price25PutMkt - price25PutBS);
379 Real outPrice = priceBS + lambda * adjust;
390 outPrice = std::max(0.0, std::min(vanillaOption, outPrice));
391 inPrice = vanillaOption - outPrice;
Analytic barrier option engines.
Black constant volatility, no time dependence, no strike dependence.
Black-Scholes formula delta calculator class.
Actual/365 (Fixed) day count convention.
1-D array used in linear algebra.
Black delta calculator class.
Real atmStrike(DeltaVolQuote::AtmType atmT) const
Real strikeFromDelta(Real delta) const
Cumulative normal distribution function.
DoubleBarrier::Type barrierType
Double Barrier option on a single asset.
template base class for option pricing engines
DoubleBarrierOption::results results_
DoubleBarrierOption::arguments arguments_
Shared handle to an observable.
const ext::shared_ptr< T > & currentLink() const
dereferencing
std::map< std::string, ext::any > additionalResults
Real NPV() const
returns the net present value of the instrument.
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
base class for 1-D interpolations.
Matrix used in linear algebra.
Normal distribution function.
Calendar for reproducing theoretical calculations.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
static Settings & instance()
access to the unique instance
Vanna Volga double-barrier option engine.
const bool adaptVanDelta_
const Handle< Quote > spotFX_
const Handle< YieldTermStructure > foreignTS_
const Handle< DeltaVolQuote > vol25Put_
VannaVolgaDoubleBarrierEngine(Handle< DeltaVolQuote > atmVol, Handle< DeltaVolQuote > vol25Put, Handle< DeltaVolQuote > vol25Call, Handle< Quote > spotFX, Handle< YieldTermStructure > domesticTS, Handle< YieldTermStructure > foreignTS, const bool adaptVanDelta=false, const Real bsPriceWithSmile=0.0, int series=5)
const Handle< DeltaVolQuote > vol25Call_
void calculate() const override
const Handle< YieldTermStructure > domesticTS_
const Real bsPriceWithSmile_
const Handle< DeltaVolQuote > atmVol_
VannaVolga-interpolation factory and traits
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
Class for the quotation of delta vs vol.
double Barrier european option on a single asset
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
ext::function< Real(Real)> b
Real Time
continuous quantity with 1-year units
ext::shared_ptr< QuantLib::Payoff > payoff
matrix used in linear algebra.
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)
Matrix inverse(const Matrix &m)
Calendar for reproducing theoretical calculations.
ext::shared_ptr< YieldTermStructure > q
Vanna/Volga interpolation between discrete points.