【问题标题】:Pandas dot product with Multiindex带有 Multiindex 的 Pandas 点积
【发布时间】:2018-07-31 20:44:46
【问题描述】:

我的问题在金融领域很常见。

给定权重数组 w (1xN) 和资产协方差矩阵 Q (NxN),可以使用二次表达式 w' * Q * w 计算投资组合的协方差,其中 * 是点积。

当我有权重 W (T x N) 的历史和协方差矩阵 (T, N, N) 的 3D 结构时,我想了解执行此操作的最佳方法。

import numpy as np
import pandas as pd

returns = pd.DataFrame(0.1 * np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])
covariance = returns.rolling(20).cov()

weights = pd.DataFrame(np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])

到目前为止,我的解决方案是将 pandas DataFrames 转换为 numpy,执行循环计算,然后再转换回 pandas。 请注意,我需要明确检查标签的对齐方式,因为实际上协方差和权重可以通过不同的过程计算。

cov_dict = {key: covariance.xs(key, axis=0, level=0) for key in covariance.index.get_level_values(0)}

def naive_numpy(weights, cov_dict):

    expected_risk = {}

    # Extract columns, index before passing to numpy arrays
    # Columns
    cov_assets = cov_dict[next(iter(cov_dict))].columns
    avail_assets = [el for el in cov_assets if el in weights]

    # Indexes
    cov_dates = list(cov_dict.keys())
    avail_dates = weights.index.intersection(cov_dates)

    sel_weights = weights.loc[avail_dates, avail_assets]

    # Main loop and calculation
    for t, value in zip(sel_weights.index, sel_weights.values):
        expected_risk[t] = np.sqrt(np.dot(value, np.dot(cov_dict[t].values, value)))

    # Back to pandas DataFrame
    expected_risk = pd.Series(expected_risk).reindex(weights.index).sort_index()

    return expected_risk

有没有纯熊猫的方式来达到同样的结果?还是对代码有任何改进以使其更高效? (尽管使用了 numpy,它仍然很慢)。

【问题讨论】:

  • 我建议您继续使用numpy 以提高速度。
  • 我同意 numpy 通常是最快的,但我想知道一些智能阵列广播是否会使解决方案更有效率。

标签: python pandas numpy financial


【解决方案1】:

我认为 numpy 绝对是最好的选择。虽然如果你循环价值/日期,你会失去效率。

我对计算投资组合滚动波动率的建议(无循环):

returns = pd.DataFrame(0.1 * np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])
covariance = returns.rolling(20).cov()
weights = pd.DataFrame(np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])

rows, columns = weights.shape

# Go to numpy:
w = weights.values
cov = covariance.values.reshape(rows, columns, columns)

A = np.matmul(w.reshape(rows, 1, columns), cov)
var = np.matmul(A, w.reshape(rows, columns, 1)).reshape(rows)
std_dev = np.sqrt(var)

# Back to pandas (in case you want that):
pd.Series(std_dev, index = weights.index)

【讨论】:

    猜你喜欢
    • 2019-05-20
    • 1970-01-01
    • 2021-04-18
    • 2018-06-03
    • 2021-02-06
    • 1970-01-01
    • 2017-10-12
    • 2016-02-04
    • 2014-05-28
    相关资源
    最近更新 更多