Python修正股票日收益率计算错误,获取上市初期30/60/90日平均收益率
修正股票上市初期日收益率计算代码错误
问题背景
现有Excel文件DF0.xlsx,包含DATE(日期)、CODE(股票代码)、CLOSEPRICE(收盘价)、FIRST TRADING DAY(上市首日)四列,记录了各股票上市首日及之后每日的收盘价。需求是:按股票上市首日起,计算其上市初期30、60、90日的日收益率,并求出对应周期的平均收益率。当前代码中(thirty_day_prices[1:] / thirty_day_prices[-1]) - 1的日收益率计算逻辑错误,需修正该部分以得到正确结果。
现有错误代码
import pandas as pd # 读取Excel数据 df0 = pd.read_excel("DF0.xlsx") # 初始化结果列表 result_list = [] # 按股票代码分组处理 for stock_code, group_data in df0.groupby("CODE"): # 按日期升序排序 sorted_group = group_data.sort_values("DATE", ascending=True) # 筛选上市首日及之后的交易数据,取前30个交易日的收盘价 thirty_day_prices = sorted_group[ sorted_group["DATE"] >= sorted_group["FIRST TRADING DAY"] ].head(30)["CLOSEPRICE"].values # 错误的日收益率计算逻辑 thirty_day_returns = (thirty_day_prices[1:] / thirty_day_prices[-1]) - 1 # 计算30日周期的平均收益率 avg_30_return = thirty_day_returns.mean() # 60日、90日逻辑与30日一致(此处省略重复代码) result_list.append({ "CODE": stock_code, "AVG_30DAY_RETURN": avg_30_return # 可添加AVG_60DAY_RETURN、AVG_90DAY_RETURN字段 }) # 转换为结果DataFrame result_df = pd.DataFrame(result_list)
样本数据示例
| DATE | CODE | CLOSEPRICE | FIRST TRADING DAY |
|---|---|---|---|
| 2023-01-03 | A0001 | 10.20 | 2023-01-03 |
| 2023-01-04 | A0001 | 10.50 | 2023-01-03 |
| 2023-01-05 | A0001 | 10.30 | 2023-01-03 |
| 2023-01-06 | A0001 | 10.60 | 2023-01-03 |
| ... | ... | ... | ... |
错误原因分析
原代码中用thirty_day_prices[-1](即30日周期的最后一天收盘价)作为分母,这是错误的逻辑。正确的日收益率计算应该是:当日收盘价 ÷ 前一日收盘价 - 1,反映当日相对于前一日的价格变动幅度。
修正后的代码
仅需替换错误的收益率计算行,同时补充数据校验逻辑(处理不足指定交易日的情况):
import pandas as pd df0 = pd.read_excel("DF0.xlsx") result_list = [] for stock_code, group_data in df0.groupby("CODE"): sorted_group = group_data.sort_values("DATE", ascending=True) # 筛选上市首日及之后的交易数据 post_listing_data = sorted_group[sorted_group["DATE"] >= sorted_group["FIRST TRADING DAY"]] # 计算30日周期收益率 thirty_day_subset = post_listing_data.head(30)["CLOSEPRICE"].values if len(thirty_day_subset) >= 2: # 至少需要2个数据点才能计算日收益率 # 正确的日收益率计算:当日价格/前一日价格 - 1 thirty_day_returns = (thirty_day_subset[1:] / thirty_day_subset[:-1]) - 1 avg_30_return = thirty_day_returns.mean() else: avg_30_return = None # 数据不足时标记为None # 同理处理60日、90日周期 sixty_day_subset = post_listing_data.head(60)["CLOSEPRICE"].values avg_60_return = (sixty_day_subset[1:] / sixty_day_subset[:-1] - 1).mean() if len(sixty_day_subset)>=2 else None ninety_day_subset = post_listing_data.head(90)["CLOSEPRICE"].values avg_90_return = (ninety_day_subset[1:] / ninety_day_subset[:-1] - 1).mean() if len(ninety_day_subset)>=2 else None result_list.append({ "CODE": stock_code, "AVG_30DAY_RETURN": avg_30_return, "AVG_60DAY_RETURN": avg_60_return, "AVG_90DAY_RETURN": avg_90_return }) result_df = pd.DataFrame(result_list) # 可选:保存结果到Excel # result_df.to_excel("stock_return_avg.xlsx", index=False)
预期输出示例
| CODE | AVG_30DAY_RETURN | AVG_60DAY_RETURN | AVG_90DAY_RETURN |
|---|---|---|---|
| A0001 | 0.0025 | 0.0018 | 0.0012 |
| A0002 | 0.0031 | 0.0022 | 0.0015 |
| B0001 | None | 0.0010 | 0.0008 |
内容的提问来源于stack exchange,提问作者Bianconera99
相关产品推荐
相关产品推荐

