Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/instrument.hpp
Line
Count
Source (jump to first uncovered line)
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
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
        //! 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
0
        void reset() override {
116
0
            value = errorEstimate = Null<Real>();
117
0
            valuationDate = Date();
118
0
            additionalResults.clear();
119
0
        }
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
518k
    inline void Instrument::calculate() const {
130
518k
        if (!calculated_) {
131
518k
            if (isExpired()) {
132
518k
                setupExpired();
133
518k
                calculated_ = true;
134
518k
            } else {
135
0
                LazyObject::calculate();
136
0
            }
137
518k
        }
138
518k
    }
139
140
518k
    inline void Instrument::setupExpired() const {
141
518k
        NPV_ = errorEstimate_ = 0.0;
142
518k
        valuationDate_ = Date();
143
518k
        additionalResults_.clear();
144
518k
    }
145
146
0
    inline void Instrument::performCalculations() const {
147
0
        QL_REQUIRE(engine_, "null pricing engine");
148
0
        engine_->reset();
149
0
        setupArguments(engine_->getArguments());
150
0
        engine_->getArguments()->validate();
151
0
        engine_->calculate();
152
0
        fetchResults(engine_->getResults());
153
0
    }
154
155
    inline void Instrument::fetchResults(
156
0
                                      const PricingEngine::results* r) const {
157
0
        const auto* results = dynamic_cast<const Instrument::results*>(r);
158
0
        QL_ENSURE(results != nullptr, "no results returned from pricing engine");
159
160
0
        NPV_ = results->value;
161
0
        errorEstimate_ = results->errorEstimate;
162
0
        valuationDate_ = results->valuationDate;
163
164
0
        additionalResults_ = results->additionalResults;
165
0
    }
166
167
518k
    inline Real Instrument::NPV() const {
168
518k
        calculate();
169
518k
        QL_REQUIRE(NPV_ != Null<Real>(), "NPV not provided");
170
518k
        return NPV_;
171
518k
    }
172
173
0
    inline Real Instrument::errorEstimate() const {
174
0
        calculate();
175
0
        QL_REQUIRE(errorEstimate_ != Null<Real>(),
176
0
                   "error estimate not provided");
177
0
        return errorEstimate_;
178
0
    }
179
180
0
    inline const Date& Instrument::valuationDate() const {
181
0
        calculate();
182
0
        QL_REQUIRE(valuationDate_ != Date(),
183
0
                   "valuation date not provided");
184
0
        return valuationDate_;
185
0
    }
Unexecuted instantiation: QuantLib::Instrument::valuationDate() const
Unexecuted instantiation: QuantLib::Instrument::valuationDate() const
186
187
    template <class T>
188
    inline T Instrument::result(const std::string& tag) const {
189
        calculate();
190
        auto value =
191
            additionalResults_.find(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
0
    Instrument::additionalResults() const {
199
0
        calculate();
200
0
        return additionalResults_;
201
0
    }
202
203
}
204
205
#endif