1

我在 python 中计算函数时遇到问题。我想计算一些投资的 IRR,所有这些投资都在他们自己的数据框中进行了描述。在某个日期之前,我为每项投资都有一个数据框,因此我有一个多个数据框,用于描述在每项投资的不同日期之前投资已完成的付款流,每个数据框的最后一行包含股票的信息到那时为止,每项投资所拥有的资本。我这样做是为了获得每项投资的 IRR 时间序列。我要计算 IRR 的每个数据框都在一个列表中。

为了计算每个数据帧的 IRR,我做了这些函数:

def npv(irr, cfs, yrs):
    return np.sum(cfs / ((1. +  irr) ** yrs))
def irr(cfs, yrs, x0)
    return np.asscalar(fsolve(npv, x0=x0, args=(cfs, yrs)))

因此,为了计算列表中每个数据帧的 IRR,我做了:

 for i, new_df in enumerate(dfs):
   cash_flow = new_df.FLOWS.values
   years = new_df.timediff.values
   output.loc[i, ['DATE']] = new_df['DATE'].iloc[-1]
   output.loc[i, ['Investment']] = new_df['Investment'].iloc[-1]
   output.loc[i, ['irr']] = irr(cash_flow, years, x0=0.)

输出是我想要创建的数据框,其中包含我想要的信息,即直到某个日期之前每笔投资的 IRR。问题是,它可以正确计算某些数据帧的 IRR,但不能正确计算其他数据帧。例如,它为此数据帧正确计算 IRR:

       DATE     INVESTMENT       FLOWS        timediff
0   2014-02-24      1        -36278400.0         0.0
1   2014-03-25      1        -11490744.0    0.07945205479452055
2   2015-01-22      1        -13244300.0    0.9095890410958904
3   2015-09-24      1        -10811412.0    1.5808219178082192
4   2015-11-12      1         -6208238.0    1.715068493150685
5   2016-01-22      1         -6210161.0    1.9095890410958904
6   2016-03-31      1         -4535569.0    2.0986301369863014
7   2016-05-25      1          8420470.0    2.249315068493151
8   2016-06-30      1         12357138.0    2.347945205479452
9   2016-07-14      1          3498535.0    2.3863013698630136
10  2016-12-26      1          4085285.0    2.8383561643835615
11  2017-06-07      1          3056835.0    3.2849315068493152
12  2017-09-11      1         11254424.0    3.547945205479452
13  2017-11-16      1          9274834.0    3.728767123287671
14  2018-02-22      1          1622857.0    3.9972602739726026
15  2018-05-23      1          2642985.0    4.243835616438356
18  2018-08-23      1          9265099.0    4.495890410958904
16  2018-11-29      1          1011915.0    4.764383561643836
19  2018-12-28      1          1760734.0    4.843835616438356
17  2019-01-14      1          1940112.0    4.890410958904109
20  2019-06-30      1         116957227.3   5.347945205479452

内部收益率为 0.215。但是这个数据框,对于完全相同的投资,它没有。它返回 0.0001 的 IRR,但实际的 IRR 应该在 0.216 左右。

       DATE     INVESTMENT       FLOWS         timediff
0   2014-02-24      1        -36278400.0         0.0
1   2014-03-25      1        -11490744.0    0.07945205479452055
2   2015-01-22      1        -13244300.0    0.9095890410958904
3   2015-09-24      1        -10811412.0    1.5808219178082192
4   2015-11-12      1         -6208238.0    1.715068493150685
5   2016-01-22      1         -6210161.0    1.9095890410958904
6   2016-03-31      1         -4535569.0    2.0986301369863014
7   2016-05-25      1          8420470.0    2.249315068493151
8   2016-06-30      1         12357138.0    2.347945205479452
9   2016-07-14      1          3498535.0    2.3863013698630136
10  2016-12-26      1          4085285.0    2.8383561643835615
11  2017-06-07      1          3056835.0    3.2849315068493152
12  2017-09-11      1         11254424.0    3.547945205479452
13  2017-11-16      1          9274834.0    3.728767123287671
14  2018-02-22      1          1622857.0    3.9972602739726026
15  2018-05-23      1          2642985.0    4.243835616438356
18  2018-08-23      1          9265099.0    4.495890410958904
16  2018-11-29      1          1011915.0    4.764383561643836
19  2018-12-28      1          1760734.0    4.843835616438356
17  2019-01-14      1          1940112.0    4.890410958904109
20  2019-09-30      1        123753575.7    5.6

除了最后一行之外,这两个数据框具有完全相同的流量,其中包含了该投资截至该日期的资本存量。所以这两个数据帧之间的唯一区别是最后一行。这意味着该投资在此期间没有任何流入或流出。我不明白为什么内部收益率变化如此之大。或者为什么某些 IRR 计算不正确。

大多数计算正确,但少数计算不正确。

谢谢你帮助我。

4

1 回答 1

0

正如我所想,这是优化方法的问题。当我用第二个 df 尝试了你的 irr 函数时,我什至收到了一个警告:

RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
  warnings.warn(msg, RuntimeWarning)

但是用其他方法尝试scipy.optimize.root似乎对我有用。将函数更改为:

import scipy.optimize as optimize

def irr(cfs, yrs, x0):
    r = optimize.root(npv, args=(cfs, yrs), x0=x0, method='broyden1')
    return float(r.x)

我刚刚检查了 lm 和 broyden1,它们都与您的第二个示例收敛到 0.216 左右。有多种方法,我不知道哪种方法是最好的选择,但大多数似乎比 fsolve 中使用的 hybr 方法更好。

于 2021-04-26T18:44:20.843 回答