Coverage Report

Created: 2025-08-28 06:30

/src/quantlib/ql/time/daycounters/business252.cpp
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 Piter Dias
5
 Copyright (C) 2011 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
#include <ql/time/daycounters/business252.hpp>
22
#include <map>
23
24
namespace QuantLib {
25
26
    namespace {
27
28
        typedef std::map<Year, std::map<Month, Date::serial_type> > Cache;
29
        typedef std::map<Year, Date::serial_type> OuterCache;
30
        
31
        std::map<std::string, Cache> monthlyFigures_;
32
        std::map<std::string, OuterCache> yearlyFigures_;
33
34
0
        bool sameYear(const Date& d1, const Date& d2) {
35
0
            return d1.year() == d2.year();
36
0
        }
37
38
0
        bool sameMonth(const Date& d1, const Date& d2) {
39
0
            return d1.year() == d2.year() && d1.month() == d2.month();
40
0
        }
41
42
        Date::serial_type businessDays(Cache& cache,
43
                                       const Calendar& calendar,
44
0
                                       Month month, Year year) {
45
0
            if (cache[year][month] == 0) {
46
                // calculate and store.
47
0
                Date d1 = Date(1,month,year);
48
0
                Date d2 = d1 + 1*Months;
49
0
                cache[year][month] = calendar.businessDaysBetween(d1, d2);
50
0
            }
51
0
            return cache[year][month];
52
0
        }
53
54
        Date::serial_type businessDays(OuterCache& outerCache,
55
                                       Cache& cache,
56
                                       const Calendar& calendar,
57
0
                                       Year year) {
58
0
            if (outerCache[year] == 0) {
59
                // calculate and store.
60
0
                Date::serial_type total = 0;
61
0
                for (Integer i=1; i<=12; ++i) {
62
0
                    total += businessDays(cache,calendar,
63
0
                                          Month(i), year);
64
0
                }
65
0
                outerCache[year] = total;
66
0
            }
67
0
            return outerCache[year];
68
0
        }
69
70
    }
71
72
0
    std::string Business252::Impl::name() const {
73
0
        std::ostringstream out;
74
0
        out << "Business/252(" << calendar_.name() << ")";
75
0
        return out.str();
76
0
    }
77
78
    Date::serial_type Business252::Impl::dayCount(const Date& d1,
79
0
                                                  const Date& d2) const {
80
0
        if (sameMonth(d1,d2) || d1 >= d2) {
81
            // we treat the case of d1 > d2 here, since we'd need a
82
            // second cache to get it right (our cached figures are
83
            // for first included, last excluded and might have to be
84
            // changed going the other way.)
85
0
            return calendar_.businessDaysBetween(d1, d2);
86
0
        } else if (sameYear(d1,d2)) {
87
0
            Cache& cache = monthlyFigures_[calendar_.name()];
88
0
            Date::serial_type total = 0;
89
0
            Date d;
90
            // first, we get to the beginning of next month.
91
0
            d = Date(1,d1.month(),d1.year()) + 1*Months;
92
0
            total += calendar_.businessDaysBetween(d1, d);
93
            // then, we add any whole months (whose figures might be
94
            // cached already) in the middle of our period.
95
0
            while (!sameMonth(d,d2)) {
96
0
                total += businessDays(cache, calendar_,
97
0
                                      d.month(), d.year());
98
0
                d += 1*Months;
99
0
            }
100
            // finally, we get to the end of the period.
101
0
            total += calendar_.businessDaysBetween(d, d2);
102
0
            return total;
103
0
        } else {
104
0
            Cache& cache = monthlyFigures_[calendar_.name()];
105
0
            OuterCache& outerCache = yearlyFigures_[calendar_.name()];
106
0
            Date::serial_type total = 0;
107
0
            Date d;
108
            // first, we get to the beginning of next year.
109
            // The first bit gets us to the end of this month...
110
0
            d = Date(1,d1.month(),d1.year()) + 1*Months;
111
0
            total += calendar_.businessDaysBetween(d1, d);
112
            // ...then we add any remaining months, possibly cached
113
0
            for (Integer m = Integer(d1.month())+1; m <= 12; ++m) {
114
0
                total += businessDays(cache, calendar_,
115
0
                                      Month(m), d.year());
116
0
            }
117
            // then, we add any whole year in the middle of our period.
118
0
            d = Date(1,January,d1.year()+1);
119
0
            while (!sameYear(d,d2)) {
120
0
                total += businessDays(outerCache, cache,
121
0
                                      calendar_, d.year());
122
0
                d += 1*Years;
123
0
            }
124
            // finally, we get to the end of the period.
125
            // First, we add whole months...
126
0
            for (Integer m = 1; m<Integer(d2.month()); ++m) {
127
0
                total += businessDays(cache, calendar_,
128
0
                                      Month(m), d2.year());
129
0
            }
130
            // ...then the last bit.
131
0
            d = Date(1,d2.month(),d2.year());
132
0
            total += calendar_.businessDaysBetween(d, d2);
133
0
            return total;
134
0
        }
135
0
    }
136
137
    Time Business252::Impl::yearFraction(const Date& d1,
138
                                         const Date& d2,
139
                                         const Date&,
140
0
                                         const Date&) const {
141
0
        return dayCount(d1, d2)/252.0;
142
0
    }
143
144
}