【问题标题】:Pandas P&L rollup to the next business dayPandas 损益汇总到下一个工作日
【发布时间】:2025-12-26 05:00:11
【问题描述】:

我很难有效地做到这一点。我在数据框中有一些股票和每日损益信息。实际上,我有数百万行数据,所以效率很重要! 数据框看起来像:

-------------------------------
| Date       | Security | P&L |
-------------------------------
| 2016-01-01 | AAPL     | 100 |
-------------------------------
| 2016-01-02 | AAPL     | 200 |
-------------------------------
| 2016-01-03 | AAPL     | 300 |
-------------------------------
| 2016-01-04 | AAPL     | -200 |
-------------------------------

所有,我想做的是将损益表滚动到下一个工作日(不包括所有美国节假日和周末) 因此,生成的 Dataframe 如下所示:

-------------------------------
| Date       | Security | P&L |
-------------------------------
| 2016-01-04 | AAPL     | 400 |
-------------------------------

我正在寻找一种有效的方法来实现这一目标。我确实有数以千计的证券和超过 5 年的数据要处理,所以很遗憾,蛮力无法工作!

在此先感谢,并非常感谢任何关于此的指示!

【问题讨论】:

  • 你有要放弃的日子列表吗?
  • @ansev 你可以使用weekday 和这个库holidays
  • 你可以考虑在这里使用dask

标签: python pandas pandas-groupby python-datetime quantitative-finance


【解决方案1】:

我们可以创建营业日期的DataFrame,然后merge_asof。然后我们可以对此进行分组以获得总和。

import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar

#df['Date'] = pd.to_datetime(df.Date)
date_min = '2015-01-01'
date_max = '2016-12-31'

cal = USFederalHolidayCalendar()
holidays = cal.holidays(date_min, date_max).tolist()
df2 = pd.DataFrame({'bdate': pd.bdate_range(date_min, date_max, 
                                            holidays=holidays, freq='C')})

res = pd.merge_asof(df, df2, left_on='Date', right_on='bdate', direction='forward')
#        Date Security  P&L      bdate
#0 2016-01-01     AAPL  100 2016-01-04
#1 2016-01-02     AAPL  200 2016-01-04
#2 2016-01-03     AAPL  300 2016-01-04
#3 2016-01-04     AAPL -200 2016-01-04

res.groupby(['Security', 'bdate'])['P&L'].sum()
#Security  bdate     
#AAPL      2016-01-04    400

【讨论】:

  • 应该的。这将是 1:1 的合并,带来未来最接近的工作日,因此无需担心更改形状。只需确保指定正确的最小和最大日期以包含完整的数据集。
【解决方案2】:

IIUC 你可以这样做:

import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
import numpy as np

date_min = '2015-01-01'
date_max = '2016-12-31'

cal = USFederalHolidayCalendar()
holidays = cal.holidays(date_min, date_max).tolist()

df = pd.DataFrame({"Date":pd.date_range(date_min, date_max)})
df["Security"] ="APPL"
df["P&L"] = np.random.randint(-1000, 1000, len(df))

df[~df["Date"].isin(holidays)].groupby("Security")\
                              .agg({"Date":"max",
                                    "P&L":"sum"})\
                              .reset_index()



【讨论】:

  • 谢谢...我想这样就可以了
  • 如果您想更快地运行它,这应该可以在不改变 dask 的情况下工作。我可能会建议你,如果这是一项日常工作,你应该考虑其他方法。
  • 是的,我不知道 dask...它看起来很有希望....要去试验一下!谢谢
最近更新 更多