Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/timeseries.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) 2006 Joseph Wang
5
 Copyright (C) 2010 Liquidnet Holdings, Inc.
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 timeseries.hpp
22
    \brief Container for historical data
23
*/
24
25
#ifndef quantlib_timeseries_hpp
26
#define quantlib_timeseries_hpp
27
28
#include <ql/time/date.hpp>
29
#include <ql/utilities/null.hpp>
30
#include <ql/errors.hpp>
31
#include <ql/functional.hpp>
32
#include <boost/iterator/transform_iterator.hpp>
33
#include <iterator>
34
#include <algorithm>
35
#include <map>
36
#include <vector>
37
#include <type_traits>
38
39
namespace QuantLib {
40
41
    //! Container for historical data
42
    /*! This class acts as a generic repository for a set of
43
        historical data.  Any single datum can be accessed through its
44
        date, while sets of consecutive data can be accessed through
45
        iterators.
46
47
        \pre The <c>Container</c> type must satisfy the requirements
48
             set by the C++ standard for associative containers.
49
    */
50
    template <class T, class Container = std::map<Date, T> >
51
    class TimeSeries {
52
      public:
53
        typedef Date key_type;
54
        typedef T value_type;
55
      private:
56
        mutable Container values_;
57
      public:
58
        /*! Default constructor */
59
0
        TimeSeries() = default;
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::TimeSeries()
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::TimeSeries()
60
        /*! This constructor initializes the history with a set of
61
            values passed as two sequences, the first containing dates
62
            and the second containing corresponding values.
63
        */
64
        template <class DateIterator, class ValueIterator>
65
        TimeSeries(DateIterator dBegin, DateIterator dEnd,
66
0
                   ValueIterator vBegin) {
67
0
            while (dBegin != dEnd)
68
0
                values_[*(dBegin++)] = *(vBegin++);
69
0
        }
70
        /*! This constructor initializes the history with a set of
71
            values. Such values are assigned to a corresponding number
72
            of consecutive dates starting from <b><i>firstDate</i></b>
73
            included.
74
        */
75
        template <class ValueIterator>
76
        TimeSeries(const Date& firstDate,
77
                   ValueIterator begin, ValueIterator end) {
78
            Date d = firstDate;
79
            while (begin != end)
80
                values_[d++] = *(begin++);
81
        }
82
        //! \name Inspectors
83
        //@{
84
        //! returns the first date for which a historical datum exists
85
        Date firstDate() const;
86
        //! returns the last date for which a historical datum exists
87
        Date lastDate() const;
88
        //! returns the number of historical data including null ones
89
        Size size() const;
90
        //! returns whether the series contains any data
91
        bool empty() const;
92
        //@}
93
        //! \name Historical data access
94
        //@{
95
        //! returns the (possibly null) datum corresponding to the given date
96
0
        T operator[](const Date& d) const {
97
0
            auto found = values_.find(d);
98
0
            if (found == values_.cend())
99
0
                return Null<T>();
100
0
            return found->second;
101
0
        }
102
0
        T& operator[](const Date& d) {
103
0
            auto found = values_.insert(std::pair<Date, T>(d, Null<T>())).first;
104
0
            return found->second;
105
0
        }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::operator[](QuantLib::Date const&)
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::operator[](QuantLib::Date const&)
106
        //@}
107
108
        //! \name Iterators
109
        //@{
110
        typedef typename Container::const_iterator const_iterator;
111
        typedef typename const_iterator::iterator_category iterator_category;
112
113
        // Reverse iterators
114
        // The following class makes compilation fail for the code
115
        // that calls rbegin or rend with a container that does not
116
        // support reverse iterators.  All the rest TimeSeries class
117
        // features should compile and work for this type of
118
        // containers.
119
        template <class container, class iterator_category>
120
        struct reverse {
121
            typedef std::reverse_iterator<typename container::const_iterator>
122
                                                       const_reverse_iterator;
123
            reverse(const container& c) : c_(c) {}
124
            const_reverse_iterator rbegin() const {
125
                return const_reverse_iterator(c_.end());
126
            }
127
            const_reverse_iterator rend() const {
128
                return const_reverse_iterator(c_.begin());
129
            }
130
            const container& c_;
131
        };
132
133
        // This class defines reverse iterator features via
134
        // container's native calls.
135
        template <class container>
136
        struct reverse<container, std::bidirectional_iterator_tag> {
137
            typedef typename container::const_reverse_iterator
138
                                                       const_reverse_iterator;
139
0
            reverse(const container& c) : c_(c) {}
140
0
            const_reverse_iterator rbegin() const { return c_.rbegin(); }
141
            const_reverse_iterator rend() const { return c_.rend(); }
142
            const container& c_;
143
        };
144
145
        // The following typedef enables reverse iterators for
146
        // bidirectional_iterator_tag category.
147
        typedef std::conditional_t<
148
                std::is_same_v<iterator_category, std::bidirectional_iterator_tag> ||
149
                std::is_base_of_v<std::bidirectional_iterator_tag, iterator_category>,
150
            std::bidirectional_iterator_tag, std::input_iterator_tag> enable_reverse;
151
152
        typedef typename
153
        reverse<Container, enable_reverse>::const_reverse_iterator
154
                                                       const_reverse_iterator;
155
156
        const_iterator cbegin() const;
157
        const_iterator cend() const;
158
0
        const_iterator begin() const { return cbegin(); }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::begin() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::begin() const
159
0
        const_iterator end() const { return cend(); }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::end() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::end() const
160
0
        const_reverse_iterator crbegin() const {
161
0
            return reverse<Container, enable_reverse>(values_).rbegin();
162
0
        }
163
        const_reverse_iterator crend() const {
164
            return reverse<Container, enable_reverse>(values_).rend();
165
        }
166
0
        const_reverse_iterator rbegin() const { return crbegin(); }
167
        const_reverse_iterator rend() const { return crend(); }
168
        //@}
169
170
      private:
171
        typedef typename Container::value_type container_value_type;
172
        typedef std::function<Date(const container_value_type&)>
173
                                                              projection_time;
174
        typedef std::function<T(const container_value_type&)>
175
                                                             projection_value;
176
177
      public:
178
        //! \name Utilities
179
        //@{
180
        const_iterator find(const Date&);
181
        //! returns the dates for which historical data exist
182
        std::vector<Date> dates() const;
183
        //! returns the historical data
184
        std::vector<T> values() const;
185
        //@}
186
187
      private:
188
0
        static const Date& get_time (const container_value_type& v) {
189
0
            return v.first;
190
0
        }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::get_time(std::__1::pair<QuantLib::Date const, double> const&)
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::get_time(std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> const&)
191
0
        static const T& get_value (const container_value_type& v) {
192
0
            return v.second;
193
0
        }
194
    };
195
196
197
    // inline definitions
198
199
    template <class T, class C>
200
    inline Date TimeSeries<T,C>::firstDate() const {
201
        QL_REQUIRE(!values_.empty(), "empty timeseries");
202
        return values_.begin()->first;
203
    }
204
205
    template <class T, class C>
206
0
    inline Date TimeSeries<T,C>::lastDate() const {
207
0
        QL_REQUIRE(!values_.empty(), "empty timeseries");
208
0
        return rbegin()->first;
209
0
    }
210
211
    template <class T, class C>
212
0
    inline Size TimeSeries<T,C>::size() const {
213
0
        return values_.size();
214
0
    }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::size() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::size() const
215
216
    template <class T, class C>
217
0
    inline bool TimeSeries<T,C>::empty() const {
218
0
        return values_.empty();
219
0
    }
220
221
    template <class T, class C>
222
    inline typename TimeSeries<T,C>::const_iterator
223
0
    TimeSeries<T,C>::cbegin() const {
224
0
        return values_.begin();
225
0
    }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::cbegin() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::cbegin() const
226
227
    template <class T, class C>
228
    inline typename TimeSeries<T,C>::const_iterator
229
0
    TimeSeries<T,C>::cend() const {
230
0
        return values_.end();
231
0
    }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::cend() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::cend() const
232
233
    template <class T, class C>
234
    inline typename TimeSeries<T,C>::const_iterator
235
    TimeSeries<T,C>::find(const Date& d) {
236
        auto i = values_.find(d);
237
        if (i == values_.end()) {
238
            values_[d] = Null<T>();
239
            i = values_.find(d);
240
        }
241
        return i;
242
    }
243
244
    template <class T, class C>
245
0
    std::vector<Date> TimeSeries<T,C>::dates() const {
246
0
        std::vector<Date> v;
247
0
        v.reserve(size());
248
0
        std::transform(cbegin(), cend(), std::back_inserter(v),
249
0
                       TimeSeries<T,C>::get_time);
250
0
        return v;
251
0
    }
Unexecuted instantiation: QuantLib::TimeSeries<double, std::__1::map<QuantLib::Date, double, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, double> > > >::dates() const
Unexecuted instantiation: QuantLib::TimeSeries<QuantLib::IntervalPrice, std::__1::map<QuantLib::Date, QuantLib::IntervalPrice, std::__1::less<QuantLib::Date>, std::__1::allocator<std::__1::pair<QuantLib::Date const, QuantLib::IntervalPrice> > > >::dates() const
252
253
    template <class T, class C>
254
0
    std::vector<T> TimeSeries<T,C>::values() const {
255
0
        std::vector<T> v;
256
0
        v.reserve(size());
257
0
        std::transform(cbegin(), cend(), std::back_inserter(v),
258
0
                       TimeSeries<T,C>::get_value);
259
0
        return v;
260
0
    }
261
262
}
263
264
#endif