问题描述
我在 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 计算错误。
大多数计算正确,但少数不正确。
谢谢你帮助我。
解决方法
如我所想,是优化方法的问题。 当我用第二个 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 方法更好。