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
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
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
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
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
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
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}