Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/instrument.hpp
Line
Count
Source
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
 <https://www.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
36
namespace 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
        const ext::shared_ptr<PricingEngine>& pricingEngine() const;
59
        //! returns any additional result returned by the pricing engine.
60
        template <typename T> T result(const std::string& tag) const;
61
        //! returns all additional result returned by the pricing engine.
62
        const std::map<std::string, ext::any>& additionalResults() const;
63
64
        //! returns whether the instrument might have value greater than zero.
65
        virtual bool isExpired() const = 0;
66
        //@}
67
        //! \name Modifiers
68
        //@{
69
        //! set the pricing engine to be used.
70
        /*! \warning calling this method will have no effects in
71
                     case the <b>performCalculation</b> method
72
                     was overridden in a derived class.
73
        */
74
        void setPricingEngine(const ext::shared_ptr<PricingEngine>&);
75
        //@}
76
        /*! When a derived argument structure is defined for an
77
            instrument, this method should be overridden to fill
78
            it. This is mandatory in case a pricing engine is used.
79
        */
80
        virtual void setupArguments(PricingEngine::arguments*) const;
81
        /*! When a derived result structure is defined for an
82
            instrument, this method should be overridden to read from
83
            it. This is mandatory in case a pricing engine is used.
84
        */
85
        virtual void fetchResults(const PricingEngine::results*) const;
86
      protected:
87
        //! \name Calculations
88
        //@{
89
        void calculate() const override;
90
        /*! This method must leave the instrument in a consistent
91
            state when the expiration condition is met.
92
        */
93
        virtual void setupExpired() const;
94
        /*! In case a pricing engine is <b>not</b> used, this
95
            method must be overridden to perform the actual
96
            calculations and set any needed results. In case
97
            a pricing engine is used, the default implementation
98
            can be used.
99
        */
100
        void performCalculations() const override;
101
        //@}
102
        /*! \name Results
103
            The value of this attribute and any other that derived
104
            classes might declare must be set during calculation.
105
        */
106
        //@{
107
        mutable Real NPV_, errorEstimate_;
108
        mutable Date valuationDate_;
109
        mutable std::map<std::string, ext::any> additionalResults_;
110
        //@}
111
        ext::shared_ptr<PricingEngine> engine_;
112
    };
113
114
    class Instrument::results : public virtual PricingEngine::results {
115
      public:
116
0
        void reset() override {
117
0
            value = errorEstimate = Null<Real>();
118
0
            valuationDate = Date();
119
0
            additionalResults.clear();
120
0
        }
121
        Real value;
122
        Real errorEstimate;
123
        Date valuationDate;
124
        std::map<std::string, ext::any> additionalResults;
125
    };
126
127
128
    // inline definitions
129
130
451k
    inline void Instrument::calculate() const {
131
451k
        if (!calculated_) {
132
451k
            if (isExpired()) {
133
451k
                setupExpired();
134
451k
                calculated_ = true;
135
451k
            } else {
136
0
                LazyObject::calculate();
137
0
            }
138
451k
        }
139
451k
    }
140
141
451k
    inline void Instrument::setupExpired() const {
142
451k
        NPV_ = errorEstimate_ = 0.0;
143
451k
        valuationDate_ = Date();
144
451k
        additionalResults_.clear();
145
451k
    }
146
147
0
    inline void Instrument::performCalculations() const {
148
0
        QL_REQUIRE(engine_, "null pricing engine");
149
0
        engine_->reset();
150
0
        setupArguments(engine_->getArguments());
151
0
        engine_->getArguments()->validate();
152
0
        engine_->calculate();
153
0
        fetchResults(engine_->getResults());
154
0
    }
155
156
    inline void Instrument::fetchResults(
157
0
                                      const PricingEngine::results* r) const {
158
0
        const auto* results = dynamic_cast<const Instrument::results*>(r);
159
0
        QL_ENSURE(results != nullptr, "no results returned from pricing engine");
160
161
0
        NPV_ = results->value;
162
0
        errorEstimate_ = results->errorEstimate;
163
0
        valuationDate_ = results->valuationDate;
164
165
0
        additionalResults_ = results->additionalResults;
166
0
    }
167
168
451k
    inline Real Instrument::NPV() const {
169
451k
        calculate();
170
451k
        QL_REQUIRE(NPV_ != Null<Real>(), "NPV not provided");
171
451k
        return NPV_;
172
451k
    }
173
174
0
    inline Real Instrument::errorEstimate() const {
175
0
        calculate();
176
0
        QL_REQUIRE(errorEstimate_ != Null<Real>(),
177
0
                   "error estimate not provided");
178
0
        return errorEstimate_;
179
0
    }
180
181
0
    inline const Date& Instrument::valuationDate() const {
182
0
        calculate();
183
0
        QL_REQUIRE(valuationDate_ != Date(),
184
0
                   "valuation date not provided");
185
0
        return valuationDate_;
186
0
    }
Unexecuted instantiation: QuantLib::Instrument::valuationDate() const
Unexecuted instantiation: QuantLib::Instrument::valuationDate() const
187
188
0
    inline const ext::shared_ptr<PricingEngine>& Instrument::pricingEngine() const {
189
0
        return engine_;
190
0
    }
191
192
    template <class T>
193
    inline T Instrument::result(const std::string& tag) const {
194
        calculate();
195
        auto value =
196
            additionalResults_.find(tag);
197
        QL_REQUIRE(value != additionalResults_.end(),
198
                   tag << " not provided");
199
        return ext::any_cast<T>(value->second);
200
    }
201
202
    inline const std::map<std::string, ext::any>&
203
0
    Instrument::additionalResults() const {
204
0
        calculate();
205
0
        return additionalResults_;
206
0
    }
207
208
}
209
210
#endif