Pandas 每月第几周的工作日股票价格数据

5

我提出的问题与以下问题不同:

问题1:如何在Pandas中获取一个月的周数 问题2:如何获取一个月的周数

上述问题涉及假设一周七天。它试图计算有多少7天的周。我的数据由(工作日)每日价格组成,因为市场关闭了节假日,有时一周中会缺少某些天。

我的问题是如何在给定日期的情况下找到这个月的周数。请注意,我强调“给定日期”,因为这个过程每天都会处理,所以任何需要向前看到本月末的答案可能都不起作用。
我的尝试是向前看,这并不是最优解:

def is_third_friday(s):
    d = datetime.datetime.strptime(s, '%Y-%m-%d')
    return d.weekday() == 5 and 15 <= d.day <= 21

dow = deepcopy(data['Close'] * np.nan).to_frame()
dow.columns = ['OpexFriday']
dow['next_date'] = pd.Series([str(i.date() + datetime.timedelta(days=1)) for i in dow.index]).values
dow['OpexFriday'] = pd.Series([is_third_friday(str(i)) for i in dow['next_date']]).values
dow['OpexWeek'] = (dow['OpexFriday'] * 1).replace(0, np.nan).fillna(method='bfill', limit=4).replace(np.nan, 0) == True

我不知道如何提供一些样本数据,但是如果您访问“https://aroussi.com/post/python-yahoo-finance”页面并使用作者的yfinance包,您将能够获取一些价格数据进行使用。

上面的函数将找到该月的第三个星期(全部为真)。此外,还会设置该星期的星期五。

如果您对问题有任何疑问或者发现它是重复的,请告诉我。我已经搜索了一段时间来寻找解决方案。

4个回答

3

一种方法是使用 timedelta 将任何日期更改为下一个星期五,然后检查这个星期五是否在15日至21日之间。

from datetime import datetime, timedelta
def OpexWeek (s):
    d = datetime.strptime(s, '%Y-%m-%d')
    day = (d+timedelta(days=(4-d.weekday())%7)).day
    return (day>=15) & (day<=21)

那么你会得到:
#for the example the second Friday of June 2020:
OpexWeek('2020-06-12')
False

# the Monday after is True because part of the OpexWeek
OpexWeek('2020-06-15')
True

注意:需要知道的一件事情是OpexWeek之前的周六和周日是真实存在的,但由于您说您的数据是工作日,所以这应该没有关系。

用于Datetime序列的pandas版本可能是:

def OpexWeekPd (ser):
    return (ser+pd.to_timedelta((4-ser.dt.weekday)%7, unit='d')).dt.day.between(15,21)

举个小例子:

print (
    pd.DataFrame({'date':pd.bdate_range('2020-06-01', '2020-06-30').astype(str)})
      .assign(isOpexWeek=lambda x: x['date'].apply(OpexWeek), 
              isIpexWeekPd=lambda x: OpexWeekPd(pd.to_datetime(x['date'])))
    )
          date  isOpexWeek  isIpexWeekPd
0   2020-06-01       False         False
1   2020-06-02       False         False
2   2020-06-03       False         False
3   2020-06-04       False         False
4   2020-06-05       False         False
5   2020-06-08       False         False
6   2020-06-09       False         False
7   2020-06-10       False         False
8   2020-06-11       False         False
9   2020-06-12       False         False
10  2020-06-15        True          True
11  2020-06-16        True          True
12  2020-06-17        True          True
13  2020-06-18        True          True
14  2020-06-19        True          True
15  2020-06-22       False         False
16  2020-06-23       False         False
17  2020-06-24       False         False
18  2020-06-25       False         False
19  2020-06-26       False         False
20  2020-06-29       False         False
21  2020-06-30       False         False

2
我们可以轻松修改您的函数以在索引上运行:
# sample data
dow = pd.DataFrame(index=pd.date_range('2020-01-01', '2020-01-31'),
                   columns=['OpexFriday'])

isFriday = dow.index.dayofweek == 5
thirdWeek = dow.index.day.to_series().between(15,21)

# third Friday
dow['OpexFriday'] = (isFriday & thirdWeek).values

# third work week
dow['OpexWeek'] = dow['OpexFriday'].where(dow['OpexFriday']).bfill(limit=4).fillna(0)

# extract the third week:
dow[dow['OpexWeek']==1]

输出:

            OpexFriday  OpexWeek
2020-01-14       False       1.0
2020-01-15       False       1.0
2020-01-16       False       1.0
2020-01-17       False       1.0
2020-01-18        True       1.0

这种方法比我的更加简洁,但是问题在于为了知道我是否处于 OPEX 周,我需要等到周五。我需要一种方法在周一就能知道我是否处于 opex 周。 - user1234440
1
@user1234440,所以你更关心OPEXweek而不是OPEXFriday吗?你需要OPEXFriday吗? - Quang Hoang
我并不在意OpexFriday,我只需要opex week。从那里我可以得到我所需的一切。谢谢! - user1234440

0
import datetime
from math import ceil


def week_of_month(dt):
    """ Returns the week of the month for the specified date.
    """

    adjusted_dom = dt.day + dt.replace(day=1).day

    return int(ceil(adjusted_dom / 7.0))


def week_of_month_from_str(d_str):
    return week_of_month(datetime.datetime.strptime(d_str, '%Y-%m-%d'))


assert week_of_month_from_str("2020-03-02") == 1
assert week_of_month_from_str("2020-03-07") == 2
assert week_of_month_from_str("2020-03-13") == 2
assert week_of_month_from_str("2020-03-14") == 3
assert week_of_month_from_str("2020-03-20") == 3
assert week_of_month_from_str("2020-06-01") == 1
assert week_of_month_from_str("2020-06-06") == 1
assert week_of_month_from_str("2020-06-07") == 2
assert week_of_month_from_str("2020-06-08") == 2

你说得对。我已经更正了我的答案。现在应该没问题了。我附加了一些测试以确保它按预期工作。 - pakallis

0
尽管问题的标题是“Pandas月份的周数”,但根据您对其他答案的评论,似乎您主要想要识别“OpEx周”,即包含第三个星期五的交易周(即从星期一到星期五)。
如果上述假设和定义是正确的,那么这个函数将完成这项工作:
def isOpexWeek(d):
    first_week_day = datetime.date(d.year, d.month, 1).weekday()
    first_friday = 1 + ((4 - first_week_day + 7) % 7)
    third_friday = first_friday + 14
    return d.day in range(third_friday-4, third_friday+1)

dow = pd.DataFrame(index=pd.date_range('2020-01-01', '2020-02-01'), columns=['OpexWeek'])
dow['OpexWeek'] = dow.index.to_series().apply(isOpexWeek)
print(dow)

dow = pd.DataFrame(index=pd.date_range('2020-01-01', '2021-01-01'), columns=['OpexWeek'])
dow['OpexWeek'] = dow.index.to_series().apply(isOpexWeek)
print(dow[dow.OpexWeek])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接