Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
strippedoptionletadapter2.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/test/unit_test.hpp>
20#include <ql/quotes/simplequote.hpp>
21#include <ql/termstructures/volatility/optionlet/strippedoptionlet.hpp>
22#include <ql/time/calendars/unitedstates.hpp>
25
26using namespace QuantExt;
27using namespace QuantLib;
28using namespace boost::unit_test_framework;
29
31using std::vector;
32
33namespace {
34
35// Fixture to create an optionlet surface that is used in the tests
36class F : public TopLevelFixture {
37public:
38 Date asof;
39 vector<Date> expiries;
40 vector<Rate> strikes;
41 DayCounter dc;
42 vector<vector<Handle<Quote> > > vols;
43 QuantLib::ext::shared_ptr<StrippedOptionlet> optionletSurface;
44
45 F() : expiries(2), strikes(2), dc(Actual365Fixed()), vols(2) {
46
47 // Set the evaluation date
48 asof = Date(17, Apr, 2019);
49 Settings::instance().evaluationDate() = asof;
50
51 // Inputs for the optionlet surface
52 Natural settlementDays = 2;
53 UnitedStates calendar(UnitedStates::Settlement);
54 BusinessDayConvention bdc = Following;
55 QuantLib::ext::shared_ptr<IborIndex> dummyIborIndex;
56 VolatilityType type = Normal;
57
58 expiries[0] = Date(17, Apr, 2020);
59 expiries[1] = Date(19, Apr, 2021);
60
61 strikes[0] = 0.02;
62 strikes[1] = 0.04;
63
64 // clang-format off
65 vols[0].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0091)));
66 vols[0].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0092)));
67 vols[1].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0070)));
68 vols[1].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0088)));
69 // clang-format on
70
71 // Create the optionlet surface
72 optionletSurface = QuantLib::ext::make_shared<StrippedOptionlet>(settlementDays, calendar, bdc, dummyIborIndex,
73 expiries, strikes, vols, dc, type);
74 }
75
76 ~F() {}
77};
78
79} // namespace
80BOOST_FIXTURE_TEST_SUITE(QuantExtTestSuite, TopLevelFixture)
81
82BOOST_AUTO_TEST_SUITE(StrippedOptionletAdapterTwoTests)
83
84BOOST_FIXTURE_TEST_CASE(testFlatExtrapAfterLastExpiry, F) {
85
86 // Set up optionlet adapter with flat extrapolation
87 QuantLib::ext::shared_ptr<StrippedOptionletAdapter2> adapter =
88 QuantLib::ext::make_shared<StrippedOptionletAdapter2>(optionletSurface, true);
89
90 // Pick a date 1Y after the max date
91 Date testDate = expiries.back() + 1 * Years;
92
93 // Check flat extrapolation on the pillar strikes
94 for (Size i = 0; i < strikes.size(); i++) {
95 Volatility testVol = adapter->volatility(testDate, strikes[i], true);
96 BOOST_CHECK_CLOSE(testVol, vols.back()[i]->value(), 1e-12);
97 }
98
99 // Check flat extrapolation below first strike
100 Volatility testVol = adapter->volatility(testDate, strikes.front() / 2.0, true);
101 BOOST_CHECK_CLOSE(testVol, vols.back().front()->value(), 1e-12);
102
103 // Check flat extrapolation above last strike
104 testVol = adapter->volatility(testDate, 2.0 * strikes.back(), true);
105 BOOST_CHECK_CLOSE(testVol, vols.back().back()->value(), 1e-12);
106
107 // Check flat extrapolation between two strikes
108 Rate avgStrike = (strikes[0] + strikes[1]) / 2.0;
109 Volatility expectedVol = (vols.back()[0]->value() + vols.back()[1]->value()) / 2.0;
110 testVol = adapter->volatility(testDate, avgStrike, true);
111 BOOST_CHECK_CLOSE(testVol, expectedVol, 1e-12);
112}
113
114BOOST_FIXTURE_TEST_CASE(testFlatExtrapBetweenFirstLastExpiry, F) {
115
116 // Set up optionlet adapter with flat extrapolation
117 QuantLib::ext::shared_ptr<StrippedOptionletAdapter2> adapter =
118 QuantLib::ext::make_shared<StrippedOptionletAdapter2>(optionletSurface, true);
119
120 // Check flat extrapolation on expiry pillars
121 for (Size i = 0; i < expiries.size(); i++) {
122 // Below first strike
123 Volatility testVol = adapter->volatility(expiries[i], strikes.front() / 2.0, true);
124 BOOST_CHECK_CLOSE(testVol, vols[i].front()->value(), 1e-12);
125 // Above last strike
126 testVol = adapter->volatility(expiries[i], 2.0 * strikes.back(), true);
127 BOOST_CHECK_CLOSE(testVol, vols[i].back()->value(), 1e-12);
128 }
129
130 // Pick a date between first expiry and last expiry
131 Size numDays = dc.dayCount(expiries.front(), expiries.back()) / 2;
132 Date testDate = expiries.front() + numDays * Days;
133
134 // Check flat extrapolation below first strike
135 Volatility testVol = adapter->volatility(testDate, strikes.front() / 2.0, true);
136 Volatility expectedVol = adapter->volatility(testDate, strikes.front(), true);
137 BOOST_CHECK_CLOSE(testVol, expectedVol, 1e-12);
138
139 // Check flat extrapolation above last strike
140 testVol = adapter->volatility(testDate, 2.0 * strikes.back(), true);
141 expectedVol = adapter->volatility(testDate, strikes.back(), true);
142 BOOST_CHECK_CLOSE(testVol, expectedVol, 1e-12);
143}
144
145BOOST_FIXTURE_TEST_CASE(testFlatExtrapBeforeFirstExpiry, F) {
146
147 // Set up optionlet adapter with flat extrapolation
148 QuantLib::ext::shared_ptr<StrippedOptionletAdapter2> adapter =
149 QuantLib::ext::make_shared<StrippedOptionletAdapter2>(optionletSurface, true);
150
151 // Pick a date between evaluation date and first expiry
152 Size numDays = dc.dayCount(asof, expiries.front()) / 2;
153 Date testDate = asof + numDays * Days;
154
155 // Check flat extrapolation on the pillar strikes
156 for (Size i = 0; i < strikes.size(); i++) {
157 Volatility testVol = adapter->volatility(testDate, strikes[i], true);
158 BOOST_CHECK_CLOSE(testVol, vols.front()[i]->value(), 1e-12);
159 }
160
161 // Check flat extrapolation below first strike
162 Volatility testVol = adapter->volatility(testDate, strikes.front() / 2.0, true);
163 BOOST_CHECK_CLOSE(testVol, vols.front().front()->value(), 1e-12);
164
165 // Check flat extrapolation above last strike
166 testVol = adapter->volatility(testDate, 2.0 * strikes.back(), true);
167 BOOST_CHECK_CLOSE(testVol, vols.front().back()->value(), 1e-12);
168
169 // Check flat extrapolation between two strikes
170 Rate avgStrike = (strikes[0] + strikes[1]) / 2.0;
171 Volatility expectedVol = (vols.front()[0]->value() + vols.front()[1]->value()) / 2.0;
172 testVol = adapter->volatility(testDate, avgStrike, true);
173 BOOST_CHECK_CLOSE(testVol, expectedVol, 1e-12);
174}
175
176BOOST_AUTO_TEST_SUITE_END()
177
178BOOST_AUTO_TEST_SUITE_END()
StrippedOptionlet Adapter (with a deeper update method, linear interpolation and optional flat extrap...
vector< Real > strikes
BOOST_FIXTURE_TEST_CASE(testFlatExtrapAfterLastExpiry, F)
Fixture that can be used at top level.