【问题标题】:Pandas Week of the Month Business Day Stock Price Data每月熊猫周工作日股价数据
【发布时间】:2020-05-28 18:19:49
【问题描述】:

我的问题与以下不同:

问题1:Week of a month pandas 问题2:Week number of the month

上述问题涉及假设一周中有 7 天。它试图计算每周有 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

我不知道如何提供一些示例 data 但如果您转到“https://aroussi.com/post/python-yahoo-finance”页面并使用作者的 yfinance 包,您将能够获取一些价格数据。

上面的函数将找到该月的第 3 周(全部为 True)。此外,它还将设置该周的星期五。

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

【问题讨论】:

    标签: python pandas datetime


    【解决方案1】:

    一种方法是使用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 之前的周六和周日是 True,但是因为您说您的数据是工作日,所以这应该无关紧要。

    用于日期时间系列的 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 周,我需要等到星期五。我需要一种方法来知道我在星期一是运营支出周。
      • @user1234440 所以你更关心OPEXweek 而不是OPEXFriday?你需要OPEXFriday吗?
      • 我并不真正关心 OpexFriday,我只需要 opex 周。从那里我可以得到我需要的一切。谢谢!
      【解决方案3】:
      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
      

      【讨论】:

      • 你是对的。我已经更正了我的答案。现在应该可以了。我附上了一些测试以确保它按预期工作
      【解决方案4】:

      虽然问题的标题是“本月的熊猫周”,但根据您对其他答案的 cmets,您似乎主要对确定“OpEx week”感兴趣,即交易周(即周一至周五)包含第三个星期五。

      如果上述假设和定义是正确的,那么这个函数就可以完成这项工作:

      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])
      

      【讨论】:

        猜你喜欢
        • 2015-03-23
        • 1970-01-01
        • 1970-01-01
        • 2021-10-08
        • 2020-02-08
        • 2019-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多