/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2003 RiskMap srl This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email . The license is also available online at . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #include "quotes.hpp" #include "utilities.hpp" #include #include #include #include #include #include #include #include #include #include using namespace QuantLib; using namespace boost::unit_test_framework; QL_BEGIN_TEST_LOCALS(QuoteTest) Real add10(Real x) { return x+10; } Real mul10(Real x) { return x*10; } Real sub10(Real x) { return x-10; } Real add(Real x, Real y) { return x+y; } Real mul(Real x, Real y) { return x*y; } Real sub(Real x, Real y) { return x-y; } QL_END_TEST_LOCALS(QuoteTest) void QuoteTest::testObservable() { BOOST_MESSAGE("Testing observability of quotes..."); boost::shared_ptr me(new SimpleQuote(0.0)); Flag f; f.registerWith(me); me->setValue(3.14); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); } void QuoteTest::testObservableHandle() { BOOST_MESSAGE("Testing observability of quote handles..."); boost::shared_ptr me1(new SimpleQuote(0.0)); RelinkableHandle h(me1); Flag f; f.registerWith(h); me1->setValue(3.14); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); f.lower(); boost::shared_ptr me2(new SimpleQuote(0.0)); h.linkTo(me2); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); } void QuoteTest::testDerived() { BOOST_MESSAGE("Testing derived quotes..."); typedef Real (*unary_f)(Real); unary_f funcs[3] = { add10, mul10, sub10 }; boost::shared_ptr me(new SimpleQuote(17.0)); Handle h(me); for (Integer i=0; i<3; i++) { DerivedQuote derived(h,funcs[i]); Real x = derived.value(), y = funcs[i](me->value()); if (std::fabs(x-y) > 1.0e-10) BOOST_FAIL("derived quote yields " << x << "\n" << "function result is " << y); } } void QuoteTest::testComposite() { BOOST_MESSAGE("Testing composite quotes..."); typedef Real (*binary_f)(Real,Real); binary_f funcs[3] = { add, mul, sub }; boost::shared_ptr me1(new SimpleQuote(12.0)), me2(new SimpleQuote(13.0)); Handle h1(me1), h2(me2); for (Integer i=0; i<3; i++) { CompositeQuote composite(h1,h2,funcs[i]); Real x = composite.value(), y = funcs[i](me1->value(),me2->value()); if (std::fabs(x-y) > 1.0e-10) BOOST_FAIL("composite quote yields " << x << "\n" << "function result is " << y); } } void QuoteTest::testForwardValueQuoteAndImpliedStdevQuote(){ BOOST_MESSAGE("Testing forward-value and implied-stdev quotes..."); Real forwardRate = .05; DayCounter dc = ActualActual(); Calendar calendar = TARGET(); boost::shared_ptr forwardQuote(new SimpleQuote(forwardRate)); Handle forwardHandle(forwardQuote); Date evaluationDate = Settings::instance().evaluationDate(); boost::shared_ptryc (new FlatForward( evaluationDate, forwardHandle, dc)); Handle ycHandle(yc); Period euriborTenor(1,Years); boost::shared_ptr euribor(new Euribor(euriborTenor, ycHandle)); Date fixingDate = calendar.advance(evaluationDate, euriborTenor); boost::shared_ptr forwardValueQuote( new ForwardValueQuote(euribor, fixingDate)); Rate forwardValue = forwardValueQuote->value(); Rate expectedForwardValue = euribor->fixing(fixingDate, true); // we test if the forward value given by the quote is consistent // with the one directly given by the index if (std::fabs(forwardValue-expectedForwardValue) > 1.0e-15) BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n" << "expected result is " << expectedForwardValue); // then we test the observer/observable chain Flag f; f.registerWith(forwardValueQuote); forwardQuote->setValue(0.04); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); // and we retest if the values are still matching forwardValue = forwardValueQuote->value(); expectedForwardValue = euribor->fixing(fixingDate, true); if (std::fabs(forwardValue-expectedForwardValue) > 1.0e-15) BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n" << "expected result is " << expectedForwardValue); // we test the ImpliedStdevQuote class f.unregisterWith(forwardValueQuote); f.lower(); Real price = 0.02; Rate strike = 0.04; Volatility guess = .15; Real accuracy = 1.0e-6; Option::Type optionType = Option::Call; boost::shared_ptr priceQuote(new SimpleQuote(price)); Handle priceHandle(priceQuote); boost::shared_ptr impliedStdevQuote(new ImpliedStdDevQuote(optionType, forwardHandle, priceHandle, strike, guess, accuracy)); Real impliedStdev = impliedStdevQuote->value(); Real expectedImpliedStdev = blackFormulaImpliedStdDev(optionType, strike, forwardQuote->value(), price, 1.0, guess, 1.0e-6); if (std::fabs(impliedStdev-expectedImpliedStdev) > 1.0e-15) BOOST_FAIL("impliedStdevQuote yields " << impliedStdev << "\n" << "expected result is " << expectedImpliedStdev); // then we test the observer/observable chain boost::shared_ptr quote = impliedStdevQuote; f.registerWith(quote); forwardQuote->setValue(0.05); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); quote->value(); f.lower(); priceQuote->setValue(0.11); if (!f.isUp()) BOOST_FAIL("Observer was not notified of quote change"); } test_suite* QuoteTest::suite() { test_suite* suite = BOOST_TEST_SUITE("Quote tests"); /*suite->add(BOOST_TEST_CASE(&QuoteTest::testObservable)); suite->add(BOOST_TEST_CASE(&QuoteTest::testObservableHandle)); suite->add(BOOST_TEST_CASE(&QuoteTest::testDerived)); suite->add(BOOST_TEST_CASE(&QuoteTest::testComposite));*/ suite->add(BOOST_TEST_CASE(&QuoteTest::testForwardValueQuoteAndImpliedStdevQuote)); return suite; }