Pandas中基于另一表进出场日期对计算持仓期每日价格变动
实现方案
核心思路
你之前用iterrows()容易出错的核心原因有两个:一是没有统一日期字段的存储格式,字符串比对时容易出现匹配错位;二是逐行配对交易条目时没有做批量区间检索,不仅效率低,还容易出现奇偶行配对混淆的问题。可以通过「结构化拆分交易对→区间批量匹配→差值计算」三步完成,全程不需要逐行遍历。
分步实现代码
1. 基础格式统一
首先把两个表的日期字段从字符串转为标准datetime格式,从根源上避免日期比对错误:
import pandas as pd # 转换日度价格表日期格式 daily_prices_df['Date'] = pd.to_datetime(daily_prices_df['Date']) # 转换交易记录表日期格式 trades_df['Date'] = pd.to_datetime(trades_df['Date'])
2. 拆分配对交易对
你的trades_df是按「入场记录、出场记录」顺序依次排列的,直接把奇偶索引拆成两个子表再拼接,就能得到每笔交易的完整区间:
# 提取所有入场记录:索引为0,2,4...的行 entry_records = trades_df.iloc[::2].reset_index(drop=True).rename( columns={'Date': 'entry_date', 'Price': 'entry_price'} ) # 提取所有出场记录:索引为1,3,5...的行 exit_records = trades_df.iloc[1::2].reset_index(drop=True).rename( columns={'Date': 'exit_date', 'Price': 'exit_price'} ) # 拼接为标准交易区间表 trade_ranges = pd.concat([entry_records, exit_records], axis=1)
3. 批量匹配交易日对应持仓
用IntervalIndex构造可检索的日期区间,直接给每个交易日匹配所属持仓对应的入场价格,不需要逐行遍历比对:
# 为每笔交易构造包含入/出场日的闭区间 trade_ranges['hold_interval'] = trade_ranges.apply( lambda row: pd.Interval( left=row['entry_date'], right=row['exit_date'], closed='both' ), axis=1 ) # 建立可快速检索的区间索引 interval_index = pd.IntervalIndex(trade_ranges['hold_interval']) # 批量匹配每个交易日对应的入场价格 daily_prices_df['entry_price_match'] = trade_ranges['entry_price'].iloc[ interval_index.get_indexer(daily_prices_df['Date']) ].values
4. 计算价格差值
直接用当日收盘价减去匹配到的入场价格,生成最终的Price_Diff列:
daily_prices_df['Price_Diff'] = daily_prices_df['Close'] - daily_prices_df['entry_price_match'] # 删除临时使用的匹配列 daily_prices_df = daily_prices_df.drop(columns=['entry_price_match'])
可调规则说明
- 如果你的持仓规则是「出场日当天即平仓、不计入持仓」,把构造区间时的
closed参数改为'left'即可 - 如果存在多笔交易时间重叠的情况,只需要在交易区间表中增加交易ID字段,匹配时把ID一起关联上即可适配
- 这套批量匹配方法的运行效率远高于
iterrows()遍历,即便覆盖十几年的日度行情,也能在秒级完成计算
最终输出效果示例:
Date Close Price_Diff 2014-11-18 496.0 0.3 2014-11-19 484.0 -11.7 2014-11-20 487.0 -8.7 2014-11-21 495.0 -0.7 2014-11-24 484.0 -11.7 2014-11-25 470.0 -25.7
内容的提问来源于stack exchange,提问作者cmp
相关产品推荐
相关产品推荐

