簡體   English   中英

在30天的時間范圍內在PANDAS中滾動產品

[英]Rolling Product in PANDAS over 30-day time window

我正在嘗試為進行財務事件分析准備數據,並希望計算購買和持有異常收益(BHAR)。 對於測試數據集,我有3個事件(由event_id表示 ),對於每個事件,我有272行,從t-252天到t + 20天(由time表示 )。 對於每一天,我還擁有股票的收益數據( ret )以及使用市場模型計算的預期收益( Exp_Ret )。 這是數據示例:

index   event_id    time    ret       vwretd    Exp_Ret
0       0           -252    0.02905   0.02498   nan
1       0           -251    0.01146   -0.00191  nan
2       0           -250    0.01553   0.00562   nan
...
250     0           -2      -0.00378  0.00028   -0.00027
251     0           -1      0.01329   0.00426   0.00479
252     0            0      -0.01723  -0.00875  -0.01173
271     0            19     0.01335   0.01150   0.01398
272     0            20     0.00722   -0.00579  -0.00797
273     1           -252    0.01687   0.00928   nan
274     1           -251    -0.00615  -0.01103  nan

這就是問題。 我想每天計算以下BHAR公式:

在此處輸入圖片說明

因此,以上述公式為例,如果我想計算10天的買入和持有異常收益,我將不得不計算(1 + ret_t = 0)x(1 + ret_t = 1)。 .x(1 + ret_t = 10),然后對預期收益做同樣的事情,(1 + Exp_Ret_t = 0)x(1 + Exp_Ret_t = 1)... x(1 + Exp_Ret_t = 10),然后減去后者從前。

我在使用rolling_apply方面取得了一些進展,但是並不能解決我的所有問題:

df['part1'] = pd.rolling_apply(df['ret'], 10, lambda x : (1+x).prod())

這似乎正確地實現了BHAR方程的左側,因為它將添加正確的乘積-盡管它將向下兩行輸入值(可以通過移位來解決)。 但是,一個問題是,數據框中有3個不同的“組”(3個事件),如果窗口前進30天以上,它可能會開始使用下一個事件的產品。 我嘗試使用rolling_apply實現groupby ,但始終出現錯誤: TypeError:“系列”對象是可變的,因此無法進行哈希處理

df.groupby('event_id').apply(pd.rolling_apply(df['ret'], 10, lambda x : (1+x).prod()))

我敢肯定,我在這里缺少一些基本的知識,因此我們將不勝感激。 我可能只需要從另一個角度來處理它。 這是一個想法:最后,我最感興趣的是從時間= 0開始獲得30天和60天的購買和持有異常收益。 因此,也許更容易選擇時間= 0的每個事件,然后計算未來30天的產品? 我不確定如何才能最好地做到這一點。

預先感謝您的任何見解。

已進行編輯,以使BHAR的最終值包含在主DataFrame中。

BHAR = pd.Series()

def bhar(arr):
    return np.cumprod(arr+1)[-1]

grouped = df.groupby('event_id')
    for name, group in grouped:
        BHAR = BHAR.append(pd.rolling_apply(group['ret'],10,bhar) -
                           pd.rolling_apply(group['Exp_Ret'],10,bhar))

df['BHAR'] = BHAR

然后,您可以使用df[df['time']>=0]對DataFrame進行切片,以便僅獲得所需的部分。

您顯然可以在該組上使用.apply()將循環折疊成一行,但我喜歡這種方式。 短行閱讀=更好的可讀性。

# Create sample data.
np.random.seed(0)
VOL = .3
df = pd.DataFrame({'event_id': [0] * 273 + [1] * 273 + [2] * 273, 
                   'time': range(-252, 21) * 3, 
                   'ret': np.random.randn(273 * 3) * VOL / 252 ** .5, 
                   'Exp_Ret': np.random.randn(273 * 3) * VOL / 252 ** .5})

# Pivot on time and event_id.
df = df.set_index(['time', 'event_id']).unstack('event_id')

# Calculated return difference from t=0.
df_diff = df.ix[df.index >= 0, 'ret'] - df.loc[df.index >= 0, 'Exp_Ret']

# Calculate cumulative abnormal returns.
cum_returns = (1 + df_diff).cumprod() - 1

# Get 10 day abnormal returns.
>>> cum_returns.loc[10]
event_id
0   -0.014167
1   -0.172599
2   -0.032647
Name: 10, dtype: float64

這是我所做的:

((df+1.0) \
  .apply(lambda x: np.log(x),axis=1)\
  .rolling(365).sum() \
  .apply(lambda x: np.exp(x),axis=1)-1.0)

結果是滾動產品。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM