问题描述
我正在使用以下函数通过Python执行IRR计算:
from scipy.optimize import newton
def xnpv(rate,values,dates):
if rate <= -1.0:
return float('inf')
min_date = min(dates)
return sum([
value / (1 + rate)**((date - min_date).days / 365)
for value,date
in zip(values,dates)
])
def xirr(values,dates):
return newton(lambda r: xnpv(r,dates),0)
函数来源:https://2018.pycon.co/talks/personal-pynance/personal-pynance.pdf
几个月来,此功能与各种不同的现金流量和日期完美配合,而我得到的效果与Excel的XIRR功能相同。但是,突然有了下面的现金流量和日期列表,它就停止了工作,并且我得到的结果与Excel的IRR公式(这是正确的和预期的)不同:
import pandas as pd
import datetime
import numpy as np
from decimal import *
# Input Data
dates = [datetime.date(2020,8,31),datetime.date(2020,5,5),2,28),datetime.date(2018,6,30)]
values = [50289.0,-75000.0,0.0,0.0]
# Create Dataframe from Input Data
test = pd.DataFrame({"dates" : dates,"values" : values})
# Filter all rows with 0 cashflows
test = test[test['values'] != 0]
# Sort dataframe by date
test = test.sort_values('dates',ascending=True)
test['values'] = test['values'].astype('float')
# Create separate lists for values and dates
test_values = list(test['values'])
test_dates = list(test['dates'])
# Calculate IRR
xirr(test_values,test_dates)
我在Python中得到的结果是 0.0001 ,而在Excel中我得到的结果是 -0.71 ,我不知道这里缺少什么。也许有人有主意?!?!!
解决方法
科学优化功能对局部极小值是错误的。将优化方法更改为其他内容,例如anderson
,并达到您的期望。
证明
from scipy.optimize import anderson
def xnpv(rate,values,dates):
if rate <= -1.0:
return float('inf')
min_date = min(dates)
return sum([
value / (1 + rate)**((date - min_date).days / 365)
for value,date
in zip(values,dates)
])
def xirr(values,dates):
return anderson(lambda r: xnpv(r,dates),0)
import datetime
from decimal import *
# Input Data
dates = [datetime.date(2020,8,31),datetime.date(2020,5,5),2,28),datetime.date(2018,6,30)]
values = [50289.0,-75000.0,0.0,0.0]
# Create Dataframe from Input Data
test = pd.DataFrame({"dates" : dates,"values" : values})
# Filter all rows with 0 cashflows
test = test[test['values'] != 0]
# Sort dataframe by date
test = test.sort_values('dates',ascending=True)
test['values'] = test['values'].astype('float')
# Create separate lists for values and dates
test_values = list(test['values'])
test_dates = list(test['dates'])
# Calculate IRR
xirr(test_values,test_dates)
array(-0.70956212)