|
| 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 | +} |
0 commit comments