Skip to content

Commit 858d12a

Browse files
authored
Add Philippines calendar (#2789)
2 parents 3d21442 + 2ffade2 commit 858d12a

8 files changed

Lines changed: 447 additions & 0 deletions

File tree

QuantLib.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,7 @@
18611861
<ClInclude Include="ql\time\calendars\northmacedonia.hpp" />
18621862
<ClInclude Include="ql\time\calendars\norway.hpp" />
18631863
<ClInclude Include="ql\time\calendars\nullcalendar.hpp" />
1864+
<ClInclude Include="ql\time\calendars\philippines.hpp" />
18641865
<ClInclude Include="ql\time\calendars\poland.hpp" />
18651866
<ClInclude Include="ql\time\calendars\romania.hpp" />
18661867
<ClInclude Include="ql\time\calendars\russia.hpp" />
@@ -2886,6 +2887,7 @@
28862887
<ClCompile Include="ql\time\calendars\newzealand.cpp" />
28872888
<ClCompile Include="ql\time\calendars\northmacedonia.cpp" />
28882889
<ClCompile Include="ql\time\calendars\norway.cpp" />
2890+
<ClCompile Include="ql\time\calendars\philippines.cpp" />
28892891
<ClCompile Include="ql\time\calendars\poland.cpp" />
28902892
<ClCompile Include="ql\time\calendars\romania.cpp" />
28912893
<ClCompile Include="ql\time\calendars\russia.cpp" />

QuantLib.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,9 @@
29972997
<ClInclude Include="ql\time\calendars\nullcalendar.hpp">
29982998
<Filter>time\calendars</Filter>
29992999
</ClInclude>
3000+
<ClInclude Include="ql\time\calendars\philippines.hpp">
3001+
<Filter>time\calendars</Filter>
3002+
</ClInclude>
30003003
<ClInclude Include="ql\time\calendars\poland.hpp">
30013004
<Filter>time\calendars</Filter>
30023005
</ClInclude>
@@ -6359,6 +6362,9 @@
63596362
<ClCompile Include="ql\time\calendars\norway.cpp">
63606363
<Filter>time\calendars</Filter>
63616364
</ClCompile>
6365+
<ClCompile Include="ql\time\calendars\philippines.cpp">
6366+
<Filter>time\calendars</Filter>
6367+
</ClCompile>
63626368
<ClCompile Include="ql\time\calendars\poland.cpp">
63636369
<Filter>time\calendars</Filter>
63646370
</ClCompile>

ql/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ set(QL_SOURCES
940940
time/calendars/newzealand.cpp
941941
time/calendars/northmacedonia.cpp
942942
time/calendars/norway.cpp
943+
time/calendars/philippines.cpp
943944
time/calendars/poland.cpp
944945
time/calendars/romania.cpp
945946
time/calendars/russia.cpp
@@ -2263,6 +2264,7 @@ set(QL_HEADERS
22632264
time/calendars/northmacedonia.hpp
22642265
time/calendars/norway.hpp
22652266
time/calendars/nullcalendar.hpp
2267+
time/calendars/philippines.hpp
22662268
time/calendars/poland.hpp
22672269
time/calendars/romania.hpp
22682270
time/calendars/russia.hpp

ql/time/calendars/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ this_include_HEADERS = \
3737
northmacedonia.hpp \
3838
norway.hpp \
3939
nullcalendar.hpp \
40+
philippines.hpp \
4041
poland.hpp \
4142
romania.hpp \
4243
russia.hpp \
@@ -92,6 +93,7 @@ cpp_files = \
9293
newzealand.cpp \
9394
northmacedonia.cpp \
9495
norway.cpp \
96+
philippines.cpp \
9597
poland.cpp \
9698
romania.cpp \
9799
russia.cpp \

ql/time/calendars/all.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <ql/time/calendars/northmacedonia.hpp>
3535
#include <ql/time/calendars/norway.hpp>
3636
#include <ql/time/calendars/nullcalendar.hpp>
37+
#include <ql/time/calendars/philippines.hpp>
3738
#include <ql/time/calendars/poland.hpp>
3839
#include <ql/time/calendars/romania.hpp>
3940
#include <ql/time/calendars/russia.hpp>

ql/time/calendars/philippines.cpp

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/*
4+
Copyright (C) 2026 Lawrenz Law
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+
#include <ql/time/calendars/philippines.hpp>
21+
#include <algorithm>
22+
#include <vector>
23+
24+
namespace QuantLib {
25+
26+
namespace {
27+
28+
// Holidays that cannot be derived from a rule: the Islamic and
29+
// Chinese festivals, the additional special (non-working) days
30+
// proclaimed in a given year only, election days, and the days on
31+
// which the exchange itself was closed.
32+
bool isTabulatedPhilippineHoliday(const Date& date) {
33+
static const std::vector<Date> holidays = {
34+
// 2020
35+
Date(25, January, 2020), // Chinese New Year
36+
Date(25, February, 2020), // EDSA People Power Revolution Anniversary
37+
Date(17, March, 2020), // COVID-19 trading suspension
38+
Date(18, March, 2020), // Market Holiday
39+
Date(25, May, 2020), // Eid'l Fitr
40+
Date(31, July, 2020), // Eid'l Adha
41+
Date(2, November, 2020), // All Souls' Day
42+
Date(12, November, 2020), // No Trading
43+
Date(24, December, 2020), // Christmas Eve
44+
// 2021
45+
Date(12, February, 2021), // Chinese New Year
46+
Date(25, February, 2021), // EDSA People Power Revolution Anniversary
47+
Date(13, May, 2021), // Eid'l Fitr
48+
Date(20, July, 2021), // Eid'l Adha
49+
// 2022
50+
Date(1, February, 2022), // Chinese New Year
51+
Date(25, February, 2022), // EDSA People Power Revolution Anniversary
52+
Date(3, May, 2022), // Eid'l Fitr
53+
Date(9, May, 2022), // National and local elections
54+
Date(10, July, 2022), // Eid'l Adha
55+
Date(26, September, 2022), // No Trading
56+
Date(31, October, 2022), // Additional special (non-working) day
57+
Date(26, December, 2022), // Additional special (non-working) day
58+
// 2023
59+
Date(2, January, 2023), // Additional special (non-working) day
60+
Date(24, February, 2023), // EDSA anniversary, in lieu of February 25th
61+
Date(10, April, 2023), // Araw ng Kagitingan, in lieu of April 9th
62+
Date(21, April, 2023), // Eid'l Fitr
63+
Date(28, June, 2023), // Eid'l Adha
64+
Date(30, October, 2023), // Barangay and Sangguniang Kabataan elections
65+
Date(2, November, 2023), // All Souls' Day
66+
Date(27, November, 2023), // Bonifacio Day, in lieu of November 30th
67+
Date(26, December, 2023), // Additional special (non-working) day
68+
// 2024
69+
Date(9, February, 2024), // Additional special (non-working) day
70+
Date(10, February, 2024), // Chinese New Year
71+
Date(10, April, 2024), // Eid'l Fitr
72+
Date(17, June, 2024), // Eid'l Adha
73+
Date(24, July, 2024), // Closed - Typhoon
74+
Date(23, August, 2024), // Ninoy Aquino Day, in lieu of August 21st
75+
Date(2, November, 2024), // All Souls' Day
76+
Date(24, December, 2024), // Christmas Eve
77+
// 2025
78+
Date(29, January, 2025), // Chinese New Year
79+
Date(1, April, 2025), // Eid'l Fitr
80+
Date(12, May, 2025), // National and local elections
81+
Date(6, June, 2025), // Eid'l Adha
82+
Date(27, July, 2025), // Founding anniversary of the Iglesia ni Cristo
83+
Date(31, October, 2025), // Additional special (non-working) day
84+
Date(24, December, 2025), // Christmas Eve
85+
// 2026
86+
Date(17, February, 2026), // Chinese New Year
87+
Date(20, March, 2026), // Eid'l Fitr
88+
Date(27, May, 2026), // Eid'l Adha
89+
Date(2, November, 2026), // All Souls' Day
90+
Date(24, December, 2026), // Christmas Eve
91+
// 2027
92+
Date(6, February, 2027), // Chinese New Year
93+
Date(10, March, 2027), // Eid'l Fitr
94+
Date(17, May, 2027), // Eid'l Adha
95+
};
96+
return std::binary_search(holidays.begin(), holidays.end(), date);
97+
}
98+
99+
// Rule-based holidays that a proclamation moved to another date or
100+
// turned into a special working day for one year only.
101+
bool isWithdrawnPhilippineHoliday(const Date& date) {
102+
static const std::vector<Date> withdrawn = {
103+
Date(31, December, 2021), // declared a special working day
104+
Date(30, November, 2023), // Bonifacio Day moved to November 27th
105+
Date(21, August, 2024), // Ninoy Aquino Day moved to August 23rd
106+
};
107+
return std::binary_search(withdrawn.begin(), withdrawn.end(), date);
108+
}
109+
110+
}
111+
112+
Philippines::Philippines(Market) {
113+
// all calendar instances share the same implementation instance
114+
static ext::shared_ptr<Calendar::Impl> impl(new Philippines::PseImpl);
115+
impl_ = impl;
116+
}
117+
118+
bool Philippines::PseImpl::isBusinessDay(const Date& date) const {
119+
Weekday w = date.weekday();
120+
Day d = date.dayOfMonth(), dd = date.dayOfYear();
121+
Month m = date.month();
122+
Year y = date.year();
123+
Day em = easterMonday(y);
124+
125+
if (isWeekend(w))
126+
return false;
127+
128+
if (isWithdrawnPhilippineHoliday(date))
129+
return true;
130+
131+
if ( // New Year's Day
132+
(d == 1 && m == January)
133+
// Maundy Thursday
134+
|| (dd == em - 4)
135+
// Good Friday
136+
|| (dd == em - 3)
137+
// Araw ng Kagitingan (Day of Valor)
138+
|| (d == 9 && m == April)
139+
// Labor Day
140+
|| (d == 1 && m == May)
141+
// Independence Day
142+
|| (d == 12 && m == June)
143+
// Ninoy Aquino Day (a special non-working day since RA 9256)
144+
|| (d == 21 && m == August && y >= 2004)
145+
// National Heroes Day (the last Monday of August)
146+
|| (d >= 25 && m == August && w == Monday)
147+
// All Saints' Day
148+
|| (d == 1 && m == November)
149+
// Bonifacio Day
150+
|| (d == 30 && m == November)
151+
// Feast of the Immaculate Conception (since RA 10966)
152+
|| (d == 8 && m == December && y >= 2018)
153+
// Christmas Day
154+
|| (d == 25 && m == December)
155+
// Rizal Day
156+
|| (d == 30 && m == December)
157+
// Last Day of the Year
158+
|| (d == 31 && m == December))
159+
return false;
160+
161+
return !isTabulatedPhilippineHoliday(date);
162+
}
163+
164+
}

ql/time/calendars/philippines.hpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/*
4+
Copyright (C) 2026 Lawrenz Law
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 philippines.hpp
21+
\brief Philippine calendar
22+
*/
23+
24+
#ifndef quantlib_philippines_calendar_hpp
25+
#define quantlib_philippines_calendar_hpp
26+
27+
#include <ql/time/calendar.hpp>
28+
29+
namespace QuantLib {
30+
31+
//! Philippine calendar
32+
/*! Holidays for the Philippine Stock Exchange.
33+
34+
The exchange is closed on both classes of holiday defined by the
35+
Labor Code, the regular holidays and the special (non-working) days,
36+
which are also the days on which banks supervised by the Bangko
37+
Sentral ng Pilipinas are closed. The list additionally contains a few
38+
dates on which the exchange alone suspended trading, so it is not a
39+
banking calendar.
40+
41+
Holidays with a fixed date or a computable rule:
42+
<ul>
43+
<li>Saturdays</li>
44+
<li>Sundays</li>
45+
<li>New Year's Day, January 1st</li>
46+
<li>Maundy Thursday</li>
47+
<li>Good Friday</li>
48+
<li>Araw ng Kagitingan (Day of Valor), April 9th</li>
49+
<li>Labor Day, May 1st</li>
50+
<li>Independence Day, June 12th</li>
51+
<li>Ninoy Aquino Day, August 21st (a special non-working day since
52+
RA 9256 of 2004)</li>
53+
<li>National Heroes Day, the last Monday of August</li>
54+
<li>All Saints' Day, November 1st</li>
55+
<li>Bonifacio Day, November 30th</li>
56+
<li>Feast of the Immaculate Conception, December 8th (a special
57+
non-working day since RA 10966 of 2017)</li>
58+
<li>Christmas Day, December 25th</li>
59+
<li>Rizal Day, December 30th</li>
60+
<li>Last Day of the Year, December 31st</li>
61+
</ul>
62+
63+
Black Saturday is proclaimed a special (non-working) day every year,
64+
but by construction it always falls on a Saturday and so is already
65+
covered by the weekend rule.
66+
67+
Holidays with no fixed rule, tabulated for 2020 to 2027:
68+
<ul>
69+
<li>Eid'l Fitr</li>
70+
<li>Eid'l Adha</li>
71+
<li>Chinese New Year (a special non-working day since 2012)</li>
72+
<li>All Souls' Day and Christmas Eve, which are proclaimed in most
73+
but not all years</li>
74+
<li>EDSA People Power Revolution Anniversary, a special non-working
75+
day up to 2023 and a special working day from 2025</li>
76+
<li>Election days</li>
77+
<li>One-off additional special non-working days, and the two days on
78+
which the exchange was closed by the COVID-19 trading suspension
79+
of March 2020</li>
80+
</ul>
81+
82+
A handful of the rule-based holidays above were transferred to another
83+
date by proclamation (Bonifacio Day in 2023, Ninoy Aquino Day in 2024)
84+
or downgraded to a special working day (the Last Day of the Year in
85+
2021); those years are handled as explicit exceptions.
86+
87+
The Islamic festivals, Chinese New Year and the additional special
88+
days are set each year by presidential proclamation rather than by
89+
rule, so they are tabulated from the published proclamations rather
90+
than computed. Outside the tabulated range only the rule-based
91+
holidays above are returned. The 2027 proclamation had not been
92+
issued when this calendar was written, so the 2027 entries cover only
93+
the festivals whose dates can be predicted (Chinese New Year and the
94+
two Islamic festivals, the latter still subject to moon sighting);
95+
any additional special (non-working) day declared for that year is
96+
missing. The rules also predate the
97+
"holiday economics" transfers of RA 9492, so years before 2011 are
98+
not reliable.
99+
100+
Holiday dates compiled from the presidential proclamations published
101+
by the Official Gazette and the Presidential Communications Office
102+
(Proclamations 845 s.2019, 986 and 1107 s.2021, 1236 s.2021, 1357
103+
s.2022, 42 and 90 s.2022, 167 and 425 s.2023, 368 and 665 s.2024,
104+
727 s.2024 and 1006 s.2025), cross-checked against
105+
<https://www.officeholidays.com/countries/philippines>. They should
106+
be verified against the trading calendar published by the Philippine
107+
Stock Exchange at <https://www.pse.com.ph/> before being relied upon.
108+
109+
\ingroup calendars
110+
*/
111+
class Philippines : public Calendar {
112+
private:
113+
class PseImpl final : public Calendar::WesternImpl {
114+
public:
115+
std::string name() const override { return "Philippine stock exchange"; }
116+
bool isBusinessDay(const Date&) const override;
117+
};
118+
119+
public:
120+
enum Market {
121+
PSE //!< Philippine Stock Exchange
122+
};
123+
explicit Philippines(Market m = PSE);
124+
};
125+
126+
}
127+
128+
#endif

0 commit comments

Comments
 (0)