Изучение событий - как упаковать результаты в управляемую форму? - PullRequest
0 голосов
/ 27 декабря 2018

Я провожу исследование событий и хотел бы упаковать результаты функции в легко управляемую форму.Приведенная ниже функция возвращает результаты в виде:

Результаты

Результаты приведены для одного индекса для анализа одного окна события (-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

Большое спасибо,

1 Ответ

0 голосов
/ 27 декабря 2018

Я прав, что ваш вывод выглядит так?

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')]

Out:

[-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)

Out:

    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

После этого вы можете заполнить значения NaN, если хотите, с помощью df.fillna(value), где значение должнобыть числом.Если хотите, вы можете получить матрицу:

pd.concat(array, axis=1).fillna(0).as_matrix()

Out:

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)]

Out:

[    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'})

Out:

    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

После этого вы можете группировать по дням или идентификаторам и делать то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...