如何基于两个Datetime DataFrame实现小时级交易资金累计值计算
解决方案:用Pandas向量化操作替代循环,高效计算小时级资金值
不用纠结datetime循环啦,Pandas的向量化操作完全能搞定这个需求,而且比循环高效得多(尤其是数据量大的时候)。我直接给你一套可落地的代码,再一步步解释逻辑:
核心思路
- 把所有时间截断到小时级别,这样同一小时内的交易能被归到同一个时间节点;
- 分别汇总每小时的卖出、买入总金额;
- 把汇总结果和df1的小时序列合并,自动补全无交易小时的0值;
- 用累加计算得到每小时的资金值,全程不用写循环。
完整代码示例
import pandas as pd # ---------------------- 1. 预处理时间数据 ---------------------- # 转换df1的时间格式,并截断到小时(生成匹配用的键) df1['Time'] = pd.to_datetime(df1['Time']) df1['hour'] = df1['Time'].dt.floor('H') # 比如2009-09-13 01:17:00 → 2009-09-13 01:00:00 # 转换df2的交易时间,分别提取卖出、买入的小时节点 df2['Selling Time'] = pd.to_datetime(df2['Selling Time']) df2['Buying Time'] = pd.to_datetime(df2['Buying Time']) df2['sell_hour'] = df2['Selling Time'].dt.floor('H') df2['buy_hour'] = df2['Buying Time'].dt.floor('H') # ---------------------- 2. 按小时汇总交易金额 ---------------------- # 汇总每小时的卖出总金额 sell_total = df2.groupby('sell_hour')['sell'].sum().reset_index() sell_total.rename(columns={'sell_hour': 'hour', 'sell': 'total_sell'}, inplace=True) # 汇总每小时的买入总金额 buy_total = df2.groupby('buy_hour')['buy'].sum().reset_index() buy_total.rename(columns={'buy_hour': 'hour', 'buy': 'total_buy'}, inplace=True) # ---------------------- 3. 合并到df1并计算资金值 ---------------------- # 把汇总结果合并到df1,无交易的小时自动补0 df1 = df1.merge(sell_total, on='hour', how='left').fillna(0) df1 = df1.merge(buy_total, on='hour', how='left').fillna(0) # 计算每小时的资金变动额 df1['capital_change'] = df1['total_sell'] + df1['total_buy'] # 累加得到当前资金值(初始资金默认为0,若有初始值可直接加在后面) df1['Present Value'] = df1['capital_change'].cumsum() # ---------------------- 4. 整理成需求的输出格式 ---------------------- final_result = df1[['hour', 'Present Value']].rename(columns={'hour': 'Time'}).reset_index(drop=True) print(final_result.head())
关键细节解释
dt.floor('H'):这是把时间精确到小时的关键,不管分钟秒数是多少,都会被截断到当前小时的整点,保证同一小时的交易能被正确分组;- 分组求和:卖出交易按「卖出时间的小时」汇总,买入交易按「买入时间的小时」汇总,完全匹配你的需求规则;
cumsum()累加:代替循环实现资金值的逐小时累加,Pandas的内置函数比手动循环快几十倍,数据量越大优势越明显;- 初始资金调整:如果你的初始资金不是0,只需要把最后一行改成
df1['Present Value'] = df1['capital_change'].cumsum() + 初始资金就行。
用这套代码跑你的示例数据,得到的结果完全符合你给出的例子:
- 2009-09-13 01:00:00的资金值是1;
- 02、03点无交易,资金值保持1;
- 04点汇总卖出27,买入-4,资金值变为1+27-4=24。
内容的提问来源于stack exchange,提问作者Abdullah Al Mamun
相关产品推荐
相关产品推荐

