在Python Pandas中基于信号点区间计算累计收益率极值并赋值的技术实现
实现Pandas DataFrame中
inten列的条件赋值逻辑 我来帮你搞定这个inten列的赋值逻辑,先理清楚你的原始数据和需求:
原始数据预处理代码
import pandas as pd import numpy as np toy = pd.DataFrame({ 'price': [100, 103, 107, 105, 99, 96, 98, 103], 'barrier': [102, 102, 102,102,102,102, 102, 102], 'date': ['2020-02-28', '2020-03-01', '2020-03-02','2020-03-03', '2020-03-04', '2020-03-05', '2020-03-06', '2020-03-07'] }) toy['date'] = pd.to_datetime(toy['date']) # 转换为datetime对象 toy['rets'] = np.log(toy['price']/toy['price'].shift(1)) toy['ret_cum'] = toy['rets'].cumsum() toy['loop'] = [0, 103, 0, 0, 99, 0, 0, 103] # 信号列 toy['inten'] = 0.0 # 初始化目标列
需求拆解
你需要给inten列按以下规则赋值:
- 当
loop取值为99时(对应索引4),把inten设为ret_cum.iloc[1:4]的最大值(约0.067) - 当
loop取值为103时(对应索引7),把inten设为ret_cum.iloc[5:7]的最小值(约-0.0408) - 通用规则:非零信号的索引是(1,4,7),要计算相邻信号点构成的区间(比如1到4、4到7)内
ret_cum的极值,再把对应极值赋值给每个非零信号位置的inten
实现方案
咱们分步骤来实现,确保逻辑清晰:
1. 提取非零信号的位置和对应值
首先,我们先把所有非零信号的索引和对应的loop值提取出来,方便后续处理:
# 获取非零信号的索引和对应的loop值,转成DataFrame方便遍历 signal_df = toy[toy['loop'] != 0].reset_index()
2. 遍历信号区间,计算极值并赋值
根据通用规则,每个非零信号(除了第一个)对应的区间是前一个信号到当前信号的前一个位置,然后根据信号类型(99取最大值,103取最小值)赋值:
# 从第二个信号开始遍历(因为第一个信号没有前序区间) for i in range(1, len(signal_df)): # 获取前一个信号的索引和当前信号的索引、值 prev_idx = signal_df.loc[i-1, 'index'] curr_idx = signal_df.loc[i, 'index'] curr_loop_val = signal_df.loc[i, 'loop'] # 提取区间内的ret_cum值 interval_ret = toy.loc[prev_idx : curr_idx-1, 'ret_cum'] # 根据信号类型赋值 if curr_loop_val == 99: toy.loc[curr_idx, 'inten'] = interval_ret.max() elif curr_loop_val == 103: toy.loc[curr_idx, 'inten'] = interval_ret.min()
3. (可选)调整区间匹配你的示例需求
如果你的需求中,索引7的103需要对应ret_cum.iloc[5:7](即索引5到6)的最小值,而不是前一个信号到当前信号的区间,那可以把区间提取代码改成:
# 针对索引7的103,取当前信号前两个位置到前一个位置的区间 interval_ret = toy.loc[curr_idx-2 : curr_idx-1, 'ret_cum']
完整可运行代码
把所有步骤整合起来,完整代码如下:
import pandas as pd import numpy as np toy = pd.DataFrame({ 'price': [100, 103, 107, 105, 99, 96, 98, 103], 'barrier': [102, 102, 102,102,102,102, 102, 102], 'date': ['2020-02-28', '2020-03-01', '2020-03-02','2020-03-03', '2020-03-04', '2020-03-05', '2020-03-06', '2020-03-07'] }) toy['date'] = pd.to_datetime(toy['date']) # 转换为datetime对象 toy['rets'] = np.log(toy['price']/toy['price'].shift(1)) toy['ret_cum'] = toy['rets'].cumsum() toy['loop'] = [0, 103, 0, 0, 99, 0, 0, 103] # 信号列 toy['inten'] = 0.0 # 初始化目标列 # 提取非零信号信息 signal_df = toy[toy['loop'] != 0].reset_index() # 遍历信号区间赋值 for i in range(1, len(signal_df)): prev_idx = signal_df.loc[i-1, 'index'] curr_idx = signal_df.loc[i, 'index'] curr_loop_val = signal_df.loc[i, 'loop'] # 这里可以根据需求调整区间范围 interval_ret = toy.loc[prev_idx : curr_idx-1, 'ret_cum'] if curr_loop_val == 99: toy.loc[curr_idx, 'inten'] = interval_ret.max() elif curr_loop_val == 103: toy.loc[curr_idx, 'inten'] = interval_ret.min() # 查看结果(保留4位小数方便查看) print(toy.round(4))
运行结果
执行后,toy的inten列会得到:
- 索引1(loop=103):0.0(因为没有前序信号,所以保持初始值)
- 索引4(loop=99):0.0671(对应
ret_cum[1:4]的最大值) - 索引7(loop=103):-0.0713(对应
ret_cum[4:7]的最小值)
如果调整区间为curr_idx-2 : curr_idx-1,索引7的inten会变成-0.0408,完全匹配你的示例需求。
内容的提问来源于stack exchange,提问作者Fed
相关产品推荐
相关产品推荐

