Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
bfrrvolsurface.cpp File Reference
#include "toplevelfixture.hpp"
#include <qle/termstructures/blackdeltautilities.hpp>
#include <qle/termstructures/blackvolsurfacebfrr.hpp>
#include <ql/experimental/fx/blackdeltacalculator.hpp>
#include <ql/pricingengines/blackformula.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/nullcalendar.hpp>
#include <ql/time/daycounters/actual365fixed.hpp>
#include <boost/make_shared.hpp>
#include <boost/test/unit_test.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testSmileBF)
 
 BOOST_AUTO_TEST_CASE (testBrokerBF)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/2]

BOOST_AUTO_TEST_CASE ( testSmileBF  )

Definition at line 69 of file bfrrvolsurface.cpp.

69 {
70
71 BOOST_TEST_MESSAGE("Testing bf/rr vol surface with smile bf quotes...");
72
73 Real tol1 = 1E-5;
74
75 auto vol1 = QuantLib::ext::make_shared<BlackVolatilitySurfaceBFRR>(
76 refDate, dates, deltas, bfQuotes, rrQuotes, atmQuotes, dc, cal, spot, spotDays, cal, domesticTS, foreignTS, dt,
77 at, switchTenor, ltdt, ltat, rrInFavorOf, false, smileInterpolation);
78
79 Real t1 = vol1->timeFromReference(dates[0]);
80 Real domDisc1 = domesticTS->discount(dates[0] + spotDays) / domesticTS->discount(refDate + spotDays);
81 Real forDisc1 = foreignTS->discount(dates[0] + spotDays) / foreignTS->discount(refDate + spotDays);
82 Real k1_1_10p = getStrikeFromDelta(Option::Put, -deltas[0], dt, spot->value(), domDisc1, forDisc1, vol1, t1);
83 Real k1_1_25p = getStrikeFromDelta(Option::Put, -deltas[1], dt, spot->value(), domDisc1, forDisc1, vol1, t1);
84 Real k1_1_atm = getAtmStrike(dt, at, spot->value(), domDisc1, forDisc1, vol1, t1);
85 Real k1_1_25c = getStrikeFromDelta(Option::Call, deltas[1], dt, spot->value(), domDisc1, forDisc1, vol1, t1);
86 Real k1_1_10c = getStrikeFromDelta(Option::Call, deltas[0], dt, spot->value(), domDisc1, forDisc1, vol1, t1);
87
88 BOOST_CHECK_SMALL(vol1->blackVol(dates[0], k1_1_10p) - (atmQuotes[0] + bfQuotes[0][0] - 0.5 * rrQuotes[0][0]),
89 tol1);
90 BOOST_CHECK_SMALL(vol1->blackVol(dates[0], k1_1_25p) - (atmQuotes[0] + bfQuotes[0][1] - 0.5 * rrQuotes[0][1]),
91 tol1);
92 BOOST_CHECK_SMALL(vol1->blackVol(dates[0], k1_1_atm) - atmQuotes[0], tol1);
93 BOOST_CHECK_SMALL(vol1->blackVol(dates[0], k1_1_25c) - (atmQuotes[0] + bfQuotes[0][1] + 0.5 * rrQuotes[0][1]),
94 tol1);
95 BOOST_CHECK_SMALL(vol1->blackVol(dates[0], k1_1_10c) - (atmQuotes[0] + bfQuotes[0][0] + 0.5 * rrQuotes[0][0]),
96 tol1);
97
98 Real t2 = vol1->timeFromReference(dates[1]);
99 Real domDisc2 = domesticTS->discount(dates[1] + spotDays) / domesticTS->discount(refDate + spotDays);
100 Real forDisc2 = foreignTS->discount(dates[1] + spotDays) / foreignTS->discount(refDate + spotDays);
101 Real k1_2_10p = getStrikeFromDelta(Option::Put, -deltas[0], ltdt, spot->value(), domDisc2, forDisc2, vol1, t2);
102 Real k1_2_25p = getStrikeFromDelta(Option::Put, -deltas[1], ltdt, spot->value(), domDisc2, forDisc2, vol1, t2);
103 Real k1_2_atm = getAtmStrike(ltdt, ltat, spot->value(), domDisc2, forDisc2, vol1, t2);
104 Real k1_2_25c = getStrikeFromDelta(Option::Call, deltas[1], ltdt, spot->value(), domDisc2, forDisc2, vol1, t2);
105 Real k1_2_10c = getStrikeFromDelta(Option::Call, deltas[0], ltdt, spot->value(), domDisc2, forDisc2, vol1, t2);
106
107 BOOST_CHECK_SMALL(vol1->blackVol(dates[1], k1_2_10p) - (atmQuotes[1] + bfQuotes[1][0] - 0.5 * rrQuotes[1][0]),
108 tol1);
109 BOOST_CHECK_SMALL(vol1->blackVol(dates[1], k1_2_25p) - (atmQuotes[1] + bfQuotes[1][1] - 0.5 * rrQuotes[1][1]),
110 tol1);
111 BOOST_CHECK_SMALL(vol1->blackVol(dates[1], k1_2_atm) - atmQuotes[1], tol1);
112 BOOST_CHECK_SMALL(vol1->blackVol(dates[1], k1_2_25c) - (atmQuotes[1] + bfQuotes[1][1] + 0.5 * rrQuotes[1][1]),
113 tol1);
114 BOOST_CHECK_SMALL(vol1->blackVol(dates[1], k1_2_10c) - (atmQuotes[1] + bfQuotes[1][0] + 0.5 * rrQuotes[1][0]),
115 tol1);
116}
Real getStrikeFromDelta(Option::Type optionType, Real delta, DeltaVolQuote::DeltaType dt, Real spot, Real domDiscount, Real forDiscount, QuantLib::ext::shared_ptr< BlackVolTermStructure > vol, Real t, Real accuracy, Size maxIterations)
Real getAtmStrike(DeltaVolQuote::DeltaType dt, DeltaVolQuote::AtmType at, Real spot, Real domDiscount, Real forDiscount, QuantLib::ext::shared_ptr< BlackVolTermStructure > vol, Real t, Real accuracy, Size maxIterations)
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/2]

BOOST_AUTO_TEST_CASE ( testBrokerBF  )

Definition at line 118 of file bfrrvolsurface.cpp.

118 {
119
120 BOOST_TEST_MESSAGE("Testing bf/rr vol surface with broker bf quotes...");
121
122 Real tol1 = 1E-5;
123 Real tol2 = 1E-5;
124
125 auto vol2 = QuantLib::ext::make_shared<BlackVolatilitySurfaceBFRR>(
126 refDate, dates, deltas, bfQuotes, rrQuotes, atmQuotes, dc, cal, spot, spotDays, cal, domesticTS, foreignTS, dt,
127 at, switchTenor, ltdt, ltat, rrInFavorOf, true, smileInterpolation);
128
129 Real t1 = vol2->timeFromReference(dates[0]);
130 Real domDisc1 = domesticTS->discount(dates[0] + spotDays) / domesticTS->discount(refDate + spotDays);
131 Real forDisc1 = foreignTS->discount(dates[0] + spotDays) / foreignTS->discount(refDate + spotDays);
132 Real t2 = vol2->timeFromReference(dates[1]);
133 Real domDisc2 = domesticTS->discount(dates[1] + spotDays) / domesticTS->discount(refDate + spotDays);
134 Real forDisc2 = foreignTS->discount(dates[1] + spotDays) / foreignTS->discount(refDate + spotDays);
135
136 // checks for expiry 1
137
138 Real bfvol2_1_10_broker = atmQuotes[0] + bfQuotes[0][0];
139 Real bfvol2_1_25_broker = atmQuotes[0] + bfQuotes[0][1];
140
141 BlackDeltaCalculator bdc_1_10_p(Option::Put, dt, spot->value(), domDisc1, forDisc1,
142 bfvol2_1_10_broker * std::sqrt(t1));
143 Real k2_1_10p_broker = bdc_1_10_p.strikeFromDelta(-deltas[0]);
144
145 BlackDeltaCalculator bdc_1_10_c(Option::Call, dt, spot->value(), domDisc1, forDisc1,
146 bfvol2_1_10_broker * std::sqrt(t1));
147 Real k2_1_10c_broker = bdc_1_10_c.strikeFromDelta(deltas[0]);
148
149 BlackDeltaCalculator bdc_1_25_p(Option::Put, dt, spot->value(), domDisc1, forDisc1,
150 bfvol2_1_25_broker * std::sqrt(t1));
151 Real k2_1_25p_broker = bdc_1_25_p.strikeFromDelta(-deltas[1]);
152
153 BlackDeltaCalculator bdc_1_25_c(Option::Call, dt, spot->value(), domDisc1, forDisc1,
154 bfvol2_1_25_broker * std::sqrt(t1));
155 Real k2_1_25c_broker = bdc_1_25_c.strikeFromDelta(deltas[1]);
156
157 Real bfPrice_1_10_broker = blackFormula(Option::Put, k2_1_10p_broker, spot->value() / domDisc1 * forDisc1,
158 bfvol2_1_10_broker * std::sqrt(t1)) +
159 blackFormula(Option::Call, k2_1_10c_broker, spot->value() / domDisc1 * forDisc1,
160 bfvol2_1_10_broker * std::sqrt(t1));
161
162 Real bfPrice_1_25_broker = blackFormula(Option::Put, k2_1_25p_broker, spot->value() / domDisc1 * forDisc1,
163 bfvol2_1_25_broker * std::sqrt(t1)) +
164 blackFormula(Option::Call, k2_1_25c_broker, spot->value() / domDisc1 * forDisc1,
165 bfvol2_1_25_broker * std::sqrt(t1));
166
167 Real k2_1_10p = getStrikeFromDelta(Option::Put, -deltas[0], dt, spot->value(), domDisc1, forDisc1, vol2, t1);
168 Real k2_1_25p = getStrikeFromDelta(Option::Put, -deltas[1], dt, spot->value(), domDisc1, forDisc1, vol2, t1);
169 Real k2_1_atm = getAtmStrike(dt, at, spot->value(), domDisc1, forDisc1, vol2, t1);
170 Real k2_1_25c = getStrikeFromDelta(Option::Call, deltas[1], dt, spot->value(), domDisc1, forDisc1, vol2, t1);
171 Real k2_1_10c = getStrikeFromDelta(Option::Call, deltas[0], dt, spot->value(), domDisc1, forDisc1, vol2, t1);
172
173 Real bfPrice_1_10_smile = blackFormula(Option::Put, k2_1_10p_broker, spot->value() / domDisc1 * forDisc1,
174 std::sqrt(vol2->blackVariance(dates[0], k2_1_10p_broker))) +
175 blackFormula(Option::Call, k2_1_10c_broker, spot->value() / domDisc1 * forDisc1,
176 std::sqrt(vol2->blackVariance(dates[0], k2_1_10c_broker)));
177
178 Real bfPrice_1_25_smile = blackFormula(Option::Put, k2_1_25p_broker, spot->value() / domDisc1 * forDisc1,
179 std::sqrt(vol2->blackVariance(dates[0], k2_1_25p_broker))) +
180 blackFormula(Option::Call, k2_1_25c_broker, spot->value() / domDisc1 * forDisc1,
181 std::sqrt(vol2->blackVariance(dates[0], k2_1_25c_broker)));
182
183 // check broker bf premium = smile bf premium
184
185 BOOST_CHECK_SMALL(bfPrice_1_10_smile - bfPrice_1_10_broker, tol2);
186 BOOST_CHECK_SMALL(bfPrice_1_25_smile - bfPrice_1_25_broker, tol2);
187
188 // check rr and atm quotes are reproduced on smile
189
190 BOOST_CHECK_SMALL(vol2->blackVol(dates[0], k2_1_10c) - vol2->blackVol(dates[0], k2_1_10p) - rrQuotes[0][0], tol1);
191 BOOST_CHECK_SMALL(vol2->blackVol(dates[0], k2_1_25c) - vol2->blackVol(dates[0], k2_1_25p) - rrQuotes[0][1], tol1);
192 BOOST_CHECK_SMALL(vol2->blackVol(dates[0], k2_1_atm) - atmQuotes[0], tol1);
193
194 // checks for expiry 2
195
196 Real bfvol2_2_10_broker = atmQuotes[1] + bfQuotes[1][0];
197 Real bfvol2_2_25_broker = atmQuotes[1] + bfQuotes[1][1];
198
199 BlackDeltaCalculator bdc_2_10_p(Option::Put, ltdt, spot->value(), domDisc2, forDisc2,
200 bfvol2_2_10_broker * std::sqrt(t2));
201 Real k2_2_10p_broker = bdc_2_10_p.strikeFromDelta(-deltas[0]);
202
203 BlackDeltaCalculator bdc_2_10_c(Option::Call, ltdt, spot->value(), domDisc2, forDisc2,
204 bfvol2_2_10_broker * std::sqrt(t2));
205 Real k2_2_10c_broker = bdc_2_10_c.strikeFromDelta(deltas[0]);
206
207 BlackDeltaCalculator bdc_2_25_p(Option::Put, ltdt, spot->value(), domDisc2, forDisc2,
208 bfvol2_2_25_broker * std::sqrt(t2));
209 Real k2_2_25p_broker = bdc_2_25_p.strikeFromDelta(-deltas[1]);
210
211 BlackDeltaCalculator bdc_2_25_c(Option::Call, ltdt, spot->value(), domDisc2, forDisc2,
212 bfvol2_2_25_broker * std::sqrt(t2));
213 Real k2_2_25c_broker = bdc_2_25_c.strikeFromDelta(deltas[1]);
214
215 Real bfPrice_2_10_broker = blackFormula(Option::Put, k2_2_10p_broker, spot->value() / domDisc2 * forDisc2,
216 bfvol2_2_10_broker * std::sqrt(t2)) +
217 blackFormula(Option::Call, k2_2_10c_broker, spot->value() / domDisc2 * forDisc2,
218 bfvol2_2_10_broker * std::sqrt(t2));
219
220 Real bfPrice_2_25_broker = blackFormula(Option::Put, k2_2_25p_broker, spot->value() / domDisc2 * forDisc2,
221 bfvol2_2_25_broker * std::sqrt(t2)) +
222 blackFormula(Option::Call, k2_2_25c_broker, spot->value() / domDisc2 * forDisc2,
223 bfvol2_2_25_broker * std::sqrt(t2));
224
225 Real k2_2_10p = getStrikeFromDelta(Option::Put, -deltas[0], ltdt, spot->value(), domDisc2, forDisc2, vol2, t2);
226 Real k2_2_25p = getStrikeFromDelta(Option::Put, -deltas[1], ltdt, spot->value(), domDisc2, forDisc2, vol2, t2);
227 Real k2_2_atm = getAtmStrike(ltdt, ltat, spot->value(), domDisc2, forDisc2, vol2, t2);
228 Real k2_2_25c = getStrikeFromDelta(Option::Call, deltas[1], ltdt, spot->value(), domDisc2, forDisc2, vol2, t2);
229 Real k2_2_10c = getStrikeFromDelta(Option::Call, deltas[0], ltdt, spot->value(), domDisc2, forDisc2, vol2, t2);
230
231 Real bfPrice_2_10_smile = blackFormula(Option::Put, k2_2_10p_broker, spot->value() / domDisc2 * forDisc2,
232 std::sqrt(vol2->blackVariance(dates[1], k2_2_10p_broker))) +
233 blackFormula(Option::Call, k2_2_10c_broker, spot->value() / domDisc2 * forDisc2,
234 std::sqrt(vol2->blackVariance(dates[1], k2_2_10c_broker)));
235
236 Real bfPrice_2_25_smile = blackFormula(Option::Put, k2_2_25p_broker, spot->value() / domDisc2 * forDisc2,
237 std::sqrt(vol2->blackVariance(dates[1], k2_2_25p_broker))) +
238 blackFormula(Option::Call, k2_2_25c_broker, spot->value() / domDisc2 * forDisc2,
239 std::sqrt(vol2->blackVariance(dates[1], k2_2_25c_broker)));
240
241 // check broker bf premium = smile bf premium
242
243 BOOST_CHECK_SMALL(bfPrice_2_10_smile - bfPrice_2_10_broker, tol2);
244 BOOST_CHECK_SMALL(bfPrice_2_25_smile - bfPrice_2_25_broker, tol2);
245
246 // check rr and atm quotes are reproduced on smile
247
248 BOOST_CHECK_SMALL(vol2->blackVol(dates[1], k2_2_10c) - vol2->blackVol(dates[1], k2_2_10p) - rrQuotes[1][0], tol1);
249 BOOST_CHECK_SMALL(vol2->blackVol(dates[1], k2_2_25c) - vol2->blackVol(dates[1], k2_2_25p) - rrQuotes[1][1], tol1);
250 BOOST_CHECK_SMALL(vol2->blackVol(dates[1], k2_2_atm) - atmQuotes[1], tol1);
251}
+ Here is the call graph for this function: