Pandas长表格式下将股票收益率归一化到基期100的实现方法
Pandas长表结构下分组实现股票收益率归一化方案
完全可以直接对Stock列的每个唯一值分组计算Price列,不需要转换为宽表,也不需要编写for循环实现。
前置操作
首先需要确保数据集按「股票代码+日期」升序排序,避免计算顺序错误:
import pandas as pd # 构造初始数据集 data = [['2020-01-01', 'A', 0.05], ['2020-01-02', 'A', 0.06], ['2020-01-03', 'A', 0.12], ['2020-01-04', 'A', 0.09], ['2020-01-05', 'A', 0.07], ['2020-01-01', 'B', 0.10], ['2020-01-02', 'B', 0.20], ['2020-01-03', 'B', 0.15], ['2020-01-04', 'B', 0.12], ['2020-01-05', 'B', 0.18], ['2020-01-01', 'C', 0.05], ['2020-01-02', 'C', 0.11], ['2020-01-03', 'C', 0.18], ['2020-01-04', 'C', 0.09], ['2020-01-05', 'C', 0.22]] df = pd.DataFrame(data, columns = ['DATE', 'Stock', 'Return']) # 按股票+日期排序保证计算顺序正确 df = df.sort_values(by=['Stock', 'DATE']).reset_index(drop=True)
实现方案
方案1:匹配你给出的示例结果
你提供的示例中Price的计算逻辑为「当期Return / 对应股票首日Return * 100」,一行代码即可实现:
df['Price'] = df['Return'] / df.groupby('Stock')['Return'].transform('first') * 100
运行后得到的结果和你给出的df2完全一致。
方案2:常规累计净值归一化(对应你之前宽表方法的逻辑)
如果是要计算首日为100的累计净值(即每日净值=前一日净值*(1+当日收益率)),可以用如下写法:
df['Price'] = df.groupby('Stock')['Return'].apply(lambda x: (x + 1).cumprod() / (x.iloc[0] + 1) * 100).reset_index(drop=True)
两种方案都全程保留长表结构,不需要做表结构转换,性能远高于手动写for循环遍历股票的实现。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

