基于DataFrame中入场/离场信号列计算区间股价涨跌幅
高效计算股票信号区间内的PnL(涨跌幅)
需求说明
需要在包含Entry Signal(入场信号)、Exit Signal(离场信号)和股价的DataFrame中,计算每一组「入场-离场」区间内的涨跌幅(PnL),替代循环遍历每行维护持仓状态的低效方法。
示例数据
Date Price Entry Signal Exit Signal Price Change 2024-01-18 3595.0 NaN NaN 2024-01-19 3280.0 Entry NaN 2024-01-22 3505.0 NaN NaN 2024-01-23 3945.0 NaN Exit (3945 / 3280 - 1) 2024-01-24 4075.0 NaN NaN 2024-03-07 10270.0 Entry NaN 2024-03-08 8120.0 NaN NaN 2024-03-11 6620.0 NaN Exit (6620 / 10270 - 1)
高效实现方法(基于Pandas向量操作)
利用Pandas内置函数实现无循环计算,步骤如下:
1. 标记持仓状态
通过累加入场/离场信号生成持仓状态列,确保只有「空仓(0)」和「持仓(1)」两种状态:
# 入场信号记为+1,离场信号记为-1,累加后限制最小值为0 df['position'] = (df['Entry Signal'].notna() * 1) - (df['Exit Signal'].notna() * 1) df['position'] = df['position'].cumsum().clip(lower=0)
2. 填充对应入场价格
在入场信号出现的行记录当日股价,并用向前填充(ffill)将入场价覆盖整个持仓区间:
# 仅在入场日记录价格,其余行用前一个入场价填充 df['entry_price'] = df.loc[df['Entry Signal'].notna(), 'Price'] df['entry_price'] = df['entry_price'].ffill()
3. 计算离场时的涨跌幅
仅在离场信号出现的行,用当日价格除以对应入场价计算涨跌幅:
# 仅在Exit Signal行计算涨跌幅,其余行留空 df['Price Change'] = df.apply( lambda x: (x['Price'] / x['entry_price'] - 1) if x['Exit Signal'] == 'Exit' else pd.NA, axis=1 )
完整代码示例
import pandas as pd # 构造示例DataFrame data = { 'Date': ['2024-01-18', '2024-01-19', '2024-01-22', '2024-01-23', '2024-01-24', '2024-03-07', '2024-03-08', '2024-03-11'], 'Price': [3595.0, 3280.0, 3505.0, 3945.0, 4075.0, 10270.0, 8120.0, 6620.0], 'Entry Signal': [pd.NA, 'Entry', pd.NA, pd.NA, pd.NA, 'Entry', pd.NA, pd.NA], 'Exit Signal': [pd.NA, pd.NA, pd.NA, 'Exit', pd.NA, pd.NA, pd.NA, 'Exit'] } df = pd.DataFrame(data) df['Date'] = pd.to_datetime(df['Date']) # 计算持仓状态 df['position'] = (df['Entry Signal'].notna() * 1) - (df['Exit Signal'].notna() * 1) df['position'] = df['position'].cumsum().clip(lower=0) # 填充入场价格 df['entry_price'] = df.loc[df['Entry Signal'].notna(), 'Price'] df['entry_price'] = df['entry_price'].ffill() # 计算涨跌幅 df['Price Change'] = df.apply( lambda x: (x['Price'] / x['entry_price'] - 1) if x['Exit Signal'] == 'Exit' else pd.NA, axis=1 ) # 查看结果 print(df[['Date', 'Price', 'Entry Signal', 'Exit Signal', 'Price Change']])
说明
这种方法全程使用Pandas的向量化操作,避免了循环遍历的性能瓶颈,在处理大规模行情数据时效率优势明显。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

