1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21/*! \file instrument.hpp
22 \brief Abstract instrument class
23*/
24
25#ifndef quantlib_instrument_hpp
26#define quantlib_instrument_hpp
27
28#include <ql/patterns/lazyobject.hpp>
29#include <ql/pricingengine.hpp>
30#include <ql/utilities/null.hpp>
31#include <ql/time/date.hpp>
32#include <ql/any.hpp>
33#include <map>
34#include <string>
35
36namespace QuantLib {
37
38 //! Abstract instrument class
39 /*! This class is purely abstract and defines the interface of concrete
40 instruments which will be derived from this one.
41
42 \test observability of class instances is checked.
43 */
44 class Instrument : public LazyObject {
45 public:
46 class results;
47 Instrument();
48 //! \name Inspectors
49 //@{
50
51 //! returns the net present value of the instrument.
52 Real NPV() const;
53 //! returns the error estimate on the NPV when available.
54 Real errorEstimate() const;
55 //! returns the date the net present value refers to.
56 const Date& valuationDate() const;
57
58 //! returns any additional result returned by the pricing engine.
59 template <typename T> T result(const std::string& tag) const;
60 //! returns all additional result returned by the pricing engine.
61 const std::map<std::string, ext::any>& additionalResults() const;
62
63 //! returns whether the instrument might have value greater than zero.
64 virtual bool isExpired() const = 0;
65 //@}
66 //! \name Modifiers
67 //@{
68 //! set the pricing engine to be used.
69 /*! \warning calling this method will have no effects in
70 case the <b>performCalculation</b> method
71 was overridden in a derived class.
72 */
73 void setPricingEngine(const ext::shared_ptr<PricingEngine>&);
74 //@}
75 /*! When a derived argument structure is defined for an
76 instrument, this method should be overridden to fill
77 it. This is mandatory in case a pricing engine is used.
78 */
79 virtual void setupArguments(PricingEngine::arguments*) const;
80 /*! When a derived result structure is defined for an
81 instrument, this method should be overridden to read from
82 it. This is mandatory in case a pricing engine is used.
83 */
84 virtual void fetchResults(const PricingEngine::results*) const;
85 protected:
86 //! \name Calculations
87 //@{
88 void calculate() const override;
89 /*! This method must leave the instrument in a consistent
90 state when the expiration condition is met.
91 */
92 virtual void setupExpired() const;
93 /*! In case a pricing engine is <b>not</b> used, this
94 method must be overridden to perform the actual
95 calculations and set any needed results. In case
96 a pricing engine is used, the default implementation
97 can be used.
98 */
99 void performCalculations() const override;
100 //@}
101 /*! \name Results
102 The value of this attribute and any other that derived
103 classes might declare must be set during calculation.
104 */
105 //@{
106 mutable Real NPV_, errorEstimate_;
107 mutable Date valuationDate_;
108 mutable std::map<std::string, ext::any> additionalResults_;
109 //@}
110 ext::shared_ptr<PricingEngine> engine_;
111 };
112
113 class Instrument::results : public virtual PricingEngine::results {
114 public:
115 void reset() override {
116 value = errorEstimate = Null<Real>();
117 valuationDate = Date();
118 additionalResults.clear();
119 }
120 Real value;
121 Real errorEstimate;
122 Date valuationDate;
123 std::map<std::string, ext::any> additionalResults;
124 };
125
126
127 // inline definitions
128
129 inline void Instrument::calculate() const {
130 if (!calculated_) {
131 if (isExpired()) {
132 setupExpired();
133 calculated_ = true;
134 } else {
135 LazyObject::calculate();
136 }
137 }
138 }
139
140 inline void Instrument::setupExpired() const {
141 NPV_ = errorEstimate_ = 0.0;
142 valuationDate_ = Date();
143 additionalResults_.clear();
144 }
145
146 inline void Instrument::performCalculations() const {
147 QL_REQUIRE(engine_, "null pricing engine");
148 engine_->reset();
149 setupArguments(engine_->getArguments());
150 engine_->getArguments()->validate();
151 engine_->calculate();
152 fetchResults(engine_->getResults());
153 }
154
155 inline void Instrument::fetchResults(
156 const PricingEngine::results* r) const {
157 const auto* results = dynamic_cast<const Instrument::results*>(r);
158 QL_ENSURE(results != nullptr, "no results returned from pricing engine");
159
160 NPV_ = results->value;
161 errorEstimate_ = results->errorEstimate;
162 valuationDate_ = results->valuationDate;
163
164 additionalResults_ = results->additionalResults;
165 }
166
167 inline Real Instrument::NPV() const {
168 calculate();
169 QL_REQUIRE(NPV_ != Null<Real>(), "NPV not provided");
170 return NPV_;
171 }
172
173 inline Real Instrument::errorEstimate() const {
174 calculate();
175 QL_REQUIRE(errorEstimate_ != Null<Real>(),
176 "error estimate not provided");
177 return errorEstimate_;
178 }
179
180 inline const Date& Instrument::valuationDate() const {
181 calculate();
182 QL_REQUIRE(valuationDate_ != Date(),
183 "valuation date not provided");
184 return valuationDate_;
185 }
186
187 template <class T>
188 inline T Instrument::result(const std::string& tag) const {
189 calculate();
190 std::map<std::string, ext::any>::const_iterator value =
191 additionalResults_.find(x: tag);
192 QL_REQUIRE(value != additionalResults_.end(),
193 tag << " not provided");
194 return ext::any_cast<T>(value->second);
195 }
196
197 inline const std::map<std::string, ext::any>&
198 Instrument::additionalResults() const {
199 calculate();
200 return additionalResults_;
201 }
202
203}
204
205#endif
206

source code of quantlib/ql/instrument.hpp