[go: up one dir, main page]

1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2003 RiskMap 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 "quotes.hpp"
21#include "utilities.hpp"
22#include <ql/quotes/simplequote.hpp>
23#include <ql/quotes/derivedquote.hpp>
24#include <ql/quotes/compositequote.hpp>
25#include <ql/quotes/forwardvaluequote.hpp>
26#include <ql/quotes/impliedstddevquote.hpp>
27#include <ql/time/calendars/target.hpp>
28#include <ql/time/daycounters/actualactual.hpp>
29#include <ql/termstructures/yield/flatforward.hpp>
30#include <ql/indexes/ibor/euribor.hpp>
31#include <ql/pricingengines/blackformula.hpp>
32
33using namespace QuantLib;
34using namespace boost::unit_test_framework;
35
36namespace quotes_test {
37
38 Real add10(Real x) { return x+10; }
39 Real mul10(Real x) { return x*10; }
40 Real sub10(Real x) { return x-10; }
41
42 Real add(Real x, Real y) { return x+y; }
43 Real mul(Real x, Real y) { return x*y; }
44 Real sub(Real x, Real y) { return x-y; }
45
46}
47
48
49void QuoteTest::testObservable() {
50
51 BOOST_TEST_MESSAGE("Testing observability of quotes...");
52
53 ext::shared_ptr<SimpleQuote> me(new SimpleQuote(0.0));
54 Flag f;
55 f.registerWith(h: me);
56 me->setValue(3.14);
57
58 if (!f.isUp())
59 BOOST_FAIL("Observer was not notified of quote change");
60
61}
62
63void QuoteTest::testObservableHandle() {
64
65 BOOST_TEST_MESSAGE("Testing observability of quote handles...");
66
67 ext::shared_ptr<SimpleQuote> me1(new SimpleQuote(0.0));
68 RelinkableHandle<Quote> h(me1);
69 Flag f;
70 f.registerWith(h);
71
72 me1->setValue(3.14);
73 if (!f.isUp())
74 BOOST_FAIL("Observer was not notified of quote change");
75
76 f.lower();
77 ext::shared_ptr<SimpleQuote> me2(new SimpleQuote(0.0));
78 h.linkTo(h: me2);
79 if (!f.isUp())
80 BOOST_FAIL("Observer was not notified of quote change");
81
82}
83
84void QuoteTest::testDerived() {
85
86 BOOST_TEST_MESSAGE("Testing derived quotes...");
87
88 using namespace quotes_test;
89
90 typedef Real (*unary_f)(Real);
91 unary_f funcs[3] = { add10, mul10, sub10 };
92
93 ext::shared_ptr<Quote> me(new SimpleQuote(17.0));
94 Handle<Quote> h(me);
95
96 for (auto& func : funcs) {
97 DerivedQuote<unary_f> derived(h, func);
98 Real x = derived.value(), y = func(me->value());
99 if (std::fabs(x: x-y) > 1.0e-10)
100 BOOST_FAIL("derived quote yields " << x << "\n"
101 << "function result is " << y);
102 }
103}
104
105void QuoteTest::testComposite() {
106
107 BOOST_TEST_MESSAGE("Testing composite quotes...");
108
109 typedef Real (*binary_f)(Real,Real);
110 binary_f funcs[3] = { quotes_test::add, quotes_test::mul, quotes_test::sub };
111
112 ext::shared_ptr<Quote> me1(new SimpleQuote(12.0)),
113 me2(new SimpleQuote(13.0));
114 Handle<Quote> h1(me1), h2(me2);
115
116 for (auto& func : funcs) {
117 CompositeQuote<binary_f> composite(h1, h2, func);
118 Real x = composite.value(), y = func(me1->value(), me2->value());
119 if (std::fabs(x: x-y) > 1.0e-10)
120 BOOST_FAIL("composite quote yields " << x << "\n"
121 << "function result is " << y);
122 }
123}
124
125void QuoteTest::testForwardValueQuoteAndImpliedStdevQuote(){
126 BOOST_TEST_MESSAGE(
127 "Testing forward-value and implied-standard-deviation quotes...");
128 Real forwardRate = .05;
129 DayCounter dc = ActualActual(ActualActual::ISDA);
130 Calendar calendar = TARGET();
131 ext::shared_ptr<SimpleQuote> forwardQuote(new SimpleQuote(forwardRate));
132 Handle<Quote> forwardHandle(forwardQuote);
133 Date evaluationDate = Settings::instance().evaluationDate();
134 ext::shared_ptr<YieldTermStructure>yc (new FlatForward(
135 evaluationDate, forwardHandle, dc));
136 Handle<YieldTermStructure> ycHandle(yc);
137 Period euriborTenor(1,Years);
138 ext::shared_ptr<Index> euribor(new Euribor(euriborTenor, ycHandle));
139 Date fixingDate = calendar.advance(date: evaluationDate, period: euriborTenor);
140 ext::shared_ptr<ForwardValueQuote> forwardValueQuote( new
141 ForwardValueQuote(euribor, fixingDate));
142 Rate forwardValue = forwardValueQuote->value();
143 Rate expectedForwardValue = euribor->fixing(fixingDate, forecastTodaysFixing: true);
144 // we test if the forward value given by the quote is consistent
145 // with the one directly given by the index
146 if (std::fabs(x: forwardValue-expectedForwardValue) > 1.0e-15)
147 BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n"
148 << "expected result is " << expectedForwardValue);
149 // then we test the observer/observable chain
150 Flag f;
151 f.registerWith(h: forwardValueQuote);
152 forwardQuote->setValue(0.04);
153 if (!f.isUp())
154 BOOST_FAIL("Observer was not notified of quote change");
155
156 // and we retest if the values are still matching
157 forwardValue = forwardValueQuote->value();
158 expectedForwardValue = euribor->fixing(fixingDate, forecastTodaysFixing: true);
159 if (std::fabs(x: forwardValue-expectedForwardValue) > 1.0e-15)
160 BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n"
161 << "expected result is " << expectedForwardValue);
162 // we test the ImpliedStdevQuote class
163 f.unregisterWith(h: forwardValueQuote);
164 f.lower();
165 Real price = 0.02;
166 Rate strike = 0.04;
167 Volatility guess = .15;
168 Real accuracy = 1.0e-6;
169 Option::Type optionType = Option::Call;
170 ext::shared_ptr<SimpleQuote> priceQuote(new SimpleQuote(price));
171 Handle<Quote> priceHandle(priceQuote);
172 ext::shared_ptr<ImpliedStdDevQuote> impliedStdevQuote(new
173 ImpliedStdDevQuote(optionType, forwardHandle, priceHandle,
174 strike, guess, accuracy));
175 Real impliedStdev = impliedStdevQuote->value();
176 Real expectedImpliedStdev =
177 blackFormulaImpliedStdDev(optionType, strike,
178 forward: forwardQuote->value(), blackPrice: price,
179 discount: 1.0, displacement: 0.0, guess, accuracy: 1.0e-6);
180 if (std::fabs(x: impliedStdev-expectedImpliedStdev) > 1.0e-15)
181 BOOST_FAIL("\nimpliedStdevQuote yields :" << impliedStdev <<
182 "\nexpected result is :" << expectedImpliedStdev);
183 // then we test the observer/observable chain
184 ext::shared_ptr<Quote> quote = impliedStdevQuote;
185 f.registerWith(h: quote);
186 forwardQuote->setValue(0.05);
187 if (!f.isUp())
188 BOOST_FAIL("Observer was not notified of quote change");
189 quote->value();
190 f.lower();
191 quote->value();
192 priceQuote->setValue(0.11);
193 if (!f.isUp())
194 BOOST_FAIL("Observer was not notified of quote change");
195
196}
197
198
199test_suite* QuoteTest::suite() {
200 auto* suite = BOOST_TEST_SUITE("Quote tests");
201 suite->add(QUANTLIB_TEST_CASE(&QuoteTest::testObservable));
202 suite->add(QUANTLIB_TEST_CASE(&QuoteTest::testObservableHandle));
203 suite->add(QUANTLIB_TEST_CASE(&QuoteTest::testDerived));
204 suite->add(QUANTLIB_TEST_CASE(&QuoteTest::testComposite));
205 suite->add(QUANTLIB_TEST_CASE(
206 &QuoteTest::testForwardValueQuoteAndImpliedStdevQuote));
207 return suite;
208}
209
210

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