rsheftel/pandas_market_calendars

BUG xtae calendar is broken

wabscale opened this issue · 1 comments

Bug

There is an issue with the way the XTAE exchange calendar is structured where pandas_market_calendars does not handle it correctly. It is not possible to produce schedules from it.

Reproducable Example

import pandas as pd
import pandas_market_calendars as mcal

xtae = mcal.get_calendar('XTAE')
xtae.schedule(pd.Timestamp('2023-01-01'), pd.Timestamp('2023-12-31'))
In [1]: import pandas as pd
   ...: import pandas_market_calendars as mcal
   ...:
   ...: xtae = mcal.get_calendar('XTAE')
   ...: xtae.schedule(pd.Timestamp('2023-01-01'), pd.Timestamp('2023-12-31'))
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[1], line 5
      2 import pandas_market_calendars as mcal
      4 xtae = mcal.get_calendar('XTAE')
----> 5 xtae.schedule(pd.Timestamp('2023-01-01'), pd.Timestamp('2023-12-31'))

File /opt/conda/envs/py310_64/lib/python3.10/site-packages/pandas_market_calendars/market_calendar.py:616, in MarketCalendar.schedule(self, start_date, end_date, tz, start, end, force_special_times, market_times, interruptions)
    613 temp = self.days_at_time(_all_days, market_time).copy() # standard times
    614 if _adj_col:
    615     # create an array of special times
--> 616     special = self.special_dates(market_time, start_date, end_date, filter_holidays= False)
    617     # overwrite standard times
    618     specialix = special.index[special.index.isin(temp.index)] # some sources of special times don't exclude holidays

File /opt/conda/envs/py310_64/lib/python3.10/site-packages/pandas_market_calendars/market_calendar.py:557, in MarketCalendar.special_dates(self, market_time, start_date, end_date, filter_holidays)
    555 calendars = self.get_special_times(market_time)
    556 ad_hoc = self.get_special_times_adhoc(market_time)
--> 557 special = self._special_dates(calendars, ad_hoc, start_date, end_date)
    559 if filter_holidays:
    560     valid = self.valid_days(start_date, end_date, tz= None)

File /opt/conda/envs/py310_64/lib/python3.10/site-packages/pandas_market_calendars/market_calendar.py:531, in MarketCalendar._special_dates(self, calendars, ad_hoc_dates, start, end)
    524 def _special_dates(self, calendars, ad_hoc_dates, start, end):
    525     """
    526     Union an iterable of pairs of the form (time, calendar)
    527     and an iterable of pairs of the form (time, [dates])
    528
    529     (This is shared logic for computing special opens and special closes.)
    530     """
--> 531     indexes = [
    532             self.days_at_time(self._tryholidays(calendar, start, end), time_)
    533                   for time_, calendar in calendars
    534          ] + [
    535             self.days_at_time(dates, time_) for time_, dates in ad_hoc_dates
    536         ]
    537     if indexes:
    538         dates = pd.concat(indexes).sort_index().drop_duplicates()

File /opt/conda/envs/py310_64/lib/python3.10/site-packages/pandas_market_calendars/market_calendar.py:532, in <listcomp>(.0)
    524 def _special_dates(self, calendars, ad_hoc_dates, start, end):
    525     """
    526     Union an iterable of pairs of the form (time, calendar)
    527     and an iterable of pairs of the form (time, [dates])
    528
    529     (This is shared logic for computing special opens and special closes.)
    530     """
    531     indexes = [
--> 532             self.days_at_time(self._tryholidays(calendar, start, end), time_)
    533                   for time_, calendar in calendars
    534          ] + [
    535             self.days_at_time(dates, time_) for time_, dates in ad_hoc_dates
    536         ]
    537     if indexes:
    538         dates = pd.concat(indexes).sort_index().drop_duplicates()

File /opt/conda/envs/py310_64/lib/python3.10/site-packages/pandas_market_calendars/market_calendar.py:521, in MarketCalendar._tryholidays(self, cal, s, e)
    520 def _tryholidays(self, cal, s, e):
--> 521     try: return cal.holidays(s, e)
    522     except ValueError: return pd.DatetimeIndex([])

AttributeError: 'int' object has no attribute 'holidays'

Source of problem

I have determined that the problem is from here: https://github.com/gerrymanoim/exchange_calendars/blob/02054044440583be70017efa5fe7951b419c27fb/exchange_calendars/exchange_calendar_xtae.py#L170

It has a special closed definied for sunday where the SUNDAY on this line is the integer 6, not a HolidayCalendar.

I believe that altering the MarketData._tryholidays method to assume integers are week days will fix the problem.

Platform

python -c "import pandas_market_calendars; print(pandas_market_calendars.__version__)"
4.2.1
python --version
Python 3.10.12

Fixed with v4.4.1

Thank you for the PR