140 {
141
142 BOOST_TEST_MESSAGE("Testing pricing of fx option as multi leg option vs analytic engine");
143
144 SavedSettings backup;
145 Date refDate(12, January, 2015);
146 Settings::instance().evaluationDate() = refDate;
147
148 auto yts_eur = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(refDate, 0.02, Actual365Fixed()));
149 auto yts_usd = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(refDate, 0.03, Actual365Fixed()));
150
151 auto lgm_eur_p = QuantLib::ext::make_shared<IrLgm1fConstantParametrization>(EURCurrency(), yts_eur, 0.01, 0.01);
152 auto lgm_usd_p = QuantLib::ext::make_shared<IrLgm1fConstantParametrization>(USDCurrency(), yts_usd, 0.01, 0.01);
153
154 Handle<Quote> fxspot(QuantLib::ext::make_shared<SimpleQuote>(0.9));
155
156 auto fx_p = QuantLib::ext::make_shared<FxBsConstantParametrization>(USDCurrency(), fxspot, 0.15);
157
158 Matrix corr(3, 3);
159
160 corr[0][0] = 1.0; corr[0][1] = 0.2; corr[0][2] = 0.5;
161 corr[1][0] = 0.2; corr[1][1] = 1.0; corr[1][2] = 0.4;
162 corr[2][0] = 0.5; corr[2][1] = 0.4; corr[2][2] = 1.0;
163
164
165 auto xasset = Handle<CrossAssetModel>(QuantLib::ext::make_shared<CrossAssetModel>(
166 std::vector<QuantLib::ext::shared_ptr<Parametrization>>{lgm_eur_p, lgm_usd_p, fx_p}, corr));
167
168 Date exDate(12, January, 2020);
169 auto exercise = QuantLib::ext::make_shared<EuropeanExercise>(exDate);
170 auto fxOption =
171 QuantLib::ext::make_shared<VanillaOption>(QuantLib::ext::make_shared<PlainVanillaPayoff>(Option::Call, 0.8), exercise);
172
173 Leg usdFlow, eurFlow;
174 usdFlow.push_back(QuantLib::ext::make_shared<SimpleCashFlow>(1.0, exDate + 1));
175 eurFlow.push_back(QuantLib::ext::make_shared<SimpleCashFlow>(-0.8, exDate + 1));
176
177 auto multiLegOption =
178 QuantLib::ext::make_shared<MultiLegOption>(std::vector<Leg>{eurFlow, usdFlow}, std::vector<bool>{false, false},
179 std::vector<Currency>{EURCurrency(), USDCurrency()}, exercise);
180
181 auto analyticFxOptionEngine = QuantLib::ext::make_shared<AnalyticCcLgmFxOptionEngine>(*xasset, 0);
182 fxOption->setPricingEngine(analyticFxOptionEngine);
183 Real npv0 = fxOption->NPV();
184 BOOST_TEST_MESSAGE("npv (analytic cclgm fx option engine): " << npv0);
185
186
187 auto mcMultiLegOptionEngine = QuantLib::ext::make_shared<McMultiLegOptionEngine>(
189
190 multiLegOption->setPricingEngine(mcMultiLegOptionEngine);
191 boost::timer::cpu_timer timer;
192 Real npv1 = multiLegOption->NPV();
193 timer.stop();
194 BOOST_TEST_MESSAGE("npv (multi leg option engine) : " << npv1 << ", timing " << timer.elapsed().wall * 1e-6
195 << " ms");
196
197 BOOST_CHECK_SMALL(std::abs(npv1 - npv0), 1.0E-4);
198
199}