Coverage Report

Created: 2026-06-08 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/time/daycounters/business252.cpp
Line
Count
Source
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
 <https://www.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
65.6k
        bool sameYear(const Date& d1, const Date& d2) {
35
65.6k
            return d1.year() == d2.year();
36
65.6k
        }
37
38
1.09k
        bool sameMonth(const Date& d1, const Date& d2) {
39
1.09k
            return d1.year() == d2.year() && d1.month() == d2.month();
40
1.09k
        }
41
42
        Date::serial_type businessDays(Cache& cache,
43
                                       const Calendar& calendar,
44
57.9k
                                       Month month, Year year) {
45
57.9k
            if (cache[year][month] == 0) {
46
                // calculate and store.
47
48.9k
                Date d1 = Date(1,month,year);
48
48.9k
                Date d2 = d1 + 1*Months;
49
48.9k
                cache[year][month] = calendar.businessDaysBetween(d1, d2);
50
48.9k
            }
51
57.9k
            return cache[year][month];
52
57.9k
        }
53
54
        Date::serial_type businessDays(OuterCache& outerCache,
55
                                       Cache& cache,
56
                                       const Calendar& calendar,
57
63.9k
                                       Year year) {
58
63.9k
            if (outerCache[year] == 0) {
59
                // calculate and store.
60
4.05k
                Date::serial_type total = 0;
61
52.7k
                for (Integer i=1; i<=12; ++i) {
62
48.6k
                    total += businessDays(cache,calendar,
63
48.6k
                                          Month(i), year);
64
48.6k
                }
65
4.05k
                outerCache[year] = total;
66
4.05k
            }
67
63.9k
            return outerCache[year];
68
63.9k
        }
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
878
                                                  const Date& d2) const {
80
878
        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
12
            return calendar_.businessDaysBetween(d1, d2);
86
866
        } else if (sameYear(d1,d2)) {
87
56
            Cache& cache = monthlyFigures_[calendar_.name()];
88
56
            Date::serial_type total = 0;
89
56
            Date d;
90
            // first, we get to the beginning of next month.
91
56
            d = Date(1,d1.month(),d1.year()) + 1*Months;
92
56
            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
218
            while (!sameMonth(d,d2)) {
96
162
                total += businessDays(cache, calendar_,
97
162
                                      d.month(), d.year());
98
162
                d += 1*Months;
99
162
            }
100
            // finally, we get to the end of the period.
101
56
            total += calendar_.businessDaysBetween(d, d2);
102
56
            return total;
103
810
        } else {
104
810
            Cache& cache = monthlyFigures_[calendar_.name()];
105
810
            OuterCache& outerCache = yearlyFigures_[calendar_.name()];
106
810
            Date::serial_type total = 0;
107
810
            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
810
            d = Date(1,d1.month(),d1.year()) + 1*Months;
111
810
            total += calendar_.businessDaysBetween(d1, d);
112
            // ...then we add any remaining months, possibly cached
113
6.14k
            for (Integer m = Integer(d1.month())+1; m <= 12; ++m) {
114
5.33k
                total += businessDays(cache, calendar_,
115
5.33k
                                      Month(m), d.year());
116
5.33k
            }
117
            // then, we add any whole year in the middle of our period.
118
810
            d = Date(1,January,d1.year()+1);
119
64.7k
            while (!sameYear(d,d2)) {
120
63.9k
                total += businessDays(outerCache, cache,
121
63.9k
                                      calendar_, d.year());
122
63.9k
                d += 1*Years;
123
63.9k
            }
124
            // finally, we get to the end of the period.
125
            // First, we add whole months...
126
4.52k
            for (Integer m = 1; m<Integer(d2.month()); ++m) {
127
3.71k
                total += businessDays(cache, calendar_,
128
3.71k
                                      Month(m), d2.year());
129
3.71k
            }
130
            // ...then the last bit.
131
810
            d = Date(1,d2.month(),d2.year());
132
810
            total += calendar_.businessDaysBetween(d, d2);
133
810
            return total;
134
810
        }
135
878
    }
136
137
    Time Business252::Impl::yearFraction(const Date& d1,
138
                                         const Date& d2,
139
                                         const Date&,
140
439
                                         const Date&) const {
141
439
        return dayCount(d1, d2)/252.0;
142
439
    }
143
144
}