1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 StatPro Italia srl
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include "pagodaoption.hpp"
21#include "utilities.hpp"
22#include <ql/experimental/exoticoptions/pagodaoption.hpp>
23#include <ql/experimental/exoticoptions/mcpagodaengine.hpp>
24#include <ql/math/randomnumbers/rngtraits.hpp>
25#include <ql/time/daycounters/actual360.hpp>
26#include <ql/quotes/simplequote.hpp>
27
28using namespace QuantLib;
29using namespace boost::unit_test_framework;
30
31void PagodaOptionTest::testCached() {
32
33 BOOST_TEST_MESSAGE("Testing pagoda option against cached values...");
34
35 Date today = Settings::instance().evaluationDate();
36
37 DayCounter dc = Actual360();
38 std::vector<Date> fixingDates;
39 for (Size i=1; i<=4; ++i)
40 fixingDates.push_back(x: today+i*90);
41
42 Real roof = 0.20;
43 Real fraction = 0.62;
44
45 PagodaOption option(fixingDates, roof, fraction);
46
47 Handle<YieldTermStructure> riskFreeRate(flatRate(today, forward: 0.05, dc));
48
49 std::vector<ext::shared_ptr<StochasticProcess1D> > processes(4);
50 processes[0] = ext::shared_ptr<StochasticProcess1D>(
51 new BlackScholesMertonProcess(
52 Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(0.15))),
53 Handle<YieldTermStructure>(flatRate(today, forward: 0.01, dc)),
54 riskFreeRate,
55 Handle<BlackVolTermStructure>(flatVol(today, volatility: 0.30, dc))));
56 processes[1] = ext::shared_ptr<StochasticProcess1D>(
57 new BlackScholesMertonProcess(
58 Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(0.20))),
59 Handle<YieldTermStructure>(flatRate(today, forward: 0.05, dc)),
60 riskFreeRate,
61 Handle<BlackVolTermStructure>(flatVol(today, volatility: 0.35, dc))));
62 processes[2] = ext::shared_ptr<StochasticProcess1D>(
63 new BlackScholesMertonProcess(
64 Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(0.35))),
65 Handle<YieldTermStructure>(flatRate(today, forward: 0.04, dc)),
66 riskFreeRate,
67 Handle<BlackVolTermStructure>(flatVol(today, volatility: 0.25, dc))));
68 processes[3] = ext::shared_ptr<StochasticProcess1D>(
69 new BlackScholesMertonProcess(
70 Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(0.30))),
71 Handle<YieldTermStructure>(flatRate(today, forward: 0.03, dc)),
72 riskFreeRate,
73 Handle<BlackVolTermStructure>(flatVol(today, volatility: 0.20, dc))));
74
75 Matrix correlation(4,4);
76 correlation[0][0] = 1.00;
77 correlation[0][1] = 0.50;
78 correlation[0][2] = 0.30;
79 correlation[0][3] = 0.10;
80 correlation[1][0] = 0.50;
81 correlation[1][1] = 1.00;
82 correlation[1][2] = 0.20;
83 correlation[1][3] = 0.40;
84 correlation[2][0] = 0.30;
85 correlation[2][1] = 0.20;
86 correlation[2][2] = 1.00;
87 correlation[2][3] = 0.60;
88 correlation[3][0] = 0.10;
89 correlation[3][1] = 0.40;
90 correlation[3][2] = 0.60;
91 correlation[3][3] = 1.00;
92
93 BigNatural seed = 86421;
94 Size fixedSamples = 1023;
95
96 ext::shared_ptr<StochasticProcessArray> process(
97 new StochasticProcessArray(processes, correlation));
98
99 option.setPricingEngine(MakeMCPagodaEngine<PseudoRandom>(process)
100 .withSamples(samples: fixedSamples)
101 .withSeed(seed));
102
103 Real value = option.NPV();
104 Real storedValue = 0.01221094;
105 Real tolerance = 1.0e-8;
106
107 if (std::fabs(x: value-storedValue) > tolerance)
108 BOOST_FAIL(std::setprecision(9)
109 << " calculated value: " << value << "\n"
110 << " expected: " << storedValue);
111
112 Real minimumTol = 1.0e-2;
113 tolerance = option.errorEstimate();
114 tolerance = std::min<Real>(a: tolerance/2.0, b: minimumTol*value);
115
116 option.setPricingEngine(MakeMCPagodaEngine<PseudoRandom>(process)
117 .withAbsoluteTolerance(tolerance)
118 .withSeed(seed));
119
120 option.NPV();
121 Real accuracy = option.errorEstimate();
122 if (accuracy > tolerance)
123 BOOST_FAIL(std::setprecision(10)
124 << " reached accuracy: " << accuracy << "\n"
125 << " expected: " << tolerance);
126}
127
128
129test_suite* PagodaOptionTest::suite() {
130 auto* suite = BOOST_TEST_SUITE("Pagoda-option tests");
131 suite->add(QUANTLIB_TEST_CASE(&PagodaOptionTest::testCached));
132 return suite;
133}
134
135

source code of quantlib/test-suite/pagodaoption.cpp