Coverage Report

Created: 2025-09-04 07:11

/src/quantlib/ql/experimental/commodities/commoditycurve.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) 2008 J. Erik Radmall
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
 <https://www.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
/*! \file commoditycurve.hpp
21
    \brief Commodity curve
22
*/
23
24
#ifndef quantlib_commodity_curve_hpp
25
#define quantlib_commodity_curve_hpp
26
27
#include <ql/termstructure.hpp>
28
#include <ql/experimental/commodities/commoditytype.hpp>
29
#include <ql/experimental/commodities/unitofmeasure.hpp>
30
#include <ql/experimental/commodities/exchangecontract.hpp>
31
#include <ql/currency.hpp>
32
#include <ql/math/interpolations/forwardflatinterpolation.hpp>
33
#include <ql/time/daycounters/actual365fixed.hpp>
34
35
namespace QuantLib {
36
37
    //! Commodity term structure
38
    class CommodityCurve : public TermStructure {
39
        friend class CommodityIndex;
40
      public:
41
        // constructor
42
        CommodityCurve(std::string name,
43
                       CommodityType commodityType,
44
                       Currency currency,
45
                       UnitOfMeasure unitOfMeasure,
46
                       const Calendar& calendar,
47
                       const std::vector<Date>& dates,
48
                       std::vector<Real> prices,
49
                       const DayCounter& dayCounter = Actual365Fixed());
50
51
        CommodityCurve(std::string name,
52
                       CommodityType commodityType,
53
                       Currency currency,
54
                       UnitOfMeasure unitOfMeasure,
55
                       const Calendar& calendar,
56
                       const DayCounter& dayCounter = Actual365Fixed());
57
58
        //! \name Inspectors
59
        //@{
60
        const std::string& name() const;
61
        const CommodityType& commodityType() const;
62
        const UnitOfMeasure& unitOfMeasure() const;
63
        const Currency& currency() const;
64
        Date maxDate() const override;
65
        const std::vector<Time>& times() const;
66
        const std::vector<Date>& dates() const;
67
        const std::vector<Real>& prices() const;
68
        std::vector<std::pair<Date,Real> > nodes() const;
69
        bool empty() const;
70
71
        void setPrices(std::map<Date, Real>& prices);
72
        void setBasisOfCurve(
73
                       const ext::shared_ptr<CommodityCurve>& basisOfCurve);
74
75
        Real price(
76
               const Date& d,
77
               const ext::shared_ptr<ExchangeContracts>& exchangeContracts,
78
               Integer nearbyOffset) const;
79
        Real basisOfPrice(const Date& d) const;
80
        Date underlyingPriceDate(
81
                const Date& date,
82
                const ext::shared_ptr<ExchangeContracts>& exchangeContracts,
83
                Integer nearbyOffset) const;
84
85
        const ext::shared_ptr<CommodityCurve>& basisOfCurve() const;
86
87
        friend std::ostream& operator<<(std::ostream& out,
88
                                        const CommodityCurve& curve);
89
      protected:
90
        Real basisOfPriceImpl(Time t) const;
91
92
        std::string name_;
93
        CommodityType commodityType_;
94
        UnitOfMeasure unitOfMeasure_;
95
        Currency currency_;
96
        mutable std::vector<Date> dates_;
97
        mutable std::vector<Time> times_;
98
        mutable std::vector<Real> data_;
99
        mutable Interpolation interpolation_;
100
        ForwardFlat interpolator_;
101
        ext::shared_ptr<CommodityCurve> basisOfCurve_;
102
        Real basisOfCurveUomConversionFactor_;
103
104
        Real priceImpl(Time t) const;
105
    };
106
107
108
    // inline definitions
109
110
0
    inline bool operator==(const CommodityCurve& c1, const CommodityCurve& c2) {
111
0
        return c1.name() == c2.name();
112
0
    }
113
114
0
    inline const CommodityType& CommodityCurve::commodityType() const {
115
0
        return commodityType_;
116
0
    }
117
118
0
    inline const UnitOfMeasure& CommodityCurve::unitOfMeasure() const {
119
0
        return unitOfMeasure_;
120
0
    }
121
122
0
    inline const Currency& CommodityCurve::currency() const {
123
0
        return currency_;
124
0
    }
125
126
0
    inline const std::string& CommodityCurve::name() const {
127
0
        return name_;
128
0
    }
129
130
0
    inline Date CommodityCurve::maxDate() const {
131
0
        return dates_.back();
132
0
    }
133
134
0
    inline const std::vector<Time>& CommodityCurve::times() const {
135
0
        return times_;
136
0
    }
137
138
0
    inline const std::vector<Date>& CommodityCurve::dates() const {
139
0
        return dates_;
140
0
    }
141
142
0
    inline const std::vector<Real>& CommodityCurve::prices() const {
143
0
        return data_;
144
0
    }
145
146
0
    inline bool CommodityCurve::empty() const {
147
0
        return dates_.empty();
148
0
    }
149
150
    inline const ext::shared_ptr<CommodityCurve>&
151
0
    CommodityCurve::basisOfCurve() const {
152
0
        return basisOfCurve_;
153
0
    }
154
155
0
    inline std::vector<std::pair<Date,Real> > CommodityCurve::nodes() const {
156
0
        std::vector<std::pair<Date,Real> > results(dates_.size());
157
0
        for (Size i = 0; i < dates_.size(); ++i)
158
0
            results[i] = std::make_pair(dates_[i], data_[i]);
159
0
        return results;
160
0
    }
161
162
0
    inline Real CommodityCurve::basisOfPrice(const Date& d) const {
163
0
        Time t = timeFromReference(d);
164
0
        return basisOfPriceImpl(t);
165
0
    }
166
167
    // gets a price that can include an arbitrary number of basis curves
168
    inline Real CommodityCurve::price(
169
                const Date& d,
170
                const ext::shared_ptr<ExchangeContracts>& exchangeContracts,
171
0
                Integer nearbyOffset) const {
172
0
        Date date = nearbyOffset > 0 ?
173
0
            underlyingPriceDate(d, exchangeContracts, nearbyOffset) : d;
174
0
        Time t = timeFromReference(date);
175
0
        Real priceValue = 0;
176
0
        try {
177
0
            priceValue = priceImpl(t);
178
0
        } catch (const std::exception& e) {
179
0
            QL_FAIL("error retrieving price for curve [" << name() << "]: "
180
0
                    << e.what());
181
0
        }
182
0
        return priceValue + basisOfPriceImpl(t);
183
0
    }
184
185
    // get the date for the underlying price, in the case of nearby
186
    // curves, rolls on the underlying contract expiry
187
    inline Date CommodityCurve::underlyingPriceDate(
188
                const Date& date,
189
                const ext::shared_ptr<ExchangeContracts>& exchangeContracts,
190
0
                Integer nearbyOffset) const {
191
0
        QL_REQUIRE(nearbyOffset > 0, "nearby offset must be > 0");
192
0
        auto ic =
193
0
            exchangeContracts->lower_bound(date);
194
0
        if (ic != exchangeContracts->end()) {
195
0
            for (int i = 0; i < nearbyOffset-1 && ic!=exchangeContracts->end(); ++i)
196
0
                ++ic;
197
0
            QL_REQUIRE(ic != exchangeContracts->end(),
198
0
                       "not enough nearby contracts available for curve ["
199
0
                       << name() << "] for date [" << date << "].");
200
0
            return ic->second.underlyingStartDate();
201
0
        }
202
0
        return date;
203
0
    }
204
205
0
    inline Real CommodityCurve::basisOfPriceImpl(Time t) const {
206
0
        if (basisOfCurve_ != nullptr) {
207
0
            Real basisCurvePriceValue = 0;
208
0
            try {
209
0
                basisCurvePriceValue =
210
0
                    basisOfCurve_->priceImpl(t)
211
0
                    * basisOfCurveUomConversionFactor_;
212
0
            } catch (const std::exception& e) {
213
0
                QL_FAIL("error retrieving price for curve [" << name() <<
214
0
                        "]: " << e.what());
215
0
            }
216
0
            return basisCurvePriceValue + basisOfCurve_->basisOfPriceImpl(t);
217
0
        }
218
0
        return 0;
219
0
    }
220
221
0
    inline Real CommodityCurve::priceImpl(Time t) const {
222
0
        return interpolation_(t, true);
223
0
    }
224
225
}
226
227
228
#endif