You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于月末日期滚动计算PERMNO分组下RET最低1%值的滚动均值

问题描述
  • 需求:针对每个月末日期和每个PERMNO(公司标识符),计算DataFrame中RET列过去252天内最低1%值的滚动均值。
  • 用户尝试代码:
def get_es(x):
    return (x<=x.iloc[0:249].quantile(0.01)).mean()
df['es_1pct'] = df.groupby(['PERMNO'])['RET'].rolling(window = 250, min_periods=200).apply(get_es).reset_index()['RET']
  • 存在问题:结果完全错误,返回的是整个样本中低于1%分位数的观测比例,且未实现正确的滚动计算(代码参考自非滚动场景方案)。
  • 求助要点:
    1. 如何仅在月末日期执行滚动计算以提速;
    2. 如何正确计算最低1%值的滚动均值。
解决方案

1. 仅在月末执行计算(提速)

先标记并筛选出月末日期的行,仅对这些行执行滚动计算,避免无意义的全量计算。假设DataFrame包含date日期列:

import pandas as pd

# 转换日期格式并标记月末行
df['date'] = pd.to_datetime(df['date'])
df['is_month_end'] = df['date'].dt.is_month_end

# 仅保留月末数据用于后续计算
month_end_df = df[df['is_month_end']].copy()

2. 正确计算滚动最低1%值的均值

原代码的核心错误:一是用固定切片而非完整滚动窗口,二是逻辑错误——计算的是比例而非均值。修正逻辑为:在每个滚动窗口内,先找到1%分位数阈值,筛选出窗口内低于等于该阈值的RET值,再计算这些值的均值。

修正后完整代码

def calculate_bottom_1pct_mean(window):
    # 计算当前滚动窗口的1%分位数
    q1_threshold = window.quantile(0.01)
    # 筛选窗口内低于等于阈值的RET值
    bottom_values = window[window <= q1_threshold]
    # 返回均值,无符合条件值时返回NaN
    return bottom_values.mean()

# 将日期设为索引,使用时间窗口计算
month_end_df = month_end_df.set_index('date')
month_end_df['es_1pct'] = month_end_df.groupby('PERMNO')['RET'].rolling(
    window='252D',  # 按过去252天的时间范围计算,若按交易日数量可改为window=252
    min_periods=200  # 至少需要200个观测值才执行计算
).apply(calculate_bottom_1pct_mean, raw=False)

# 若需要将结果合并回原DataFrame
df = df.merge(month_end_df[['es_1pct']], on=['PERMNO', 'date'], how='left')

关键说明

  • raw=False确保传入函数的是Series而非numpy数组,方便后续筛选操作;
  • 时间窗口window='252D'适用于日期索引场景,能精准匹配过去252天的数据;若数据按交易日排列(一年约252个交易日),可改用固定行数window=252;
  • 若窗口内无符合条件的数值,函数返回NaN,可根据业务需求调整为0或其他默认值。

内容的提问来源于stack exchange,提问作者DJP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:42:18