Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions | Variables
analyticcashsettledeuropeanengine.cpp File Reference
#include "toplevelfixture.hpp"
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <ql/currencies/america.hpp>
#include <ql/math/interpolations/linearinterpolation.hpp>
#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/nullcalendar.hpp>
#include <qle/indexes/commodityindex.hpp>
#include <qle/pricingengines/analyticcashsettledeuropeanengine.hpp>
#include <qle/termstructures/pricecurve.hpp>

Go to the source code of this file.

Functions

 BOOST_DATA_TEST_CASE (testOptionBeforeExpiry, bdata::make(strikes) *bdata::make(optionTypes), strike, optionType)
 
 BOOST_DATA_TEST_CASE (testOptionManualExerciseAfterExpiry, bdata::make(strikes) *bdata::make(optionTypes), strike, optionType)
 
 BOOST_DATA_TEST_CASE (testOptionManualExerciseOnExpiry, bdata::make(strikes) *bdata::make(optionTypes) *bdata::make(irdes), strike, optionType, irde)
 
 BOOST_DATA_TEST_CASE (testOptionManualExerciseOnPayment, bdata::make(strikes) *bdata::make(optionTypes), strike, optionType)
 
 BOOST_DATA_TEST_CASE (testOptionAutomaticExerciseAfterExpiry, bdata::make(strikes) *bdata::make(optionTypes), strike, optionType)
 
 BOOST_DATA_TEST_CASE (testOptionAutomaticExerciseOnExpiry, bdata::make(strikes) *bdata::make(optionTypes) *bdata::make(irdes), strike, optionType, irde)
 
 BOOST_DATA_TEST_CASE (testOptionAutomaticExerciseOnPayment, bdata::make(strikes) *bdata::make(optionTypes), strike, optionType)
 

Variables

vector< Real > strikes { 55, 58, 62, 65 }
 
vector< Option::Type > optionTypes { Option::Type::Call, Option::Type::Put }
 
vector< boolirdes { true, false }
 

Function Documentation

◆ BOOST_DATA_TEST_CASE() [1/7]

BOOST_DATA_TEST_CASE ( testOptionBeforeExpiry  ,
bdata::make(strikes) *bdata::make(optionTypes ,
strike  ,
optionType   
)

Definition at line 149 of file analyticcashsettledeuropeanengine.cpp.

149 {
150
151 BOOST_TEST_MESSAGE("Testing cash settled option pricing before expiry...");
152
153 Settings::instance().evaluationDate() = Date(3, Jun, 2020);
154
155 // Create cash settled option instrument
156 Date expiry(3, Sep, 2020);
157 Date payment(7, Sep, 2020);
158 bool automaticExercise = false;
159 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise);
160
161 // Create engine that accounts for cash settlement.
162 Rate spot = 60.00;
163 Volatility vol = 0.30;
164 Rate r = 0.02;
165 Rate q = 0.01;
166 QuantLib::ext::shared_ptr<PricingEngine> engine =
167 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
168
169 // Value the option accounting for cash settlement and store all results
170 option.setPricingEngine(engine);
171 map<string, Real> cashSettledResults = results(option);
172
173 // Value the option ignoring cash settlement
174 engine = QuantLib::ext::make_shared<AnalyticEuropeanEngine>(getProcess(spot, vol, r, q));
175 option.setPricingEngine(engine);
176 map<string, Real> theoreticalResults = results(option);
177
178 // Discount factor from payment to expiry.
179 auto yts = flatYts(r);
180 DiscountFactor df_te_tp = yts->discount(payment) / yts->discount(expiry);
181 BOOST_TEST_MESSAGE("Discount factor from payment to expiry is: " << fixed << setprecision(12) << df_te_tp);
182
183 // Check the results
184 Real tolerance = 1e-12;
185 BOOST_REQUIRE_EQUAL(cashSettledResults.size(), theoreticalResults.size());
186 BOOST_REQUIRE(cashSettledResults.count("npv") == 1);
187 BOOST_REQUIRE(theoreticalResults.count("npv") == 1);
188 for (const auto& kv : cashSettledResults) {
189
190 BOOST_TEST_CONTEXT("With result " << kv.first) {
191
192 auto it = theoreticalResults.find(kv.first);
193 BOOST_CHECK(it != theoreticalResults.end());
194
195 // If there is no matching result in theoreticalResults, skip to next result.
196 if (it == theoreticalResults.end())
197 continue;
198
199 // Check the result is as expected by comparing to the results that do not account for delayed payment.
200 Real theorResult = it->second;
201 BOOST_TEST_MESSAGE("Value for " << kv.first << " with cash settlement is: " << fixed << setprecision(12)
202 << kv.second);
203 BOOST_TEST_MESSAGE("Value for " << kv.first << " ignoring cash settlement is: " << fixed << setprecision(12)
204 << theorResult);
205
206 // Most results should be of the form cashSettledResult = DF(t_e, t_p) * theoreticalResult.
207 // There are some exceptions dealt with below.
208 if (close(theorResult, 0.0)) {
209 BOOST_CHECK(close(kv.second, 0.0));
210 } else if (kv.first == "elasticity" || kv.first == "itmCashProbability") {
211 BOOST_CHECK(close(kv.second, theorResult));
212 } else if (kv.first == "rho") {
213 Time delta_te_tp = yts->timeFromReference(payment) - yts->timeFromReference(expiry);
214 Real expRho = df_te_tp * (theorResult - delta_te_tp * theoreticalResults.at("npv"));
215 BOOST_TEST_MESSAGE("Value for expected rho is: " << fixed << setprecision(12) << expRho);
216 BOOST_CHECK(close(kv.second, expRho));
217 } else {
218 BOOST_CHECK_SMALL(kv.second / theorResult - df_te_tp, tolerance);
219 }
220 }
221 }
222}

◆ BOOST_DATA_TEST_CASE() [2/7]

BOOST_DATA_TEST_CASE ( testOptionManualExerciseAfterExpiry  ,
bdata::make(strikes) *bdata::make(optionTypes ,
strike  ,
optionType   
)

Definition at line 224 of file analyticcashsettledeuropeanengine.cpp.

225 {
226
227 BOOST_TEST_MESSAGE("Testing cash settled manual exercise option pricing after expiry...");
228
229 Settings::instance().evaluationDate() = Date(4, Sep, 2020);
230
231 // Create cash settled option instrument
232 Date expiry(3, Sep, 2020);
233 Date payment(7, Sep, 2020);
234 bool automaticExercise = false;
235 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise);
236
237 // Create engine that accounts for cash settlement.
238 Rate spot = 60.00;
239 Volatility vol = 0.30;
240 Rate r = 0.02;
241 Rate q = 0.01;
242 QuantLib::ext::shared_ptr<PricingEngine> engine =
243 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
244
245 // Value the option accounting for cash settlement and store all results
246 option.setPricingEngine(engine);
247 map<string, Real> cashSettledResults = results(option);
248
249 // Option has not been manually exercised so all results should be zero.
250 for (const auto& kv : cashSettledResults) {
251 BOOST_TEST_CONTEXT("With result " << kv.first) { BOOST_CHECK(close(kv.second, 0.0)); }
252 }
253
254 // Manually exercise the option with an expiry value of 59.
255 Real exercisePrice = 59.00;
256 option.exercise(exercisePrice);
257
258 // Check the updated results
259 checkOptionValues(option, r, exercisePrice);
260}
+ Here is the call graph for this function:

◆ BOOST_DATA_TEST_CASE() [3/7]

BOOST_DATA_TEST_CASE ( testOptionManualExerciseOnExpiry  ,
bdata::make(strikes) *bdata::make(optionTypes) *bdata::make(irdes ,
strike  ,
optionType  ,
irde   
)

Definition at line 265 of file analyticcashsettledeuropeanengine.cpp.

266 {
267
268 BOOST_TEST_MESSAGE("Testing cash settled manual exercise option on expiry date...");
269
270 // Should work for either setting of includeReferenceDateEvents.
271 Settings::instance().includeReferenceDateEvents() = irde;
272
273 // Create cash settled option instrument
274 Date expiry(3, Sep, 2020);
275 Settings::instance().evaluationDate() = expiry;
276 Date payment(7, Sep, 2020);
277 bool automaticExercise = false;
278 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise);
279
280 // Create engine that accounts for cash settlement.
281 Rate spot = 60.00;
282 Volatility vol = 0.30;
283 Rate r = 0.02;
284 Rate q = 0.01;
285 QuantLib::ext::shared_ptr<PricingEngine> engine =
286 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
287
288 // Set the pricing engine
289 option.setPricingEngine(engine);
290
291 // We are on the expiry date but have not exercised the option. Expect the valuation to proceed and hence
292 // the value to be based off the market spot price.
293 checkOptionValues(option, r, spot);
294
295 // Manually exercise the option with an expiry value of 59.
296 Real exercisePrice = 59.00;
297 option.exercise(exercisePrice);
298
299 // Check the updated option values.
300 checkOptionValues(option, r, exercisePrice);
301}
+ Here is the call graph for this function:

◆ BOOST_DATA_TEST_CASE() [4/7]

BOOST_DATA_TEST_CASE ( testOptionManualExerciseOnPayment  ,
bdata::make(strikes) *bdata::make(optionTypes ,
strike  ,
optionType   
)

Definition at line 303 of file analyticcashsettledeuropeanengine.cpp.

304 {
305
306 BOOST_TEST_MESSAGE("Testing cash settled manual exercise option on payment date...");
307
308 // Create cash settled option instrument
309 Date expiry(3, Sep, 2020);
310 Date payment(7, Sep, 2020);
311 Settings::instance().evaluationDate() = payment;
312 bool automaticExercise = false;
313 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise);
314
315 // Create engine that accounts for cash settlement.
316 Rate spot = 60.00;
317 Volatility vol = 0.30;
318 Rate r = 0.02;
319 Rate q = 0.01;
320 QuantLib::ext::shared_ptr<PricingEngine> engine =
321 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
322
323 // Set the pricing engine
324 option.setPricingEngine(engine);
325
326 // Manually exercise the option with an expiry value of 59.
327 Real exercisePrice = 59.00;
328 option.exercise(exercisePrice);
329
330 // Set include reference date events to true so that the option is not considered expired.
331 Settings::instance().includeReferenceDateEvents() = true;
332
333 // Check the option values against expected values.
334 checkOptionValues(option, r, exercisePrice);
335
336 // Set include reference date events to false so that the option is considered expired.
337 // Must recalculate for the setting to take effect.
338 Settings::instance().includeReferenceDateEvents() = false;
339 option.recalculate();
340
341 // Check that all the values are zero, i.e. the expired state.
342 map<string, Real> cashSettledResults = results(option);
343 for (const auto& kv : cashSettledResults) {
344 BOOST_TEST_CONTEXT("With result " << kv.first) { BOOST_CHECK(close(kv.second, 0.0)); }
345 }
346}
+ Here is the call graph for this function:

◆ BOOST_DATA_TEST_CASE() [5/7]

BOOST_DATA_TEST_CASE ( testOptionAutomaticExerciseAfterExpiry  ,
bdata::make(strikes) *bdata::make(optionTypes ,
strike  ,
optionType   
)

Definition at line 348 of file analyticcashsettledeuropeanengine.cpp.

349 {
350
351 BOOST_TEST_MESSAGE("Testing cash settled automatic exercise option pricing after expiry...");
352
353 Settings::instance().evaluationDate() = Date(4, Sep, 2020);
354
355 // Create index to be used in option.
356 Date expiry(3, Sep, 2020);
357 NullCalendar fixingCalendar;
358 QuantLib::ext::shared_ptr<Index> index =
359 QuantLib::ext::make_shared<CommodityFuturesIndex>("TEST", expiry, fixingCalendar, priceTs());
360
361 // Add the expiry date fixing for the index.
362 Real exercisePrice = 59.00;
363 index->addFixing(expiry, exercisePrice);
364
365 // Create cash settled option instrument
366 Date payment(7, Sep, 2020);
367 bool automaticExercise = true;
368 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise, index);
369
370 // Create engine that accounts for cash settlement.
371 Rate spot = 60.00;
372 Volatility vol = 0.30;
373 Rate r = 0.02;
374 Rate q = 0.01;
375 QuantLib::ext::shared_ptr<PricingEngine> engine =
376 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
377
378 // Set the pricing engine
379 option.setPricingEngine(engine);
380
381 // Check the option values against expected values.
382 checkOptionValues(option, r, exercisePrice);
383}

◆ BOOST_DATA_TEST_CASE() [6/7]

BOOST_DATA_TEST_CASE ( testOptionAutomaticExerciseOnExpiry  ,
bdata::make(strikes) *bdata::make(optionTypes) *bdata::make(irdes ,
strike  ,
optionType  ,
irde   
)

Definition at line 385 of file analyticcashsettledeuropeanengine.cpp.

386 {
387
388 BOOST_TEST_MESSAGE("Testing cash settled automatic exercise option pricing on expiry...");
389
390 // Should work for either setting of includeReferenceDateEvents.
391 Settings::instance().includeReferenceDateEvents() = irde;
392
393 // Create index to be used in option.
394 Date expiry(3, Sep, 2020);
395 Settings::instance().evaluationDate() = expiry;
396 NullCalendar fixingCalendar;
397 Handle<PriceTermStructure> pts = priceTs();
398 QuantLib::ext::shared_ptr<Index> index = QuantLib::ext::make_shared<CommodityFuturesIndex>("TEST", expiry, fixingCalendar, pts);
399
400 // Create cash settled option instrument
401 Date payment(7, Sep, 2020);
402 bool automaticExercise = true;
403 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise, index);
404
405 // Create engine that accounts for cash settlement.
406 Rate spot = 60.00;
407 Volatility vol = 0.30;
408 Rate r = 0.02;
409 Rate q = 0.01;
410 QuantLib::ext::shared_ptr<PricingEngine> engine =
411 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
412
413 // Set the pricing engine
414 option.setPricingEngine(engine);
415
416 // We have not added a fixing for the index so it will be projected of the price term structure above to
417 // give the payoff. So, we use that value here in our check initially.
418 Real ptsPrice = pts->price(0.0);
419 checkOptionValues(option, r, ptsPrice);
420
421 // Add an expiry date fixing for the index.
422 Real exercisePrice = 59.00;
423 index->addFixing(expiry, exercisePrice);
424
425 // Check the updated values
426 checkOptionValues(option, r, exercisePrice);
427}

◆ BOOST_DATA_TEST_CASE() [7/7]

BOOST_DATA_TEST_CASE ( testOptionAutomaticExerciseOnPayment  ,
bdata::make(strikes) *bdata::make(optionTypes ,
strike  ,
optionType   
)

Definition at line 429 of file analyticcashsettledeuropeanengine.cpp.

430 {
431
432 BOOST_TEST_MESSAGE("Testing cash settled automatic exercise option pricing on payment date...");
433
434 // Create index to be used in option.
435 Date expiry(3, Sep, 2020);
436 NullCalendar fixingCalendar;
437 QuantLib::ext::shared_ptr<Index> index =
438 QuantLib::ext::make_shared<CommodityFuturesIndex>("TEST", expiry, fixingCalendar, priceTs());
439
440 // Add the expiry date fixing for the index.
441 Real exercisePrice = 59.00;
442 index->addFixing(expiry, exercisePrice);
443
444 // Create cash settled option instrument
445 Date payment(7, Sep, 2020);
446 Settings::instance().evaluationDate() = payment;
447 bool automaticExercise = true;
448 CashSettledEuropeanOption option(optionType, strike, expiry, payment, automaticExercise, index);
449
450 // Create engine that accounts for cash settlement.
451 Rate spot = 60.00;
452 Volatility vol = 0.30;
453 Rate r = 0.02;
454 Rate q = 0.01;
455 QuantLib::ext::shared_ptr<PricingEngine> engine =
456 QuantLib::ext::make_shared<AnalyticCashSettledEuropeanEngine>(getProcess(spot, vol, r, q));
457
458 // Set the pricing engine
459 option.setPricingEngine(engine);
460
461 // Set include reference date events to true so that the option is not considered expired.
462 Settings::instance().includeReferenceDateEvents() = true;
463
464 // Check the option values against expected values.
465 checkOptionValues(option, r, exercisePrice);
466
467 // Set include reference date events to false so that the option is considered expired.
468 // Must recalculate for the setting to take effect.
469 Settings::instance().includeReferenceDateEvents() = false;
470 option.recalculate();
471
472 // Check that all the values are zero, i.e. the expired state.
473 map<string, Real> cashSettledResults = results(option);
474 for (const auto& kv : cashSettledResults) {
475 BOOST_TEST_CONTEXT("With result " << kv.first) { BOOST_CHECK(close(kv.second, 0.0)); }
476 }
477}

Variable Documentation

◆ strikes

vector<Real> strikes { 55, 58, 62, 65 }

Definition at line 146 of file analyticcashsettledeuropeanengine.cpp.

◆ optionTypes

vector<Option::Type> optionTypes { Option::Type::Call, Option::Type::Put }

Definition at line 147 of file analyticcashsettledeuropeanengine.cpp.

◆ irdes

vector<bool> irdes { true, false }

Definition at line 263 of file analyticcashsettledeuropeanengine.cpp.