0

For example, let say my end goal is to have US business dates of every 3 months within the next 10 years. So if I do DateOffset:

import pandas as pd
start_dt = pd.to_datetime('today').normalize()
end_dt = start_dt + pd.tseries.offsets.DateOffset(years=10)
sched = pd.date_range(start=start_dt, end=end_dt, freq=pd.tseries.offsets.DateOffset(months=3))

sched is now in regular 3 months intervals. However, some of the dates in this schedule falls on US holiday, and in this case, I want to roll them forward to a business day.

DatetimeIndex(['2020-08-10', '2020-11-10', '2021-02-10', '2021-05-10',
               '2021-08-10', '2021-11-10', '2022-02-10', '2022-05-10',
               '2022-08-10', '2022-11-10', '2023-02-10', '2023-05-10',
               '2023-08-10', '2023-11-10', '2024-02-10', '2024-05-10',
               '2024-08-10', '2024-11-10', '2025-02-10', '2025-05-10',
               '2025-08-10', '2025-11-10', '2026-02-10', '2026-05-10',
               '2026-08-10', '2026-11-10', '2027-02-10', '2027-05-10',
               '2027-08-10', '2027-11-10', '2028-02-10', '2028-05-10',
               '2028-08-10', '2028-11-10', '2029-02-10', '2029-05-10',
               '2029-08-10', '2029-11-10', '2030-02-10', '2030-05-10',
               '2030-08-10'],
              dtype='datetime64[ns]', freq='<DateOffset: months=3>')

I am aware of this solution Pandas: Date range creation but feel a bit hacky to me. I want to have a proper OO solution where a class does offsetting (3M offset in this example) and also rolling date (in case of bad day/non-business day). I read through the docs about DateOffset (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.tseries.offsets.DateOffset.html) and CustomBusinessDay (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.tseries.offsets.CustomBusinessDay.html). Since the doc says CustomBusinessDay is a subclass of DateOffset, I thought I could do

pandas.tseries.offsets.CustomBusinessDay(calendar=MyOwnUSCalendar, months=3)

However, CustomBusinessDay doesn't take months argument, which tells me the kwds described in DateOffset doc is not accessible in CustomBusinessDay.

TypeError                                 Traceback (most recent call last)
<ipython-input-65-0eba5c035e33> in <module>
----> 1 quarterly = pd.tseries.offsets.CustomBusinessDay(months=3)

TypeError: __init__() got an unexpected keyword argument 'months'

Can someone please suggest a good elegant OO solution? I am thinking I can subclass the CustomBusinessDay or even DateOffset to customise the behaviour and then I can just pass it into the freq parameter of date_range. Because the documents of these classes are very sketchy, I don't understand what I should do to customise the behaviour in the way I want.

Gary
  • 1,828
  • 1
  • 20
  • 27
  • 1
    The frequency you want doesn't exist; there's no such thing as a Custom Business Month. Your best bet is doing a 3M frequency, then rolling up to the next business day with a business day offset (`sched + pd.tseries.offsets.BusinessDay(n = 0)`) – ALollz Aug 07 '20 at 16:47
  • here is an [answer](https://stackoverflow.com/a/49482921/6692898) doing what ALollz suggested, it only looks for weekends... for holidays it is more complicated, you need to combine it with something like [this question](https://stackoverflow.com/q/9187215/6692898) – RichieV Aug 07 '20 at 16:52
  • Holidays aren't too difficult. You can just use a CustomBusinessDay offset with a calendar: https://stackoverflow.com/questions/60117208/previous-business-dates-pandas/60117463#60117463. That answer subtracts, but just add with `n=0` to roll forward. – ALollz Aug 07 '20 at 16:53

0 Answers0