python - 提高支出固定利率后找到投资组合最终值(value)的速度

标签 python pandas performance finance

我有一个 pd.DataFrame 返回系列,对应于固定支出率为 5% 的年份。我希望找到每年支出后的最终投资组合值(value)。 t 年的 val_after_spending 等于 tval_before_spendingt-1< 年的平均值 val_after_spending 乘以支出率。对于第一年,t-1 中的 val_after_spending 假定为 1。

我现在有一个有效的实现(如下),但速度非常慢。有没有更快的方法来实现这个?

import pandas as pd
import numpy as np   
port_rets = pd.DataFrame({'port_ret': [.10,-.25,.15]})

spending_rate = .05

for index, row in port_rets.iterrows():
    if index != 0:
        port_rets.at[index, 'val_before_spending'] = port_rets['val_after_spending'][index - 1] * (1 + port_rets['port_ret'][index])
        port_rets.at[index, 'spending'] = np.mean([port_rets['val_after_spending'][index - 1], port_rets['val_before_spending'][index]]) * spending_rate 
    else:
        port_rets.at[index, 'val_before_spending'] = 1 * (1 + port_rets['port_ret'][index])
        port_rets.at[index, 'spending'] = np.mean([1, port_rets['val_before_spending'][index]]) * spending_rate

    port_rets.at[index, 'val_after_spending'] = port_rets['val_before_spending'][index] - port_rets['spending'][index]

#   port_ret    val_before_spending spending    val_after_spending
#0  0.100000    1.100000            0.052500    1.047500
#1  -0.250000   0.785625            0.045828    0.739797
#2  0.150000    0.850766            0.039764    0.811002

最佳答案

您在代码中与 pandas 的交互非常频繁,就性能而言,这似乎是一个坏主意。为了使其尽可能易于使用,pandas 需要做大量的簿记工作,这会导致性能下降。

我们在 numpy 中完成所有计算,然后获得所有构建 block ,最后构建数据帧。因此,代码翻译为:

def get_vals(rates, spending_rate):
    n = len(rates)
    vals_after_spending = np.zeros((n+1, ))
    vals_before_spending = np.zeros((n+1, ))

    vals_after_spending[0] = 1.0

    for i in range(n):
        vals_before_spending[i+1] = vals_after_spending[i] * (1 + rates[i])

        spending = np.mean(np.array([vals_after_spending[i], vals_before_spending[i+1]])) * spending_rate
        vals_after_spending[i+1] = vals_before_spending[i+1] - spending

    return vals_before_spending[1:], vals_after_spending[1:]

rates = np.array(port_rets["port_ret"].tolist())
vals_before_spending, vals_after_spending = get_vals(rates, spending_rate)
port_rets = pd.DataFrame({'port_ret': rates, "val_before_spending": vals_before_spending, "val_after_spending": vals_after_spending})

我们可以通过 JIT 编译代码来进一步改进,因为 python 循环很慢。 下面我使用 numba :

import numba as nb
@nb.njit(cache=True)  # as easy as putting this decorator
def get_vals(rates, spending_rate):
    n = len(rates)
    vals_after_spending = np.zeros((n+1, ))
    vals_before_spending = np.zeros((n+1, ))

    # ... code remains same, we are just compiling the function

如果我们考虑这样的随机费率列表:

port_rets = pd.DataFrame({'port_ret': np.random.uniform(low=-1.0, high=1.0, size=(100000,))})

我们得到性能比较:

Your code : 15.758s

get_vals : 1.407s

JITed get_vals : 0.093s (on second run to discount for compile time)

关于python - 提高支出固定利率后找到投资组合最终值(value)的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53476857/

相关文章:

python - 从 1 个 Dataframe 更新一列,其中其他 Dataframe 具有相同的键

asp.net - 将 MS Ajax Minfier 4.0 用于 Asp.Net MVC 2.0?

c# - 从哈希表中获取随机键值

MySQL INSERT INTO 查询在 C 中太慢

python - django 1.8 中的相关模型问题

python - 绘制离散变量的 CDF - 使用交替线的步骤图

python - 我可以使用 k 均值聚类对各种空间模式进行分类吗?

Python:导入双管 csv Pandas

python - 我怎样才能用空格分割这个数据框?

python - Instagram Graph API 按区域指标查看 View