我正在进行事件研究,并希望将功能的结果打包为易于管理的形式。下面的函数以以下形式返回结果:
结果是针对一个事件窗口(-5,+ 5天)分析的一个索引。我需要分析17个索引和120多个活动日,这需要大量的输出才能进行进一步的计算。
我尝试将结果打包到字典中,但是输出是多级字典,我不知道如何将其解压缩成有意义的形状。
我正在考虑将结果附加到np.ndarray或替换函数的输出,以便它将值的列表/系列/数组作为输入,然后汇总输出。
不幸的是,这超出了我的技能水平,因为我对Python相当陌生,但是我正在尝试学习尽可能多的东西,因此任何建议/帮助都将不胜感激。
功能:
def get_cum_returns(prices, sid, date, days_before, days_after, benchmark_sid):
"""
Calculates cumulative and abnormal returns for the sid & benchmark
Parameters
----------
prices : pd.DataFrame
Pricing history DataFrame obtained from `get_pricing`. Index should
be the datetime index and sids should be columns.
sid : int or zipline.assets._assets.Equity object
Security that returns are being calculated for.
date : datetime object
Date that will be used as t=0 for cumulative return calcuations. All
returns will be calculated around this date.
days_before, days_after : int
Days before/after to be used to calculate returns for.
benchmark : int or zipline.assets._assets.Equity object
Returns
-------
sid_returns : pd.Series
Cumulative returns time series from days_before ~ days_after from date
for sid
benchmark_returns : pd.Series
Cumulative returns time series for benchmark sid
abnormal_returns : pd.Series
Abnomral cumulative returns time series for sid compared against benchmark
"""
day_zero_index = prices.index.searchsorted(date)
starting_index = max(day_zero_index - days_before, 0)
ending_index = min(day_zero_index + days_after + 1, len(prices.index) - 1)
if starting_index < 0 or ending_index >= len(prices.index):
return None
if sid == benchmark_sid:
temp_price = prices.iloc[starting_index:ending_index,:].loc[:,[sid]]
else:
temp_price = prices.iloc[starting_index:ending_index,:].loc[:,[sid, benchmark_sid]]
beta = calc_beta(sid, benchmark_sid, temp_price)
if beta is None:
return
daily_ret = temp_price.pct_change().fillna(0)
daily_ret['abnormal_returns'] = daily_ret[sid] - beta*daily_ret[benchmark_sid]
cum_returns = (daily_ret + 1).cumprod() - 1
try:
# If there's not enough data for event study,
# return None
cum_returns.index = range(starting_index - day_zero_index,
ending_index - day_zero_index)
except:
return None
sid_returns = cum_returns[sid] - cum_returns[sid].iloc[0]
bench_returns = cum_returns[benchmark_sid] - cum_returns[benchmark_sid].iloc[0]
abnormal_returns = cum_returns['abnormal_returns'] - cum_returns['abnormal_returns'].iloc[0]
return sid_returns, bench_returns, abnormal_returns
非常感谢,
答案 0 :(得分:0)
是的,您的输出看起来像这样吗?
array = [pd.Series([1, 2, 3, 4, 5], index = [-3, -2, -1, 0, 1], name='first'),
pd.Series([11, 22, 33, 44, 55, 66], index = [-4, -3, -2, -1, 0, 1], name='second'),
pd.Series([111, 222, 333, 444, 555, 666, 777], index = [-4, -3, -2, -1, 0, 1, 2], name='last')]
退出:
[-3 1
-2 2
-1 3
0 4
1 5
Name: first, dtype: int64, -4 11
-3 22
-2 33
-1 44
0 55
1 66
Name: second, dtype: int64, -4 111
-3 222
-2 333
-1 444
0 555
1 666
2 777
Name: last, dtype: int64]
如果我是对的,则可以使用pd.concat串联系列。
df = pd.concat(array, axis=1)
退出:
first second last
-4 NaN 11.0 111
-3 1.0 22.0 222
-2 2.0 33.0 333
-1 3.0 44.0 444
0 4.0 55.0 555
1 5.0 66.0 666
2 NaN NaN 777
此后,如果需要,可以用df.fillna(value)
填充NaN值,其中value应该是一个数字。如果需要,可以得到一个矩阵:
pd.concat(array, axis=1).fillna(0).as_matrix()
退出:
array([[ 0., 11., 111.],
[ 1., 22., 222.],
[ 2., 33., 333.],
[ 3., 44., 444.],
[ 4., 55., 555.],
[ 5., 66., 666.],
[ 0., 0., 777.]])
希望对您有帮助。
UPD:
也许对您来说,任务最好有一个表(天,值,id)。
array = [pd.DataFrame(data=series.rename('value')).assign(ID = i) for i, series in enumerate(array)]
退出:
[ value ID
-3 1 0
-2 2 0
-1 3 0
0 4 0
1 5 0, value ID
-4 11 1
-3 22 1
-2 33 1
-1 44 1
0 55 1
1 66 1, value ID
-4 111 2
-3 222 2
-2 333 2
-1 444 2
0 555 2
1 666 2
2 777 2]
table = pd.concat(array, axis=0).reset_index().rename(columns={'index': 'day'})
退出:
day value ID
0 -3 1 0
1 -2 2 0
2 -1 3 0
3 0 4 0
4 1 5 0
5 -4 11 1
6 -3 22 1
7 -2 33 1
8 -1 44 1
9 0 55 1
10 1 66 1
11 -4 111 2
12 -3 222 2
13 -2 333 2
14 -1 444 2
15 0 555 2
16 1 666 2
17 2 777 2
之后,您可以按天或ID分组,然后做您想做的事。