Custom calendar in Pandas make iterable

Question:

trying to make the class iterable for the below NYSE custom calendar using pandas, say to run this check:

nyse_cal = NYSECalendar()
for date in nyse_cal:
    print(date)

but the statement last_holiday = self.rules[-1] produces TypeError: 'method' is not subscriptable for the ‘Holiday’ instance because of indexing [-1]. Is there a workaround?

from pandas.tseries.offsets import CustomBusinessDay, MonthEnd
from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, 
    USMemorialDay,  USMartinLutherKingJr, USPresidentsDay, GoodFriday, 
    USLaborDay, USThanksgivingDay, nearest_workday, next_monday

class NYSECalendar(AbstractHolidayCalendar):
    ''' NYSE holiday calendar via pandas '''
    rules = [
        Holiday('New Years Day', month=1, day=1, observance=nearest_workday),
        USMartinLutherKingJr,
        USPresidentsDay,
        GoodFriday,
        USMemorialDay,
        Holiday('Juneteenth', month=6, day=19, observance=nearest_workday),
        Holiday('USIndependenceDay', month=7, day=4, observance=nearest_workday),
        USLaborDay,
        USThanksgivingDay,
        Holiday('Christmas', month=12, day=25, observance=nearest_workday),
        ]
    def __iter__(self):
        last_holiday = self.rules[-1]
        last_holiday_date = last_holiday.dates[-1]
        start_date = last_holiday_date + MonthEnd(12) + CustomBusinessDay(calendar=self)
        end_date = start_date + MonthEnd(1) - CustomBusinessDay(calendar=self)
        curr_date = start_date
        while curr_date <= end_date:
            yield curr_date
            curr_date += CustomBusinessDay(calendar=self)
Asked By: gregV

||

Answers:

You cn do this:

from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, nearest_workday,USMartinLutherKingJr, USPresidentsDay, GoodFriday, USMemorialDay, USLaborDay,USThanksgivingDay
from pandas.tseries.offsets import MonthEnd, CustomBusinessDay
import pandas as pd


class NYSECalendar(AbstractHolidayCalendar):
    rules = [
        Holiday('New Years Day', month=1, day=1, observance=nearest_workday),
        USMartinLutherKingJr,
        USPresidentsDay,
        GoodFriday,
        USMemorialDay,
        Holiday('Juneteenth', month=6, day=19, observance=nearest_workday),
        Holiday('USIndependenceDay', month=7, day=4, observance=nearest_workday),
        USLaborDay,
        USThanksgivingDay,
        Holiday('Christmas', month=12, day=25, observance=nearest_workday),
    ]
    
    def get_rules(self):
        return self.rules

    def __iter__(self):
        last_holiday = self.get_rules()[-1]
        last_holiday_date = last_holiday.dates[-1]
        start_date = last_holiday_date + MonthEnd(12) + CustomBusinessDay(calendar=self)
        end_date = start_date + MonthEnd(1) - CustomBusinessDay(calendar=self)
        curr_date = start_date
        while curr_date <= end_date:
            yield curr_date
            curr_date += CustomBusinessDay(calendar=self)


and test it it this sample dataframe, this way:

import pandas as pd

nyse_cal = NYSECalendar()

start_date = '2022-01-01'
end_date = '2022-01-31'

df = pd.DataFrame({
    'business_day': pd.date_range(start=start_date, end=end_date, freq=CustomBusinessDay(calendar=nyse_cal))
})

print(df)

return th business days:

  business_day
0    2022-01-03
1    2022-01-04
2    2022-01-05
3    2022-01-06
4    2022-01-07
5    2022-01-10
6    2022-01-11
7    2022-01-12
8    2022-01-13
9    2022-01-14
10   2022-01-18
11   2022-01-19
12   2022-01-20
13   2022-01-21
14   2022-01-24
15   2022-01-25
16   2022-01-26
17   2022-01-27
18   2022-01-28
19   2022-01-31

Basically, you need to get th right packages.

Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.