Skip to content

Commit 835faf4

Browse files
authored
Merge pull request lballabio#1381.
Correct SVI parameter check to account for expiry
2 parents 5c6ce0d + 68fc2e8 commit 835faf4

10 files changed

+130
-5
lines changed

ql/experimental/volatility/sviinterpolation.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,18 @@ namespace QuantLib {
3333
namespace detail {
3434

3535
inline void checkSviParameters(const Real a, const Real b, const Real sigma,
36-
const Real rho, const Real m) {
36+
const Real rho, const Real m, const Time tte) {
3737
QL_REQUIRE(b >= 0.0, "b (" << b << ") must be non negative");
3838
QL_REQUIRE(std::fabs(rho) < 1.0, "rho (" << rho << ") must be in (-1,1)");
3939
QL_REQUIRE(sigma > 0.0, "sigma (" << sigma << ") must be positive");
4040
QL_REQUIRE(a + b * sigma * std::sqrt(1.0 - rho * rho) >= 0.0,
4141
"a + b sigma sqrt(1-rho^2) (a=" << a << ", b=" << b << ", sigma="
4242
<< sigma << ", rho=" << rho
4343
<< ") must be non negative");
44-
QL_REQUIRE(b * (1.0 + std::fabs(rho)) < 4.0,
45-
"b(1+|rho|) must be less than 4");
44+
if (tte != 0.0) {
45+
QL_REQUIRE(b * (1.0 + std::fabs(rho)) <= 4.0 / tte,
46+
"b(1+|rho|) must be less than or equal to 4/T");
47+
}
4648
}
4749

4850
inline Real sviTotalVariance(const Real a, const Real b, const Real sigma,

ql/experimental/volatility/svismilesection.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ namespace QuantLib {
3737
}
3838

3939
void SviSmileSection::init() {
40+
QL_REQUIRE(exerciseTime() > 0.0, "svi expects a strictly positive expiry time");
4041
QL_REQUIRE(params_.size() == 5,
4142
"svi expects 5 parameters (a,b,sigma,rho,m) but ("
4243
<< params_.size() << ") given");
43-
detail::checkSviParameters(params_[0], params_[1], params_[2], params_[3],
44-
params_[4]);
44+
detail::checkSviParameters(params_[0], params_[1], params_[2], params_[3], params_[4],
45+
exerciseTime());
4546
}
4647

4748
Volatility SviSmileSection::volatilityImpl(Rate strike) const {

ql/experimental/volatility/svismilesection.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030

3131
namespace QuantLib {
3232

33+
//! Stochastic Volatility Inspired Smile Section
34+
/*! \test the correctness of the result is tested by checking it
35+
against known good values.
36+
*/
3337
class SviSmileSection : public SmileSection {
3438

3539
public:

test-suite/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ set(QL_TEST_SOURCES
141141
squarerootclvmodel.cpp
142142
stats.cpp
143143
subperiodcoupons.cpp
144+
svivolatility.cpp
144145
swap.cpp
145146
swapforwardmappings.cpp
146147
swaption.cpp
@@ -310,6 +311,7 @@ set(QL_TEST_HEADERS
310311
squarerootclvmodel.hpp
311312
stats.hpp
312313
subperiodcoupons.hpp
314+
svivolatility.hpp
313315
swap.hpp
314316
swapforwardmappings.hpp
315317
swaption.hpp

test-suite/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ QL_TEST_SRCS = \
142142
squarerootclvmodel.cpp \
143143
stats.cpp \
144144
subperiodcoupons.cpp \
145+
svivolatility.cpp \
145146
swap.cpp \
146147
swapforwardmappings.cpp \
147148
swaption.cpp \
@@ -309,6 +310,7 @@ QL_TEST_HDRS = \
309310
squarerootclvmodel.hpp \
310311
stats.hpp \
311312
subperiodcoupons.hpp \
313+
svivolatility.hpp \
312314
swap.hpp \
313315
swapforwardmappings.hpp \
314316
swaption.hpp \

test-suite/quantlibtestsuite.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
#include "swingoption.hpp"
182182
#include "stats.hpp"
183183
#include "subperiodcoupons.hpp"
184+
#include "svivolatility.hpp"
184185
#include "swap.hpp"
185186
#include "swapforwardmappings.hpp"
186187
#include "swaption.hpp"
@@ -520,6 +521,7 @@ test_suite* init_unit_test_suite(int, char* []) {
520521
test->add(RiskNeutralDensityCalculatorTest::experimental(speed));
521522
test->add(SpreadOptionTest::suite());
522523
test->add(SquareRootCLVModelTest::experimental());
524+
test->add(SviVolatilityTest::experimental());
523525
test->add(SwingOptionTest::suite(speed));
524526
test->add(TwoAssetBarrierOptionTest::suite());
525527
test->add(TwoAssetCorrelationOptionTest::suite());

test-suite/svivolatility.cpp

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/*
4+
Copyright (C) 2022 Skandinaviska Enskilda Banken AB (publ)
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+
<[email protected]>. 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 "svivolatility.hpp"
21+
#include "utilities.hpp"
22+
#include <ql/experimental/volatility/svismilesection.hpp>
23+
24+
using namespace QuantLib;
25+
using namespace boost::unit_test_framework;
26+
27+
28+
void SviVolatilityTest::testSviSmileSection() {
29+
30+
BOOST_TEST_MESSAGE("Testing SviSmileSection construction...");
31+
32+
Date today = Settings::instance().evaluationDate();
33+
34+
// Test time based constructor
35+
Time tte = 11.0 / 365;
36+
Real forward = 123.45;
37+
Real a = -2.21;
38+
Real b = 7.61;
39+
Real sigma = 0.337;
40+
Real rho = 0.439;
41+
Real m = 0.193;
42+
std::vector<Real> sviParameters = {a, b, sigma, rho, m};
43+
// Compute the strike that yields x (log-moneyness) equal to m,
44+
// this simplifies the variance expression to a+b*sigma so we can test the correctness
45+
// against the input parameters
46+
Real strike = forward * std::exp(m);
47+
ext::shared_ptr<SviSmileSection> time_section;
48+
49+
BOOST_CHECK_NO_THROW(time_section =
50+
ext::make_shared<SviSmileSection>(tte, forward, sviParameters));
51+
BOOST_CHECK_EQUAL(time_section->atmLevel(), forward);
52+
BOOST_CHECK_CLOSE(time_section->variance(strike), a + b * sigma, 1E-10);
53+
54+
// Test date based constructor
55+
Date date = today + Period(11, Days);
56+
ext::shared_ptr<SviSmileSection> date_section;
57+
58+
BOOST_CHECK_NO_THROW(date_section =
59+
ext::make_shared<SviSmileSection>(date, forward, sviParameters));
60+
61+
BOOST_CHECK_EQUAL(date_section->atmLevel(), forward);
62+
BOOST_CHECK_CLOSE(date_section->variance(strike), a + b * sigma, 1E-10);
63+
}
64+
65+
test_suite* SviVolatilityTest::experimental() {
66+
auto* suite = BOOST_TEST_SUITE("SVI volatility tests");
67+
suite->add(QUANTLIB_TEST_CASE(&SviVolatilityTest::testSviSmileSection));
68+
return suite;
69+
}

test-suite/svivolatility.hpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/*
4+
Copyright (C) 2022 Skandinaviska Enskilda Banken AB (publ)
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+
<[email protected]>. 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+
#ifndef quantlib_test_svi_volatility_hpp
21+
#define quantlib_test_svi_volatility_hpp
22+
23+
#include <boost/test/unit_test.hpp>
24+
25+
/* remember to document new and/or updated tests in the Doxygen
26+
comment block of the corresponding class */
27+
28+
class SviVolatilityTest {
29+
public:
30+
static void testSviSmileSection();
31+
static boost::unit_test_framework::test_suite* experimental();
32+
};
33+
34+
35+
#endif

test-suite/testsuite.vcxproj

+2
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@
777777
<ClCompile Include="squarerootclvmodel.cpp" />
778778
<ClCompile Include="stats.cpp" />
779779
<ClCompile Include="subperiodcoupons.cpp" />
780+
<ClCompile Include="svivolatility.cpp" />
780781
<ClCompile Include="swap.cpp" />
781782
<ClCompile Include="swapforwardmappings.cpp" />
782783
<ClCompile Include="swaption.cpp" />
@@ -946,6 +947,7 @@
946947
<ClInclude Include="squarerootclvmodel.hpp" />
947948
<ClInclude Include="stats.hpp" />
948949
<ClInclude Include="subperiodcoupons.hpp" />
950+
<ClInclude Include="svivolatility.hpp" />
949951
<ClInclude Include="swap.hpp" />
950952
<ClInclude Include="swapforwardmappings.hpp" />
951953
<ClInclude Include="swaption.hpp" />

test-suite/testsuite.vcxproj.filters

+6
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@
504504
<ClCompile Include="bondforward.cpp">
505505
<Filter>Source Files</Filter>
506506
</ClCompile>
507+
<ClCompile Include="svivolatility.cpp">
508+
<Filter>Source Files</Filter>
509+
</ClCompile>
507510
</ItemGroup>
508511
<ItemGroup>
509512
<ClInclude Include="americanoption.hpp">
@@ -1007,5 +1010,8 @@
10071010
<ClInclude Include="bondforward.hpp">
10081011
<Filter>Header Files</Filter>
10091012
</ClInclude>
1013+
<ClInclude Include="svivolatility.hpp">
1014+
<Filter>Header Files</Filter>
1015+
</ClInclude>
10101016
</ItemGroup>
10111017
</Project>

0 commit comments

Comments
 (0)