192 {
193 BOOST_TEST_MESSAGE("Testing FXBarrierOption Price...");
194
195
196
197 BarrierOptionData fxb[] = {
198 {"DownAndOut", 95.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 9.0246},
199 {"DownAndOut", 95.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 4.8759},
200 {"DownAndOut", 100.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
201 {"DownAndOut", 100.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
202 {"DownAndOut", 100.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
203 {"UpAndOut", 105.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.6789},
204 {"UpAndOut", 105.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 2.3580},
205 {"UpAndOut", 105.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.3453},
206
207 {"DownAndIn", 95.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 7.7627},
208 {"DownAndIn", 95.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 4.0109},
209 {"DownAndIn", 95.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.0576},
210 {"DownAndIn", 100.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 13.8333},
211 {"DownAndIn", 100.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 7.8494},
212 {"DownAndIn", 100.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.9795},
213 {"UpAndIn", 105.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 14.1112},
214 {"UpAndIn", 105.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 8.4482},
215 {"UpAndIn", 105.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 4.5910},
216
217 {"DownAndOut", 95.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 8.8334},
218 {"DownAndOut", 95.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.0285},
219 {"DownAndOut", 95.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.4137},
220 {"DownAndOut", 100.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
221 {"DownAndOut", 100.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
222 {"DownAndOut", 100.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
223 {"UpAndOut", 105.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.6341},
224 {"UpAndOut", 105.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4389},
225 {"UpAndOut", 105.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4315},
226
227 {"DownAndIn", 95.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 9.0093},
228 {"DownAndIn", 95.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 5.1370},
229 {"DownAndIn", 95.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.8517},
230 {"DownAndIn", 100.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 14.8816},
231 {"DownAndIn", 100.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 9.2045},
232 {"DownAndIn", 100.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.3043},
233 {"UpAndIn", 105.0, 3.0, "Call", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 15.2098},
234 {"UpAndIn", 105.0, 3.0, "Call", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 9.7278},
235 {"UpAndIn", 105.0, 3.0, "Call", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.8350},
236
237
238 {"DownAndOut", 95.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2798},
239 {"DownAndOut", 95.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2947},
240 {"DownAndOut", 95.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.6252},
241 {"DownAndOut", 100.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
242 {"DownAndOut", 100.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
243 {"DownAndOut", 100.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000},
244 {"UpAndOut", 105.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.7760},
245 {"UpAndOut", 105.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 5.4932},
246 {"UpAndOut", 105.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 7.5187},
247
248 {"DownAndIn", 95.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.9586},
249 {"DownAndIn", 95.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 6.5677},
250 {"DownAndIn", 95.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 11.9752},
251 {"DownAndIn", 100.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2845},
252 {"DownAndIn", 100.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 5.9085},
253 {"DownAndIn", 100.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 11.6465},
254 {"UpAndIn", 105.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.25, 1.4653},
255 {"UpAndIn", 105.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.3721},
256 {"UpAndIn", 105.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.25, 7.0846},
257
258 {"DownAndOut", 95.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4170},
259 {"DownAndOut", 95.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4258},
260 {"DownAndOut", 95.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.6246},
261 {"DownAndOut", 100.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
262 {"DownAndOut", 100.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
263 {"DownAndOut", 100.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000},
264 {"UpAndOut", 105.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 4.2293},
265 {"UpAndOut", 105.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 5.8032},
266 {"UpAndOut", 105.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 7.5649},
267
268 {"DownAndIn", 95.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.8769},
269 {"DownAndIn", 95.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.7989},
270 {"DownAndIn", 95.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 13.3078},
271 {"DownAndIn", 100.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.3328},
272 {"DownAndIn", 100.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.2636},
273 {"DownAndIn", 100.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 12.9713},
274 {"UpAndIn", 105.0, 3.0, "Put", 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.0658},
275 {"UpAndIn", 105.0, 3.0, "Put", 100, 100.0, 0.04, 0.08, 0.50, 0.30, 4.4226},
276 {"UpAndIn", 105.0, 3.0, "Put", 110, 100.0, 0.04, 0.08, 0.50, 0.30, 8.3686},
277
278
279
280 {"DownAndOut", 95.0, 3.0, "Call", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
281 {"DownAndOut", 95.0, 3.0, "Call", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
282 {"DownAndOut", 100.0, 3.0, "Call", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
283 {"DownAndOut", 100.0, 3.0, "Call", 100, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
284 {"DownAndOut", 100.0, 3.0, "Call", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
285 {"UpAndOut", 105.0, 3.0, "Call", 90, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
286 {"UpAndOut", 105.0, 3.0, "Call", 100, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
287 {"UpAndOut", 105.0, 3.0, "Call", 110, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
288
289 {"DownAndOut", 95.0, 3.0, "Put", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
290 {"DownAndOut", 95.0, 3.0, "Put", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
291 {"DownAndOut", 100.0, 3.0, "Put", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
292 {"DownAndOut", 100.0, 3.0, "Put", 100, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
293 {"DownAndOut", 100.0, 3.0, "Put", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 3.0},
294 {"UpAndOut", 105.0, 3.0, "Put", 90, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
295 {"UpAndOut", 105.0, 3.0, "Put", 100, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
296 {"UpAndOut", 105.0, 3.0, "Put", 110, 110.0, 0.04, 0.08, 0.50, 0.25, 3.0},
297
298
299
300 {"DownAndIn", 95.0, 3.0, "Call", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 7.06448},
301 {"DownAndIn", 95.0, 3.0, "Call", 100, 90.0, 0.04, 0.08, 0.50, 0.25, 3.29945},
302 {"DownAndIn", 95.0, 3.0, "Call", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 1.36007},
303 {"DownAndIn", 100.0, 3.0, "Call", 90, 90.0, 0.04, 0.08, 0.50, 0.25, 7.06448},
304 {"DownAndIn", 100.0, 3.0, "Call", 100, 90.0, 0.04, 0.08, 0.50, 0.25, 3.29945},
305 {"DownAndIn", 100.0, 3.0, "Call", 110, 90.0, 0.04, 0.08, 0.50, 0.25, 1.36007},
306 {"UpAndIn", 105.0, 3.0, "Call", 90, 110.0, 0.04, 0.08, 0.50, 0.25, 22.21500},
307 {"UpAndIn", 105.0, 3.0, "Call", 100, 110.0, 0.04, 0.08, 0.50, 0.25, 14.52180},
308 {"UpAndIn", 105.0, 3.0, "Call", 110, 110.0, 0.04, 0.08, 0.50, 0.25, 8.63437}};
309
310 vector<string> positions = {"Long", "Short"};
311 for (auto& f : fxb) {
312 for (auto& position : positions) {
313
314 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>(f.s, f.q, f.r, f.v);
315 Date today = Settings::instance().evaluationDate();
316 Settings::instance().evaluationDate() = market->asofDate();
317
318
319 OptionData optionData(position, f.optionType,
"European",
true, vector<string>(1,
"20160801"));
320 vector<Real> barriers = {f.barrier};
321 vector<TradeBarrier> tradeBarriers;
323 BarrierData barrierData(f.barrierType, barriers, f.rebate, tradeBarriers);
325 FxBarrierOption fxBarrierOption(env, optionData, barrierData, Date(),
"",
"EUR", 1,
326 "JPY", f.k);
327
328
329
330 Real Notional = 1000000;
331 BarrierData barrierDataScaled(f.barrierType, barriers, f.rebate * Notional, tradeBarriers);
332 FxBarrierOption fxBarrierOptionNotional(env, optionData, barrierDataScaled, Date(),
"",
"EUR", Notional,
333 "JPY", Notional * f.k);
334
335 Real expectedNPV = f.result;
336
337
338 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
339 engineData->model("FxBarrierOption") = "GarmanKohlhagen";
340 engineData->engine("FxBarrierOption") = "AnalyticBarrierEngine";
341 engineData->model("FxOption") = "GarmanKohlhagen";
342 engineData->engine("FxOption") = "AnalyticEuropeanEngine";
343
344 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
345
346 fxBarrierOption.build(engineFactory);
347 fxBarrierOptionNotional.build(engineFactory);
348
349 Real npv = (position == "Long" ? 1 : -1) * fxBarrierOption.instrument()->NPV();
350
351 BOOST_TEST_MESSAGE("NPV Currency " << fxBarrierOption.npvCurrency());
352 BOOST_TEST_MESSAGE("FX Barrier Option NPV = " << npv);
353
354
355 QL_REQUIRE(fxBarrierOption.npvCurrency() == "JPY", "unexpected NPV currency ");
356
357 BOOST_CHECK_CLOSE(npv, expectedNPV, 0.2);
358 BOOST_CHECK_CLOSE(fxBarrierOption.instrument()->NPV() * 1000000,
359 fxBarrierOptionNotional.instrument()->NPV(), 0.2);
360 Settings::instance().evaluationDate() = today;
361 }
362 }
363}
Serializable obejct holding barrier data.
Serializable FX Barrier Option.