Python中的内部收益率计算

Python中的内部收益率计算,python,optimization,scipy,finance,irr,Python,Optimization,Scipy,Finance,Irr,我写了一些代码来计算内部收益率,效果很好 import scipy.optimize as optimize import datetime def npv(cf, rate=0.1): if len(cf) >= 2: first_date = min([x[0] for x in cf]) dcf = [x[1] * (1 / ((1 + rate) ** ((x[0] - first_date)

我写了一些代码来计算内部收益率,效果很好

import scipy.optimize as optimize
import datetime


def npv(cf, rate=0.1):
    if len(cf) >= 2:
        first_date = min([x[0] for x in cf])
        dcf = [x[1] * (1 /
                       ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
        return sum(dcf)
    elif len(cf) == 1:
        return cf[0][1]
    else:
        return 0


def irr(cf):
    f = lambda x: npv(cf, rate=x)
    r = optimize.newton(f, 0, maxiter=70)
    return r
…但当我尝试这种现金流时

cf=[(datetime.datetime(2018, 1, 10), -51089.94),
    (datetime.datetime(2022, 10, 6), 4941.0)]
我得到这个错误:

File "/Users/maxim/Dropbox/Python/FinProject/fintrack/main/models.py", line 503, in getIRR
    return irr(cf)
  File "/Users/maxim/Dropbox/Python/FinProject/fintrack/main/models.py", line 37, in irr
    r = optimize.newton(f, 0, maxiter=70)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/optimize/zeros.py", line 204, in newton
    q1 = func(p1, *args)
  File "/Users/maxim/Dropbox/Python/FinProject/fintrack/main/models.py", line 36, in <lambda>
    f = lambda x: npv(cf, rate=x)
  File "/Users/maxim/Dropbox/Python/FinProject/fintrack/main/models.py", line 27, in npv
    ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
  File "/Users/maxim/Dropbox/Python/FinProject/fintrack/main/models.py", line 27, in <listcomp>
    ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
OverflowError: complex exponentiation
[30/Nov/2018 21:28:36] "GET /inv/19/ HTTP/1.1" 500 299065

似乎
newton
无法正确处理此问题(不确定原因)。但是,您可以使用以下命令,该命令提供了预期的结果,并且只需要对代码进行非常小的修改:

import scipy.optimize as optimize
import datetime


def npv(cf, rate=0.1):
    if len(cf) >= 2:
        first_date = min([x[0] for x in cf])
        dcf = [x[1] * (1 /
                       ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
        return sum(dcf)
    elif len(cf) == 1:
        return cf[0][1]
    else:
        return 0


def irr(cf):
    f = lambda x: npv(cf, rate=x)
    r = optimize.root(f, [0])
    return r

cf = [(datetime.datetime(2018, 1, 10), -51089.94),
      (datetime.datetime(2022, 10, 6), 4941.0)]

print(irr(cf))
这将打印:

    fjac: array([[-1.]])
     fun: array([-2.91038305e-11])
 message: 'The solution converged.'
    nfev: 18
     qtf: array([2.37701897e-06])
       r: array([396401.23327105])
  status: 1
 success: True
       x: array([-0.38912302])
如您所见,
x
包含预期的
-0.38912

工作代码是:

import scipy.optimize as optimize
import datetime


def npv(cf, rate=0.1):
    if len(cf) >= 2:
        first_date = min([x[0] for x in cf])
        dcf = [x[1] * (1 /
                       ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
        return sum(dcf)
    elif len(cf) == 1:
        return cf[0][1]
    else:
        return 0


def irr(cf):
    f = lambda x: npv(cf, rate=x)
    r = optimize.root(f, [0])
    return r

非常感谢克莱布

可能是错误的,但从这些错误信息判断,这在技术上不是你的错。牛顿使用的函数根本无法处理传递的指数。希望有人能推荐一个更好的IRR导入。牛顿无法处理这个问题,因为当使用IRR<-100%(这在数学上是可行的)时,
(1+速率)**时间变得复杂,这就是你得到的错误。事实上,在速率=-1时,你有一个不连续性。您可以使用不同的优化方法,该方法允许约束
速率>-100%
(或
速率>=0
),或在已知间隔内使用有界方法(例如
brentq
割线
),或使用
newton
,从您知道低于IRR值的x0开始(例如
x0=-0.95
)@麦克斯:很高兴听到这个消息!请不要忘记将答案标记为已接受(您可以单击答案旁边的小复选框,该复选框将变为绿色)。:)添加重复答案没有多大意义。通常的做法是,如果你有足够的声誉,就投票选出有帮助的答案,并接受真正解决问题的答案(点击答案旁边的小复选框,然后变成绿色)。
import scipy.optimize as optimize
import datetime


def npv(cf, rate=0.1):
    if len(cf) >= 2:
        first_date = min([x[0] for x in cf])
        dcf = [x[1] * (1 /
                       ((1 + rate) ** ((x[0] - first_date).days / 365))) for x in cf]
        return sum(dcf)
    elif len(cf) == 1:
        return cf[0][1]
    else:
        return 0


def irr(cf):
    f = lambda x: npv(cf, rate=x)
    r = optimize.root(f, [0])
    return r