From bcbd5d3e0b9cbe1840bfbfb6fa277d142ba317fb Mon Sep 17 00:00:00 2001 From: Marcus Read Date: Tue, 29 Jun 2021 13:36:23 +0100 Subject: [PATCH] Fix conflict between holidays and special dates Fixes #33 --- exchange_calendars/exchange_calendar.py | 11 ++++++++++- exchange_calendars/exchange_calendar_xist.py | 16 +--------------- exchange_calendars/exchange_calendar_xkls.py | 17 +---------------- 3 files changed, 12 insertions(+), 32 deletions(-) diff --git a/exchange_calendars/exchange_calendar.py b/exchange_calendars/exchange_calendar.py index 9d516c6a..3dd97b99 100644 --- a/exchange_calendars/exchange_calendar.py +++ b/exchange_calendars/exchange_calendar.py @@ -1233,7 +1233,16 @@ def _special_dates(self, calendars, ad_hoc_dates, start_date, end_date): return pd.Series([], dtype="datetime64[ns, UTC]") result = pd.concat(merged).sort_index() - return result.loc[(result >= start_date) & (result <= end_date)] + result = result.loc[(result >= start_date) & (result <= end_date)] + # exclude any special date that conincides with a holiday + adhoc_holidays = pd.DatetimeIndex(self.adhoc_holidays, tz="UTC") + result = result[~result.index.isin(adhoc_holidays)] + reg_holidays = self.regular_holidays.holidays( + start_date.tz_convert(None), end_date.tz_convert(None) + ) + if not reg_holidays.empty: + result = result[~result.index.isin(reg_holidays.tz_localize("UTC"))] + return result def _calculate_special_opens(self, start, end): return self._special_dates( diff --git a/exchange_calendars/exchange_calendar_xist.py b/exchange_calendars/exchange_calendar_xist.py index b1d2261b..cdac7d2c 100644 --- a/exchange_calendars/exchange_calendar_xist.py +++ b/exchange_calendars/exchange_calendar_xist.py @@ -177,19 +177,5 @@ def special_closes(self): @property def special_closes_adhoc(self): - # Some early close days fall on holidays, so we must filter those out - # of the early close list - collisions = [ - # CAYS Day on May 19 - pd.Timestamp("1994-05-19"), - # Day before Eid al Fitr observed as holiday in 2003 - pd.Timestamp("2003-11-24"), - ] - early_close_days = EidAlFitrHalfDay + EidAlAdhaHalfDay - - early_close_days = [day for day in early_close_days if day not in collisions] - - return [ - (self.regular_early_close, early_close_days), - ] + return [(self.regular_early_close, early_close_days)] diff --git a/exchange_calendars/exchange_calendar_xkls.py b/exchange_calendars/exchange_calendar_xkls.py index 5602b43c..dd0a4e4a 100644 --- a/exchange_calendars/exchange_calendar_xkls.py +++ b/exchange_calendars/exchange_calendar_xkls.py @@ -16,7 +16,6 @@ from datetime import time from itertools import chain -import pandas as pd from pytz import timezone from .exchange_calendar import HolidayCalendar, ExchangeCalendar @@ -122,19 +121,5 @@ def adhoc_holidays(self): @property def special_closes_adhoc(self): # Regular early closes on Chinese New Years Eve, Eid al-Fitr Eve - early_close_days = ChineseNewYearsHalfDay + EidAlFitrHalfDay - - collisions = [ - # Chinese New Year's Eve was a holiday until 2005 - pd.Timestamp("1997-02-07"), - pd.Timestamp("1998-01-28"), - pd.Timestamp("2002-02-11"), - pd.Timestamp("2003-01-31"), - pd.Timestamp("2004-01-21"), - # Eid al-Fitr Eve was a holiday in 2003 - pd.Timestamp("2003-11-24"), - ] - - early_close_days = list(set(early_close_days) - set(collisions)) - + early_close_days = list(set(ChineseNewYearsHalfDay + EidAlFitrHalfDay)) return [(self.regular_early_close, early_close_days)]