# # Copyright 2019 Quantopian, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from datetime import time from itertools import chain from zoneinfo import ZoneInfo import pandas as pd from pandas.tseries.holiday import GoodFriday, Holiday from .common_holidays import ascension_day, christmas, new_years_day, new_years_eve from .lunisolar_holidays import chinese_lunar_new_year_dates from .exchange_calendar import HolidayCalendar, ExchangeCalendar class XIDXExchangeCalendar(ExchangeCalendar): """ Exchange calendar for the Indonesia Stock Exchange (XIDX). https://www.idx.co.id/en/news/trading-holiday Open Time: 09:00, Western Indonesian Time (WIB) Close Time: 15:50, Western Indonesian Time (WIB) Regularly-Observed Holidays: - New Year's Day(Jan 1) - Good Friday (Friday before Easter) - Labor Day (May 1) - Ascension Day Of Jesus Christ (39 days after Easter, always Thursday) - Pancasila Day (Jun 1) - Independence Day (Aug 17) - Christmas Day (Dec 25) - New Year's Eve (called "Trading Holiday", Dec 31) - Chinese New Year (from Gregorian year 2002 onward) - Islamic New Year - Eid al-Fitr (Festival of Breaking the Fast) - Eid al-Adha (Festival of the Sacrifice) - Isra Mikraj of the Prophet Muhammad - Birth of the Prophet Muhammad - Vesak Day - Hindu Saka New Year (also called Nyepi, or Balinese Day of Silence) Election holidays are also observed, as well as additional "common leave" days around many holidays. """ name = "XIDX" tz = ZoneInfo("Asia/Jakarta") open_times = ((None, time(9)),) close_times = ((None, time(15, 50)),) @property def regular_holidays(self): return HolidayCalendar( [ new_years_day(), GoodFriday, Holiday( "Labor Day", month=5, day=1, start_date="2014-05-01", ), # NOTE: The Indonesia Stock Exchange was open on Ascension # Day 2003, but closed the next day. We are not sure why. # (The 2003-05-30 closure is listed in adhoc_holidays.) ascension_day(end_date="2003"), ascension_day(start_date="2004"), Holiday( "Pancasila Day", month=6, day=1, start_date="2017-06-01", ), Holiday( "Independence Day", month=8, day=17, ), # Christmas Eve is not an official Indonesian holiday, but # December 24th and 26th are frequently observed as common # leave. These dates are listed in adhoc_holidays. christmas(), new_years_eve(), ] ) chinese_new_year = chinese_lunar_new_year_dates[ # The Indonesia Stock Exchange did not close for Chinese New # Year in 1998, 1999, or 2001. (It fell on a Saturday in 2000.) chinese_lunar_new_year_dates.year >= 2002 ] common_leave = pd.to_datetime( [ # Indonesia sometimes observes additional "common leave" days # around the usual observed dates of holidays. # Common leave for New Year's Day. "2002-12-30", "2005-12-30", "2009-01-02", "2017-01-02", "2020-12-31", # Common leave for Chinese New Year. "2008-02-08", "2023-01-23", "2024-02-09", "2025-01-28", "2025-01-29", # Common leave for Ascension Day. "2003-05-30", "2006-05-26", "2007-05-18", "2024-05-10", "2025-05-30", # Common leave for Independence Day. "2003-08-18", "2006-08-18", "2008-08-18", # Common leave for Christmas. "2002-12-24", "2002-12-26", "2003-12-24", "2003-12-26", "2004-12-24", "2005-12-26", "2007-12-24", "2009-12-24", "2010-12-24", "2011-12-26", "2012-12-24", "2013-12-26", "2014-12-26", "2016-12-26", "2017-12-26", "2018-12-24", "2019-12-24", "2020-12-24", "2023-12-26", "2024-12-26", "2025-12-26", ] ) islamic_new_year = pd.to_datetime( [ # Islamic/Hijri/Hijriyah New Year. # Includes common leave. "2002-03-15", "2003-03-03", "2004-02-23", "2005-02-10", "2006-01-31", "2008-01-10", # First Islamic New Year of 2008. "2008-01-11", "2008-12-29", # Second Islamic New Year of 2008. "2009-12-18", "2010-12-07", "2012-11-15", "2012-11-16", "2013-11-05", "2015-10-14", "2017-09-21", "2018-09-11", "2020-08-20", "2021-08-11", "2022-07-30", "2023-07-19", "2024-07-07", "2025-06-27", ] ) eid_al_fitr = pd.to_datetime( [ # Eid al-Fitr (Festival of Breaking the Fast). # Includes common leave. "2002-12-05", "2002-12-06", "2002-12-09", "2002-12-10", "2003-11-24", "2003-11-25", "2003-11-26", "2003-11-27", "2003-11-28", "2004-11-15", "2004-11-16", "2004-11-17", "2004-11-18", "2004-11-19", "2005-11-02", "2005-11-03", "2005-11-04", "2005-11-07", "2005-11-08", "2006-10-23", "2006-10-24", "2006-10-25", "2006-10-26", "2006-10-27", "2007-10-12", "2007-10-15", "2007-10-16", "2008-09-30", "2008-10-01", "2008-10-02", "2008-10-03", "2009-09-18", "2009-09-21", "2009-09-22", "2009-09-23", "2010-09-08", "2010-09-09", "2010-09-10", "2010-09-13", "2010-09-14", "2011-08-29", "2011-08-30", "2011-08-31", "2011-09-01", "2011-09-02", "2012-08-20", "2012-08-21", "2012-08-22", "2013-08-05", "2013-08-06", "2013-08-07", "2013-08-08", "2013-08-09", "2014-07-28", "2014-07-29", "2014-07-30", "2014-07-31", "2014-08-01", "2015-07-16", "2015-07-17", "2015-07-20", "2015-07-21", "2016-07-04", "2016-07-05", "2016-07-06", "2016-07-07", "2016-07-08", "2017-06-23", "2017-06-26", "2017-06-27", "2017-06-28", "2017-06-29", "2017-06-30", "2018-06-11", "2018-06-12", "2018-06-13", "2018-06-14", "2018-06-15", "2018-06-18", "2018-06-19", "2019-06-03", "2019-06-04", "2019-06-05", "2019-06-06", "2019-06-07", "2020-05-22", "2020-05-25", "2020-08-21", "2021-05-12", "2021-05-13", "2021-05-14", "2022-05-02", "2022-05-03", "2023-04-19", "2023-04-20", "2023-04-21", "2023-04-24", "2023-04-25", "2024-04-08", "2024-04-09", "2024-04-10", "2024-04-11", "2024-04-12", "2024-04-15", "2025-03-31", "2025-04-01", "2025-04-02", "2025-04-03", "2025-04-04", "2025-04-07", ] ) eid_al_adha = pd.to_datetime( [ # Eid al-Adha (Festival of the Sacrifice). # Includes common leave. "2002-02-22", "2003-02-12", "2004-02-02", "2005-01-21", "2006-01-10", "2006-12-29", # NOTE: Eid al-Adha occured twice in 2006, on Tuesday 01-10 and # Sunday 12-31. The exchange was closed on Friday 2006-12-29 as # a make-up holiday. "2007-12-20", "2007-12-21", "2008-12-08", "2009-11-27", "2009-11-28", "2010-11-17", "2012-10-26", "2013-10-14", "2013-10-15", "2015-09-24", "2016-09-12", "2017-09-01", "2018-08-22", "2020-07-31", "2021-07-20", "2022-07-09", "2023-06-28", "2023-06-29", "2023-06-30", "2024-06-17", "2024-06-18", "2025-06-06", "2025-06-09", ] ) isra_mikraj = pd.to_datetime( [ # Isra and Mi'raj (Ascension of the Prophet Muhammad). # Called "Isra Mikraj" in Indonesia. # # Occurs on 27 Rajab on the Hijri calendar, but the mapping of # Hijri to Gregorian dates varies. For example, in 2018 many # countries observed this holiday on Friday 04-13; but by # Indonesian reckoning it fell on Saturday 04-14 that year. # # See https://www.idx.co.id/en-us/news/trading-holiday/ # # Includes common leave. "2002-10-04", "2003-09-22", "2004-09-13", "2005-09-02", "2006-08-21", "2008-07-30", "2009-07-20", "2011-06-29", "2012-05-18", "2013-06-06", "2014-05-27", "2016-05-06", "2017-04-24", "2019-04-03", "2020-03-22", "2021-03-11", "2022-02-28", "2023-02-18", "2024-02-08", "2025-01-27", ] ) birth_of_prophet_muhammad = pd.to_datetime( [ # Birth of the Prophet Muhammad. # Includes common leave. "2003-05-15", "2004-05-03", "2005-04-22", "2006-04-10", "2008-03-20", "2009-03-09", "2010-02-26", "2011-02-15", "2013-01-24", "2014-01-14", "2015-12-24", "2016-12-12", "2017-12-01", "2018-11-20", "2020-10-28", "2020-10-29", "2020-10-30", "2021-10-20", "2022-10-08", "2023-09-28", "2024-09-16", "2025-09-05", ] ) vesak_day = pd.to_datetime( [ # Vesak Day (Buddha's Birthday). # Sometimes called "Hari Raya Waisak" in Indonesia. # Includes common leave. "2003-05-16", "2004-06-03", "2005-05-24", "2007-06-01", "2008-05-20", "2010-05-28", "2011-05-17", "2014-05-15", "2015-06-02", "2017-05-11", "2018-05-29", "2020-05-07", "2021-05-26", "2022-05-16", "2023-06-02", "2024-05-23", "2024-05-24", "2025-05-12", "2025-05-13", ] ) hindu_saka_new_year = pd.to_datetime( [ # Hindu Saka New Year (also called Nyepi, or Balinese Day of Silence). # Includes common leave. "2003-04-02", "2004-03-22", "2005-03-11", "2006-03-30", "2006-03-31", "2007-03-19", "2008-03-07", "2009-03-26", "2010-03-16", "2012-03-23", "2013-03-12", "2014-03-31", "2016-03-09", "2017-03-28", "2019-03-07", "2020-03-25", "2021-03-14", "2022-03-03", "2023-03-22", "2023-03-23", "2024-03-11", "2024-03-12", "2025-03-28", ] ) spontaneous_closures = pd.to_datetime( [ # Trading suspension due to global financial crisis. "2008-10-09", "2008-10-10", ] ) election_holidays = pd.to_datetime( [ # Local and gubernatorial election holidays. "2004-04-05", "2004-07-05", "2004-09-20", "2009-04-09", "2009-07-08", "2014-04-09", "2014-07-09", "2015-12-09", "2017-02-15", "2017-04-19", "2019-04-17", "2020-12-09", "2024-02-14", "2024-11-27", ] ) @property def adhoc_holidays(self): return list( chain( self.chinese_new_year, self.common_leave, self.islamic_new_year, self.eid_al_fitr, self.eid_al_adha, self.isra_mikraj, self.birth_of_prophet_muhammad, self.vesak_day, self.hindu_saka_new_year, self.spontaneous_closures, self.election_holidays, ) )