如何用Pandas标记滚动窗口内首次出现的新高点?
问题描述
我用以下代码标记收盘价是否突破52周新高:
df1['52wkh'] = df1['high'].rolling(min_periods=1, window=252).max() df1['is_52wkch'] = df1['close'] >= df1.shift(1)['52wkh']
运行后得到的数据如下:
close high 52wkh is_52wkch date 2021-11-22 4682.939941 4743.830078 4743.830078 False 2021-12-27 4791.189941 4791.490234 4791.490234 True 2021-12-28 4786.350098 4807.020020 4807.020020 False 2021-12-30 4778.729980 4808.930176 4808.930176 False 2022-01-04 4793.540039 4818.620117 4818.620117 False 2023-06-12 4338.930176 4340.129883 4340.129883 True 2023-06-13 4369.009766 4375.370117 4375.370117 True 2023-06-14 4372.589844 4391.819824 4391.819824 False 2023-06-15 4425.839844 4439.200195 4439.200195 True 2023-06-16 4409.589844 4448.470215 4448.470215 False
但我需要仅标记滚动窗口内首次出现的新高点,期望结果如下:
close high 52wkh is_52wkch date 2021-11-22 4682.939941 4743.830078 4743.830078 False 2021-12-27 4791.189941 4791.490234 4791.490234 True 2021-12-28 4786.350098 4807.020020 4807.020020 False 2021-12-30 4778.729980 4808.930176 4808.930176 False 2022-01-04 4793.540039 4818.620117 4818.620117 False 2023-06-12 4338.930176 4340.129883 4340.129883 True 2023-06-13 4369.009766 4375.370117 4375.370117 False 2023-06-14 4372.589844 4391.819824 4391.819824 False 2023-06-15 4425.839844 4439.200195 4439.200195 False 2023-06-16 4409.589844 4448.470215 4448.470215 False
我尝试过分组计数但没成功,因为需要在滚动52周窗口内统计True值的数量。目前想到的解决方案是:
df1['52wkh'] = df1['high'].rolling(min_periods=1, window=252).max() # 标记所有符合条件的52周新高 df1['is_52wkch'] = df1['close'] >= df1.shift(1)['52wkh'] # 统计过去52周内上述标记的出现次数 df1['is_52wkch_cnt'] = df1.rolling(window=252)['is_52wkch'].sum()
之后通过筛选is_52wkch==True且is_52wkch_cnt == 1来标记滚动窗口内的首次52周新高,请问这个思路是否正确?
解答
你的思路存在逻辑漏洞,无法准确实现需求:
- 滚动窗口的
sum()是统计窗口内所有True的总数,但后续出现新的新高点时,窗口内的True数量会累计增加,无法区分“首次”是针对当前这个新高值的首次突破,还是窗口内所有新高的第一次出现。
正确的实现逻辑应该聚焦于「52周新高值的首次更新」:
- 先识别52周新高值发生更新的日期:当当前的
52wkh大于前一天的52wkh时,说明出现了新的52周高点。 - 再结合收盘价突破前一天新高的条件,仅在新高值首次出现且收盘价突破的日期标记为
True。
具体代码如下:
# 计算52周滚动高点 df1['52wkh'] = df1['high'].rolling(min_periods=1, window=252).max() # 标记52周新高值是否更新(当天出现了新的历史高点) df1['new_52wkh'] = df1['52wkh'] > df1['52wkh'].shift(1) # 仅当新高值更新,且收盘价突破前一天的52周高点时,标记为True df1['is_52wkch'] = df1['new_52wkh'] & (df1['close'] >= df1['52wkh'].shift(1)) # 可选:删除中间辅助列 df1 = df1.drop('new_52wkh', axis=1)
运行后即可得到你期望的结果:只有当某个新的52周高点首次出现,且收盘价突破了之前的高点时,才会标记为True,后续再出现更高的高点但未满足首次突破条件时不会重复标记。
你原始代码中df1['close'] >= df1.shift(1)['52wkh']的逻辑是正确的,结合新高值更新的判断就能精准定位首次突破点。
内容的提问来源于stack exchange,提问作者mike01010
相关产品推荐
相关产品推荐

