2017-01-08 3 views
3

В контексте финансов, предположим, что существует dataframe весов активов и панель ежедневной ковариационной матрицы:Панды: применить функцию парно к dataframe и панели

w = pd.DataFrame({'Date':pd.to_datetime(['2016-01-01','2016-01-02','2016-01-03']),'A1':[0.3,0.1,0.1],'A2':[0.4,0.4,0.4]}).set_index(['Date']) 
covar = [[[0.000087,0.000017],[0.000087,0.000017],[0.000087,0.000017]],[[0.000017,0.00019],[0.000017,0.00019],[0.000017,0.00019]]] 
covPanel = pd.Panel(covar, items=['A1', 'A2'], major_axis=pd.to_datetime(['2016-01-01','2016-01-02','2016-01-03']), minor_axis=['A1', 'A2']) 

Для расчета 1-дневный портфель дисперсия, ниже функция может быть использована:

def portVar(w,sigma): 
    return w.dot(sigma.dot(w)) 

я могу применить последний ряд весов ковариационной матрицы каждый день, чтобы получить суточную дисперсию:

out = covPanel.apply(lambda cov1: portVar(w.iloc[-1,:],cov1),axis = [2,0]) 

Но как применить приведенную выше функцию к матрице данных и ковариационной матрицы попарно, для каждого дня (без цикла)?

Другими словами, что-то вроде:

pd.ApplyPairwise(portVar,w,covPanel) 

и вернуть ежедневную дисперсию так же, как «из» выше?

ответ

2

вариант 1
переписывают portVar

проход вся панель функции применяются и использовать xs, чтобы получить соответствующее сечение веса этого конкретного Дейта. Дата указана в атрибуте name.


def portVar(w, sigma): 
    s = sigma.xs(w.name, axis='major') 
    return w.dot(s.dot(w)) 

w.apply(portVar, 1, sigma=covPanel) 

Date 
2016-01-01 0.000042 
2016-01-02 0.000033 
2016-01-03 0.000033 
dtype: float64 

вариант 2
numpy вещания

cv = covPanel.values 
wv = w.values 

pd.Series(((wv[None, :] * cv).sum(-1).T * wv).sum(1), w.index) 

Date 
2016-01-01 0.000042 
2016-01-02 0.000033 
2016-01-03 0.000033 
dtype: float64 

ответ на комментарий

Общий способ python делать вещи пара мудрый zip
Я воспользуюсь списком, чтобы создать список, который мы ищем. Обратите внимание на транспонирование на объекте панели, чтобы гарантировать, что даты являются первым измерением.

def portVar(w,sigma): 
    return w.dot(sigma.dot(w)) 

[portVar(w_, s_) for w_, s_ in zip(w.values, covPanel.transpose(1, 0, 2).values)] 
+0

спасибо. В этом случае я предпочел бы вариант 1. Вы также знаете что-то более общее в python для применения функции по парному адресу в двух «списках» элементов? – iwbabn

+0

@iwbabn Я обновил свой пост. Надеюсь, это полезно. – piRSquared

+0

Спасибо вам большое! – iwbabn

Смежные вопросы