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  <http://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 commodityindex.hpp
21     \brief Commodity index
22 */
23 
24 #ifndef quantlib_commodity_index_hpp
25 #define quantlib_commodity_index_hpp
26 
27 #include <ql/experimental/commodities/commoditycurve.hpp>
28 #include <ql/indexes/indexmanager.hpp>
29 
30 namespace QuantLib {
31 
32     class TermStructure;
33 
34     //! base class for commodity indexes
35     class CommodityIndex : public Observable,
36                            public Observer {
37       public:
38         CommodityIndex(
39                 const std::string& name,
40                 const CommodityType& commodityType,
41                 const Currency& currency,
42                 const UnitOfMeasure& unitOfMeasure,
43                 const Calendar& calendar,
44                 Real lotQuantity,
45                 const ext::shared_ptr<CommodityCurve>& forwardCurve,
46                 const ext::shared_ptr<ExchangeContracts>& exchangeContracts,
47                 int nearbyOffset);
48         //! \name Index interface
49         //@{
50         std::string name() const;
51         //@}
52         //! \name Observer interface
53         //@{
54         void update();
55         //@}
56         //! \name Inspectors
57         //@{
58         const CommodityType& commodityType() const;
59         const Currency& currency() const;
60         const UnitOfMeasure& unitOfMeasure() const;
61         const Calendar& calendar() const;
62         const ext::shared_ptr<CommodityCurve>& forwardCurve() const;
63         Real lotQuantity() const;
64 
65         Real price(const Date& date);
66         Real forwardPrice(const Date& date) const;
67         Date lastQuoteDate() const;
68         //@}
69         void addQuote(const Date& quoteDate, Real quote);
70 
addQuotes(const std::map<Date,Real> & quotes)71         void addQuotes(const std::map<Date, Real>& quotes) {
72             std::string tag = name();
73             quotes_ = IndexManager::instance().getHistory(tag);
74             for (std::map<Date, Real>::const_iterator ii = quotes.begin();
75                  ii != quotes.end (); ++ii) {
76                 quotes_[ii->first] = ii->second;
77             }
78             IndexManager::instance().setHistory(tag, quotes_);
79         }
80 
81         void clearQuotes() const;
82         //! returns TRUE if the quote date is valid
83         bool isValidQuoteDate(const Date& quoteDate) const;
84         bool empty() const;
85         bool forwardCurveEmpty() const;
86         const TimeSeries<Real>& quotes() const;
87 
88         friend std::ostream& operator<<(std::ostream&, const CommodityIndex&);
89       protected:
90         std::string name_;
91         CommodityType commodityType_;
92         UnitOfMeasure unitOfMeasure_;
93         Currency currency_;
94         Calendar calendar_;
95         Real lotQuantity_;
96         TimeSeries<Real> quotes_;
97         ext::shared_ptr<CommodityCurve> forwardCurve_;
98         Real forwardCurveUomConversionFactor_;
99         ext::shared_ptr<ExchangeContracts> exchangeContracts_;
100         Integer nearbyOffset_;
101     };
102 
103 
104     // inline definitions
105 
operator ==(const CommodityIndex & i1,const CommodityIndex & i2)106     inline bool operator==(const CommodityIndex& i1, const CommodityIndex& i2) {
107         return i1.name() == i2.name();
108     }
109 
update()110     inline void CommodityIndex::update() {
111         notifyObservers();
112     }
113 
name() const114     inline std::string CommodityIndex::name() const {
115         return name_;
116     }
117 
commodityType() const118     inline const CommodityType& CommodityIndex::commodityType() const {
119         return commodityType_;
120     }
121 
unitOfMeasure() const122     inline const UnitOfMeasure& CommodityIndex::unitOfMeasure() const {
123         return unitOfMeasure_;
124     }
125 
currency() const126     inline const Currency& CommodityIndex::currency() const {
127         return currency_;
128     }
129 
calendar() const130     inline const Calendar& CommodityIndex::calendar() const {
131         return calendar_;
132     }
133 
lotQuantity() const134     inline Real CommodityIndex::lotQuantity() const {
135         return lotQuantity_;
136     }
137 
138     inline const ext::shared_ptr<CommodityCurve>&
forwardCurve() const139     CommodityIndex::forwardCurve() const {
140         return forwardCurve_;
141     }
142 
quotes() const143     inline const TimeSeries<Real>& CommodityIndex::quotes() const {
144         return quotes_;
145     }
146 
price(const Date & date)147     inline Real CommodityIndex::price(const Date& date) {
148         std::map<Date, Real>::const_iterator hq = quotes_.find(date);
149         if (hq->second == Null<Real>()) {
150             ++hq;
151             if (hq == quotes_.end())
152                 //if (hq->second == Null<Real>())
153                 return Null<Real>();
154         }
155         return hq->second;
156     }
157 
forwardPrice(const Date & date) const158     inline Real CommodityIndex::forwardPrice(const Date& date) const {
159         try {
160             Real forwardPrice =
161                 forwardCurve_->price(date, exchangeContracts_, nearbyOffset_);
162             return forwardPrice * forwardCurveUomConversionFactor_;
163         } catch (const std::exception& e) {
164             QL_FAIL("error fetching forward price for index " << name_
165                     << ": " << e.what());
166         }
167     }
168 
lastQuoteDate() const169     inline Date CommodityIndex::lastQuoteDate() const {
170         if (quotes_.empty())
171             return Date::minDate();
172         return quotes_.lastDate();
173     }
174 
empty() const175     inline bool CommodityIndex::empty() const {
176         return quotes_.empty();
177     }
178 
forwardCurveEmpty() const179     inline bool CommodityIndex::forwardCurveEmpty() const {
180         if (forwardCurve_ != 0)
181             return forwardCurve_->empty();
182         return false;
183     }
184 
addQuote(const Date & quoteDate,Real quote)185     inline void CommodityIndex::addQuote(const Date& quoteDate, Real quote) {
186         //QL_REQUIRE(isValidQuoteDate(quoteDate),
187         //           "Quote date " << quoteDate.weekday() << ", " <<
188         //           quoteDate << " is not valid");
189         std::string tag = name();
190         quotes_ = IndexManager::instance().getHistory(tag);
191         quotes_[quoteDate] = quote;
192         IndexManager::instance().setHistory(tag, quotes_);
193     }
194 
clearQuotes() const195     inline void CommodityIndex::clearQuotes() const {
196         IndexManager::instance().clearHistory(name());
197     }
198 
isValidQuoteDate(const Date & quoteDate) const199     inline bool CommodityIndex::isValidQuoteDate(const Date& quoteDate) const {
200         return calendar().isBusinessDay(quoteDate);
201     }
202 
203 }
204 
205 #endif
206