基于红利再投资计划调整股票持仓数的Pythonic实现方案问询
基于DRIP调整持仓股数的Pythonic实现方案
需求说明
基于红利再投资计划(DRIP)调整模拟投资组合的持仓股数,规则为:
- 每次分红时,用当前持仓股数 × 分红金额 ÷ 当前股价得到新增股份,累加到原持仓中
- 未分红时,持仓股数保持上一期数值不变
示例数据
import pandas as pd vals = [38.46429771, 46.01712878, 38.89251387, 33.89977144, 27.66171419, 38.03103652, 31.26521149, 35.82193894, 49.47433244, 33.60148345,] divi = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0] shares = [30,0,0,0,0,0,0,0,0,0] sample = pd.DataFrame(data=zip(vals, divi,shares), index = range(0,10), columns=['Open', 'Dividends', 'share_count'])
示例DataFrame结构:
| Open | Dividends | share_count | |
|---|---|---|---|
| 0 | 38.464298 | 0 | 30 |
| 1 | 46.017129 | 0 | 0 |
| 2 | 38.892514 | 1 | 0 |
| 3 | 33.899771 | 0 | 0 |
| 4 | 27.661714 | 0 | 0 |
| 5 | 38.031037 | 1 | 0 |
| 6 | 31.265211 | 0 | 0 |
| 7 | 35.821939 | 0 | 0 |
| 8 | 49.474332 | 1 | 0 |
| 9 | 33.601483 | 0 | 0 |
原循环实现
cum_val = [] x = max(sample.share_count) t = [] for d, sc, op in zip(sample.Dividends, sample.share_count, sample.Open): divi = (x*d)/op t = divi+x cum_val.append(t) if t > x: x = t else: pass
更Pythonic的矢量化实现
利用pandas的矢量化操作和累计乘积cumprod(),完全避免循环,代码更简洁高效:
# 获取初始持仓股数 initial_shares = sample['share_count'].iloc[0] # 计算每个时间点的持仓乘数:分红时为1 + 分红/股价,未分红时为1 sample['multiplier'] = 1 + sample['Dividends'] / sample['Open'] # 计算累计持仓:初始股数 × 累计乘数 sample['share_count'] = initial_shares * sample['multiplier'].cumprod()
实现逻辑说明
- 乘数计算:每个时间点的持仓变化倍数,未分红时倍数为1(持仓不变),分红时倍数为
1 + 分红金额/当前股价(原持仓 + 新增股份) - 累计乘积:
cumprod()会计算从第一个时间点到当前时间点的乘数乘积,本质是把每一次的持仓变化连续叠加 - 结果赋值:用初始持仓乘以累计乘数,直接得到每个时间点的最终持仓数
优势
- 代码更简洁可读,符合pandas的惯用写法
- 矢量化操作比Python循环效率更高,尤其当数据量较大时性能提升明显
- 避免手动维护循环中的状态变量(如原代码中的
x),减少出错概率
内容的提问来源于stack exchange,提问作者canconfirm24
相关产品推荐
相关产品推荐

