This is my first attempt at Python. I started with some code from https://github.com/peliot/XIRR-and-XNPV and tried to 'improve' on it. But I would like to know if in these few lines I already made beginner's mistakes. I'm particularly interested to learn whether there is a more elegant way to handle the exceptions, because this looks a bit clunky.
Note that newton itself may also give rise to an immediate exception.
import datetime
from scipy import optimize
def xnpv(rate,cashflows):
t0 = min(cashflows, key = lambda t: t[0])[0]
return sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in cashflows])
def xirr(cashflows,guess=0.1):
try:
outc = optimize.newton(lambda r: xnpv(r,cashflows),guess,maxiter=100)
if outc.imag == 0:
return outc
else:
raise
except:
try:
outc = optimize.newton(lambda r: xnpv(r,cashflows),-guess,maxiter=100)
if outc.imag == 0:
return outc
else:
raise
except:
return float("NaN")
#cftest = [(datetime.date(2001, 12, 5),-2000),(datetime.date(2007, 12, 5),-10),(datetime.date(2017, 12, 5),20)]
cftest = [(datetime.date(2001, 12, 5),-2000),(datetime.date(2000, 12, 5),-1000),(datetime.date(2017, 12, 5),2000)]
#cftest = [(datetime.date(2001, 12, 5),-2000),(datetime.date(2007, 12, 5),-1000),(datetime.date(2017, 12, 5),20)]
print(cftest)
print(xirr(cftest))