2015-10-31 21 views
0

我試圖爲財務事件分析準備好數據,並且想要計算買入和持有異常回報(BHAR)。對於測試數據集,我有三個事件(由event_id記錄),並且對於每個事件,我有272行,從t-252天到t + 20天(由變量時間記錄)。對於每一天,我也有股票的回報數據(ret)以及預期收益(Exp_Ret),這是使用市場模型計算的。這裏是一個樣本的數據:在30天的時間段內在PANDAS上滾動產品

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 

這就是問題所在。我想計算以下巴爾式的每一天:

enter image description here

因此,使用上述式作爲一個例子,如果我想以計算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()) 

這似乎是正確執行巴爾方程,它會在加的左側正確的產品 - 雖然它會輸入兩行的值(可以通過移位來解決)。但是,一個問題是,數據框中有三個不同的「組」(3個事件),如果窗口要超過30天,它可能會開始使用下一個事件的產品。我試圖實現一個GROUPBYrolling_apply但一直得到錯誤:類型錯誤:「系列」的對象是可變的,因此它們不能被散列

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

我相信我在這裏缺少一些基本的東西所以任何幫助,將不勝感激。我可能只需要從另一個角度來看待它。這裏有一個想法:最後,我最感興趣的是從時間= 0開始獲得30天和60天的買入和持有異常收益。那麼,也許在時間= 0時選擇每個事件更容易,然後計算未來30天的產品?我不確定我如何才能最好地解決這個問題。

在此先感謝您的任何見解。

回答

1

已編輯,以便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]這樣,你只能得到需要的部分。

你明顯可以在組中使用.apply()摺疊一行中的循環,但我喜歡這種方式。較短的行讀取=更好的可讀性。

+0

謝謝你 - 看起來很有希望。但是,我得到以下錯誤使用任一建議:「TypeError:只有長度爲1的數組可以轉換爲Python標量。」 –

+0

哪裏?在'返回np。cumprod(ARR + 1)'? – Kartik

+0

我在任何地方都看不到 - 看起來像這裏:----> 2組['BHAR'] = pd.rolling_apply(group ['ret'],10,bhar) - pd.rolling_apply (group ['Exp_Ret'],10,bhar) –

1
# 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 
+0

謝謝!這似乎是一個優雅的解決方案。很好學習新事物。 –