Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix conflict between holidays and special dates #39

Merged
merged 3 commits into from
Jul 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions exchange_calendars/exchange_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ def adhoc_holidays(self):
"""
Returns
-------
list: A list of timestamps representing unplanned closes.
list: A list of tz-naive timestamps representing unplanned closes.
"""
return []

Expand Down Expand Up @@ -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(
Expand Down
20 changes: 10 additions & 10 deletions exchange_calendars/exchange_calendar_asex.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import pandas as pd
from dateutil.easter import EASTER_ORTHODOX, easter
from pandas.tseries.holiday import EasterMonday, GoodFriday, Holiday
from pytz import UTC, timezone
from pytz import timezone

from .common_holidays import (
assumption_day,
Expand All @@ -43,7 +43,7 @@ def orthodox_easter(start_date="1980", end_date="2021"):
easter(year, method=EASTER_ORTHODOX)
for year in range(int(start_date), int(end_date))
]
).tz_localize(UTC)
)


NewYearsDay = new_years_day()
Expand Down Expand Up @@ -144,22 +144,22 @@ def regular_holidays(self):
def adhoc_holidays(self):
debt_crisis = pd.date_range("2015-06-29", "2015-07-31", freq="B")

debt_crisis_holidays = [pd.Timestamp(str(date), tz=UTC) for date in debt_crisis]
debt_crisis_holidays = [pd.Timestamp(str(date)) for date in debt_crisis]

misc_adhoc_holidays = [
# In 2002, market closed for unknown reason
pd.Timestamp("2002-05-07", tz=UTC),
pd.Timestamp("2002-05-07"),
# In 2004, Assumption Day fell on a sunday, observed on a Friday
pd.Timestamp("2004-08-13", tz=UTC),
pd.Timestamp("2004-08-13"),
# In 2008, worker strikes closed the market for 2 days in March
pd.Timestamp("2008-03-04", tz=UTC),
pd.Timestamp("2008-03-05", tz=UTC),
pd.Timestamp("2008-03-04"),
pd.Timestamp("2008-03-05"),
# In 2013, May Day strikes closed the market
pd.Timestamp("2013-05-07", tz=UTC),
pd.Timestamp("2013-05-07"),
# In 2014, New Year's Eve was observed as a holiday
pd.Timestamp("2014-12-31", tz=UTC),
pd.Timestamp("2014-12-31"),
# In 2016, Labour Day fell on a Sunday, observed on Tuesday
pd.Timestamp("2016-05-03", tz=UTC),
pd.Timestamp("2016-05-03"),
]

return list(
Expand Down
5 changes: 2 additions & 3 deletions exchange_calendars/exchange_calendar_bvmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@
day=31,
observance=previous_friday,
)
# Brazil hosted World Cup and played Croatia (and won 3-1!)
CopaDoMundo2014 = Holiday("Copa Do Mundo 2014", month=6, day=12, year=2014)


class BVMFExchangeCalendar(ExchangeCalendar):
Expand Down Expand Up @@ -170,7 +168,8 @@ class BVMFExchangeCalendar(ExchangeCalendar):

@property
def adhoc_holidays(self):
return [CopaDoMundo2014]
# CopaDoMundo2014 Brazil hosted World Cup and played Croatia (and won 3-1!)
return [pd.Timestamp("2014-06-12")]

@property
def regular_holidays(self):
Expand Down
4 changes: 2 additions & 2 deletions exchange_calendars/exchange_calendar_iepa.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
USPresidentsDay,
USThanksgivingDay,
)
from pytz import UTC, timezone
from pytz import timezone

from .exchange_calendar import ExchangeCalendar
from exchange_calendars.exchange_calendar import HolidayCalendar
Expand Down Expand Up @@ -69,7 +69,7 @@ def adhoc_holidays(self):
USNationalDaysofMourning,
# ICE was only closed on the first day of the Hurricane Sandy
# closings (was not closed on 2012-10-30)
[Timestamp("2012-10-29", tz=UTC)],
[Timestamp("2012-10-29")],
)
)

Expand Down
12 changes: 6 additions & 6 deletions exchange_calendars/exchange_calendar_xasx.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
sunday_to_monday,
weekend_to_monday,
)
from pytz import UTC, timezone
from pytz import timezone

from .common_holidays import (
anzac_day,
Expand Down Expand Up @@ -94,7 +94,7 @@
# also observed as a public holiday. Note that this isn't defined as a
# rule, because it will happen next in 2095 (and then in 2163), and
# there isn't a great way to tell how this will be handled at that point.
EasterTuesday2011AdHoc = Timestamp("2011-04-26", tz=UTC)
EasterTuesday2011AdHoc = Timestamp("2011-04-26")

QueensBirthday = Holiday(
"Queen's Birthday",
Expand Down Expand Up @@ -124,10 +124,10 @@
)

# additional ad-hoc holidays
NYEMonday1984AdHoc = Timestamp("1984-12-31", tz=UTC)
NYEMonday1990AdHoc = Timestamp("1990-12-31", tz=UTC)
Bicentennial1988 = Timestamp("1988-01-25", tz=UTC)
Y2KTesting = Timestamp("1999-12-31", tz=UTC)
NYEMonday1984AdHoc = Timestamp("1984-12-31")
NYEMonday1990AdHoc = Timestamp("1990-12-31")
Bicentennial1988 = Timestamp("1988-01-25")
Y2KTesting = Timestamp("1999-12-31")


class XASXExchangeCalendar(ExchangeCalendar):
Expand Down
3 changes: 2 additions & 1 deletion exchange_calendars/exchange_calendar_xdub.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@

# Ad hoc closes.
March1BadWeather = Timestamp("2018-03-01", tz=UTC)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this one also need UTC removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting another review in.

I left March1BadWeather as UTC because it feeds through to special_closes_adhoc, not adhoc_holidays. I've added a comment to 'XDUB' to note the difference.

A side note: the suggested fix creates a DatetimeIndex of adhoc_holidays, thereby requiring them to be defined consistently in terms of either UTC or tz-naive (at least within any specific calendar). At the risk of returning to the #42 UTC / tz-naive discussion 😀, I went with tz-naive in light of what they represent. Having worked through the implementation I was happy they could be defined in tz-naive terms (which was pretty clear anyway from the fact that some already were). Also, it didn't seem much point asking someone defining adhoc_holidays to set the timezone to UTC when that extra context isn't used (infact, as in some calendars, they could all just be defined as strings, e.g. "2021-07-09").

I didn't need to work through the workings of special_closes_adhoc and didn't want to risk introducing a bug by changing something for the sake of changing it - allowing special_closes_adhoc to be defined as tz-aware seemed reasonable in any case.

March2BadWeather = Timestamp("2018-03-02", tz=UTC)
# Ad hoc holidays.
March2BadWeather = Timestamp("2018-03-02")


class XDUBExchangeCalendar(ExchangeCalendar):
Expand Down
6 changes: 3 additions & 3 deletions exchange_calendars/exchange_calendar_xetr.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from pandas import Timestamp
from pandas.tseries.holiday import EasterMonday, GoodFriday, Holiday, previous_workday
from pytz import UTC, timezone
from pytz import timezone

from .common_holidays import (
boxing_day,
Expand All @@ -38,7 +38,7 @@

# Whit Monday observed in 2007, before it became regularly observed
# starting in 2015.
WhitMonday2007AdHoc = Timestamp("2007-05-28", tz=UTC)
WhitMonday2007AdHoc = Timestamp("2007-05-28")

WhitMonday = whit_monday(start_date="2015-01-01")

Expand All @@ -47,7 +47,7 @@
)

# Reformation Day was a German national holiday in 2017.
ReformationDay500thAnniversaryAdHoc = Timestamp("2017-10-31", tz=UTC)
ReformationDay500thAnniversaryAdHoc = Timestamp("2017-10-31")

ChristmasEve = christmas_eve()

Expand Down
6 changes: 3 additions & 3 deletions exchange_calendars/exchange_calendar_xfra.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from pandas import Timestamp
from pandas.tseries.holiday import EasterMonday, GoodFriday, Holiday, previous_workday
from pytz import UTC, timezone
from pytz import timezone

from .common_holidays import (
boxing_day,
Expand All @@ -38,7 +38,7 @@

# Whit Monday observed in 2007, before it became regularly observed
# starting in 2015.
WhitMonday2007AdHoc = Timestamp("2007-05-28", tz=UTC)
WhitMonday2007AdHoc = Timestamp("2007-05-28")

WhitMonday = whit_monday(start_date="2015-01-01")

Expand All @@ -47,7 +47,7 @@
)

# Reformation Day was a German national holiday in 2017.
ReformationDay500thAnniversaryAdHoc = Timestamp("2017-10-31", tz=UTC)
ReformationDay500thAnniversaryAdHoc = Timestamp("2017-10-31")

ChristmasEve = christmas_eve()

Expand Down
160 changes: 80 additions & 80 deletions exchange_calendars/exchange_calendar_xhkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,87 +142,87 @@ def process_queen_birthday(dt):

HKAdhocClosures = [
# I dont know these days
pd.Timestamp("1970-07-01", tz="UTC"),
pd.Timestamp("1971-07-01", tz="UTC"),
pd.Timestamp("1973-07-02", tz="UTC"),
pd.Timestamp("1974-07-01", tz="UTC"),
pd.Timestamp("1975-07-01", tz="UTC"),
pd.Timestamp("1976-07-01", tz="UTC"),
pd.Timestamp("1977-07-01", tz="UTC"),
pd.Timestamp("1979-07-02", tz="UTC"),
pd.Timestamp("1980-07-01", tz="UTC"),
pd.Timestamp("1981-07-01", tz="UTC"),
pd.Timestamp("1982-07-01", tz="UTC"),
pd.Timestamp("1971-03-22", tz="UTC"),
pd.Timestamp("1971-12-06", tz="UTC"),
pd.Timestamp("1971-12-20", tz="UTC"),
pd.Timestamp("1975-07-28", tz="UTC"),
pd.Timestamp("1985-07-29", tz="UTC"),
pd.Timestamp("1970-07-01"),
pd.Timestamp("1971-07-01"),
pd.Timestamp("1973-07-02"),
pd.Timestamp("1974-07-01"),
pd.Timestamp("1975-07-01"),
pd.Timestamp("1976-07-01"),
pd.Timestamp("1977-07-01"),
pd.Timestamp("1979-07-02"),
pd.Timestamp("1980-07-01"),
pd.Timestamp("1981-07-01"),
pd.Timestamp("1982-07-01"),
pd.Timestamp("1971-03-22"),
pd.Timestamp("1971-12-06"),
pd.Timestamp("1971-12-20"),
pd.Timestamp("1975-07-28"),
pd.Timestamp("1985-07-29"),
# Weather related closures
pd.Timestamp("1970-07-16", tz="UTC"), # 台风Ruby7003
pd.Timestamp("1970-09-14", tz="UTC"), # 台风Georgia7011
pd.Timestamp("1971-07-22", tz="UTC"), # 台风Lucy7114
pd.Timestamp("1971-08-31", tz="UTC"), # 重光纪念日?
pd.Timestamp("1973-04-16", tz="UTC"), # 股灾休市?
pd.Timestamp("1973-07-17", tz="UTC"), # 台风Dot7304
pd.Timestamp("1974-04-25", tz="UTC"), # 英国女王生日
pd.Timestamp("1975-10-14", tz="UTC"), # 台风Elsie7514
pd.Timestamp("1978-07-26", tz="UTC"), # 台风Agnes7807
pd.Timestamp("1978-07-27", tz="UTC"),
pd.Timestamp("1979-01-26", tz="UTC"), # 春节补假
pd.Timestamp("1979-08-02", tz="UTC"), # 台风Hope7908
pd.Timestamp("1980-05-21", tz="UTC"), # 台风Georgia8004
pd.Timestamp("1980-07-22", tz="UTC"), # 台风Joy8007
pd.Timestamp("1981-04-27", tz="UTC"), # 英国女王生日
pd.Timestamp("1981-07-06", tz="UTC"), # 台风Lynn8106
pd.Timestamp("1981-07-07", tz="UTC"),
pd.Timestamp("1981-07-29", tz="UTC"), # 查理斯王子与戴安娜婚礼
pd.Timestamp("1983-09-09", tz="UTC"), # 台风Ellen8309
pd.Timestamp("1985-06-24", tz="UTC"), # 台风Hal8504
pd.Timestamp("1986-04-01", tz="UTC"), # 复活节星期一翌日
pd.Timestamp("1986-10-22", tz="UTC"), # 英女王伊丽莎白二世访港
pd.Timestamp("1987-10-20", tz="UTC"), # 黑色星期一后,休市4天
pd.Timestamp("1987-10-21", tz="UTC"),
pd.Timestamp("1987-10-22", tz="UTC"),
pd.Timestamp("1987-10-23", tz="UTC"),
pd.Timestamp("1988-04-05", tz="UTC"), # 清明节翌日
# Timestamp('1988-06-13', tz='UTC'), # 英国女王生日
pd.Timestamp("1991-06-18", tz="UTC"), # 英国女王生日翌日
pd.Timestamp("1992-07-22", tz="UTC"), # 台风Cary9207
# pd.Timestamp('1993-06-14', tz='UTC'), # 英国女王生日
pd.Timestamp("1993-09-17", tz="UTC"), # 台风Becky9316
pd.Timestamp("1994-06-14", tz="UTC"), # 英国女王生日翌日,端午节翌日
pd.Timestamp("1997-06-30", tz="UTC"), # 英国女王生日
pd.Timestamp("1997-07-02", tz="UTC"), # 香港回归纪念日翌日
pd.Timestamp("1997-08-18", tz="UTC"), # 抗战胜利纪念日
pd.Timestamp("1997-10-02", tz="UTC"), # 国庆节翌日
pd.Timestamp("1998-08-17", tz="UTC"), # 抗战胜利纪念日
pd.Timestamp("1998-10-02", tz="UTC"), # 国庆节翌日
pd.Timestamp("1999-04-06", tz="UTC"), # 清明节翌日
pd.Timestamp("1999-09-16", tz="UTC"), # 台风约克
pd.Timestamp("1999-12-31", tz="UTC"), # 千年虫
pd.Timestamp("2001-07-06", tz="UTC"), # 台风尤特0104
pd.Timestamp("2001-07-25", tz="UTC"), # 台风玉兔0107
# pd.Timestamp(2008-06-25', tz='UTC'), # 台风风神0806,上午休市
pd.Timestamp("2008-08-06", tz="UTC"), # 台风北冕0809
pd.Timestamp("2008-08-22", tz="UTC"), # 台风鹦鹉0810
# pd.Timestamp(2009-09-15', tz='UTC'), # 台风巨爵0915,上午休市
pd.Timestamp("2010-04-06", tz="UTC"), # 清明节翌日
pd.Timestamp("2011-09-29", tz="UTC"), # 台风纳沙1117
# pd.Timestamp(2012-07-24', tz='UTC'), # 台风韦森特1208,上午休市
pd.Timestamp("2012-10-02", tz="UTC"), # 中秋节补假
# pd.Timestamp(2013-05-22', tz='UTC'), # 暴雨,上午休市
pd.Timestamp("2013-08-14", tz="UTC"), # 台风尤特1311
# pd.Timestamp(2013-09-23', tz='UTC'), # 台风天兔1319,上午休市
# pd.Timestamp(2014-09-16', tz='UTC'), # 台风海鸥1415,上午休市
pd.Timestamp("2015-04-07", tz="UTC"), # 复活节+清明节补假
# pd.Timestamp(2015-07-09', tz='UTC'), # 台风莲花1520,期货夜盘休市
pd.Timestamp("2015-09-03", tz="UTC"), # 抗战70周年纪念
# pd.Timestamp(2016-08-01', tz='UTC'), # 台风妮妲1604,期货夜盘20:55收市
pd.Timestamp("2016-08-02", tz="UTC"), # 台风妮妲1604
pd.Timestamp("2016-10-21", tz="UTC"), # 台风海马1622
# pd.Timestamp(2017-06-12', tz='UTC'), # 台风苗柏1702,期货夜盘17:35休市
pd.Timestamp("2017-08-23", tz="UTC"), # 台风天鸽1713
pd.Timestamp("1970-07-16"), # 台风Ruby7003
pd.Timestamp("1970-09-14"), # 台风Georgia7011
pd.Timestamp("1971-07-22"), # 台风Lucy7114
pd.Timestamp("1971-08-31"), # 重光纪念日?
pd.Timestamp("1973-04-16"), # 股灾休市?
pd.Timestamp("1973-07-17"), # 台风Dot7304
pd.Timestamp("1974-04-25"), # 英国女王生日
pd.Timestamp("1975-10-14"), # 台风Elsie7514
pd.Timestamp("1978-07-26"), # 台风Agnes7807
pd.Timestamp("1978-07-27"),
pd.Timestamp("1979-01-26"), # 春节补假
pd.Timestamp("1979-08-02"), # 台风Hope7908
pd.Timestamp("1980-05-21"), # 台风Georgia8004
pd.Timestamp("1980-07-22"), # 台风Joy8007
pd.Timestamp("1981-04-27"), # 英国女王生日
pd.Timestamp("1981-07-06"), # 台风Lynn8106
pd.Timestamp("1981-07-07"),
pd.Timestamp("1981-07-29"), # 查理斯王子与戴安娜婚礼
pd.Timestamp("1983-09-09"), # 台风Ellen8309
pd.Timestamp("1985-06-24"), # 台风Hal8504
pd.Timestamp("1986-04-01"), # 复活节星期一翌日
pd.Timestamp("1986-10-22"), # 英女王伊丽莎白二世访港
pd.Timestamp("1987-10-20"), # 黑色星期一后,休市4天
pd.Timestamp("1987-10-21"),
pd.Timestamp("1987-10-22"),
pd.Timestamp("1987-10-23"),
pd.Timestamp("1988-04-05"), # 清明节翌日
# Timestamp('1988-06-13'), # 英国女王生日
pd.Timestamp("1991-06-18"), # 英国女王生日翌日
pd.Timestamp("1992-07-22"), # 台风Cary9207
# pd.Timestamp('1993-06-14'), # 英国女王生日
pd.Timestamp("1993-09-17"), # 台风Becky9316
pd.Timestamp("1994-06-14"), # 英国女王生日翌日,端午节翌日
pd.Timestamp("1997-06-30"), # 英国女王生日
pd.Timestamp("1997-07-02"), # 香港回归纪念日翌日
pd.Timestamp("1997-08-18"), # 抗战胜利纪念日
pd.Timestamp("1997-10-02"), # 国庆节翌日
pd.Timestamp("1998-08-17"), # 抗战胜利纪念日
pd.Timestamp("1998-10-02"), # 国庆节翌日
pd.Timestamp("1999-04-06"), # 清明节翌日
pd.Timestamp("1999-09-16"), # 台风约克
pd.Timestamp("1999-12-31"), # 千年虫
pd.Timestamp("2001-07-06"), # 台风尤特0104
pd.Timestamp("2001-07-25"), # 台风玉兔0107
# pd.Timestamp(2008-06-25'), # 台风风神0806,上午休市
pd.Timestamp("2008-08-06"), # 台风北冕0809
pd.Timestamp("2008-08-22"), # 台风鹦鹉0810
# pd.Timestamp(2009-09-15'), # 台风巨爵0915,上午休市
pd.Timestamp("2010-04-06"), # 清明节翌日
pd.Timestamp("2011-09-29"), # 台风纳沙1117
# pd.Timestamp(2012-07-24'), # 台风韦森特1208,上午休市
pd.Timestamp("2012-10-02"), # 中秋节补假
# pd.Timestamp(2013-05-22'), # 暴雨,上午休市
pd.Timestamp("2013-08-14"), # 台风尤特1311
# pd.Timestamp(2013-09-23'), # 台风天兔1319,上午休市
# pd.Timestamp(2014-09-16'), # 台风海鸥1415,上午休市
pd.Timestamp("2015-04-07"), # 复活节+清明节补假
# pd.Timestamp(2015-07-09'), # 台风莲花1520,期货夜盘休市
pd.Timestamp("2015-09-03"), # 抗战70周年纪念
# pd.Timestamp(2016-08-01'), # 台风妮妲1604,期货夜盘20:55收市
pd.Timestamp("2016-08-02"), # 台风妮妲1604
pd.Timestamp("2016-10-21"), # 台风海马1622
# pd.Timestamp(2017-06-12'), # 台风苗柏1702,期货夜盘17:35休市
pd.Timestamp("2017-08-23"), # 台风天鸽1713
]


Expand Down
Loading