1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2014 Peter Caspers
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/volatility/noarbsabrsmilesection.hpp>
21#include <ql/pricingengines/blackformula.hpp>
22#include <ql/termstructures/volatility/sabr.hpp>
23#include <utility>
24
25
26namespace QuantLib {
27
28 NoArbSabrSmileSection::NoArbSabrSmileSection(Time timeToExpiry,
29 Rate forward,
30 std::vector<Real> sabrParams,
31 Real shift,
32 VolatilityType volatilityType)
33 : SmileSection(timeToExpiry, DayCounter(), volatilityType), forward_(forward), params_(std::move(sabrParams)),
34 shift_(shift) {
35 init();
36 }
37
38 NoArbSabrSmileSection::NoArbSabrSmileSection(
39 const Date& d, Rate forward, std::vector<Real> sabrParams, const DayCounter& dc, Real shift, VolatilityType volatilityType)
40 : SmileSection(d, dc, Date(), volatilityType), forward_(forward), params_(std::move(sabrParams)),
41 shift_(shift) {
42 init();
43 }
44
45void NoArbSabrSmileSection::init() {
46 QL_REQUIRE(params_.size() >= 4,
47 "sabr expects 4 parameters (alpha,beta,nu,rho) but ("
48 << params_.size() << ") given");
49 QL_REQUIRE(forward_ > 0.0, "forward (" << forward_ << ") must be positive");
50 QL_REQUIRE(
51 shift_ == 0.0,
52 "shift (" << shift_
53 << ") must be zero, other shifts are not implemented yet");
54 model_ =
55 ext::make_shared<NoArbSabrModel>(args: exerciseTime(), args&: forward_, args&: params_[0],
56 args&: params_[1], args&: params_[2], args&: params_[3]);
57}
58
59Real NoArbSabrSmileSection::optionPrice(Rate strike, Option::Type type,
60 Real discount) const {
61 Real call = model_->optionPrice(strike);
62 return discount *
63 (type == Option::Call ? call : call - (forward_ - strike));
64}
65
66Real NoArbSabrSmileSection::digitalOptionPrice(Rate strike, Option::Type type,
67 Real discount, Real) const {
68 Real call = model_->digitalOptionPrice(strike);
69 return discount * (type == Option::Call ? call : 1.0 - call);
70}
71
72Real NoArbSabrSmileSection::density(Rate strike, Real discount, Real) const {
73 return discount * model_->density(strike);
74}
75
76Real NoArbSabrSmileSection::volatilityImpl(Rate strike) const {
77
78 Real impliedVol = 0.0;
79 try {
80 Option::Type type;
81 if (strike >= forward_)
82 type = Option::Call;
83 else
84 type = Option::Put;
85 impliedVol =
86 blackFormulaImpliedStdDev(optionType: type, strike, forward: forward_,
87 blackPrice: optionPrice(strike, type, discount: 1.0), discount: 1.0) /
88 std::sqrt(x: exerciseTime());
89 } catch (...) {
90 }
91 if (impliedVol == 0.0)
92 // fall back on Hagan 2002 expansion
93 impliedVol =
94 unsafeSabrVolatility(strike, forward: forward_, expiryTime: exerciseTime(), alpha: params_[0],
95 beta: params_[1], nu: params_[2], rho: params_[3], volatilityType: volatilityType());
96
97 return impliedVol;
98}
99} // namespace QuantLib
100

source code of quantlib/ql/experimental/volatility/noarbsabrsmilesection.cpp