summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
authorPhilip Eliot <git.peliot@gmail.com>2014-02-01 07:48:46 -0500
committerCharles Harris <charlesr.harris@gmail.com>2014-02-01 22:09:05 -0700
commit0b92be65cc0063cabab6b9552df74788c4077e5b (patch)
tree794598449359f826d8d1eadbc4128f1218149339 /numpy/lib
parentad5bded8658c41161106a1ed51e3889bc1cf6b6b (diff)
downloadnumpy-0b92be65cc0063cabab6b9552df74788c4077e5b.tar.gz
BUG: IRR was returning nan instead of valid negative answer.
This change corrects the following two bugs in numpy.irr: * When the solution was negative, numpy.irr returned nan instead of the correct solution because of the mask applied to the roots. Corrected by removing the mask that 0 < res < 1. * When multiple roots were found, numpy.irr was returning an array of all roots rather than a single float. This bug was corrected by selecting the single root closest to zero (min(abs(root)). With these corrections, numpy.irr returns the same result as the corresponding spreadsheet function in LibreOffice Calc for all test cases (additional test cases were added to cover cases with multiple positive and negative roots)
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/financial.py20
-rw-r--r--numpy/lib/tests/test_financial.py15
2 files changed, 29 insertions, 6 deletions
diff --git a/numpy/lib/financial.py b/numpy/lib/financial.py
index ec642afd3..c085a5d53 100644
--- a/numpy/lib/financial.py
+++ b/numpy/lib/financial.py
@@ -628,21 +628,29 @@ def irr(values):
Examples
--------
- >>> print round(np.irr([-100, 39, 59, 55, 20]), 5)
+ >>> round(irr([-100, 39, 59, 55, 20]), 5)
0.28095
+ >>> round(irr([-100, 0, 0, 74]), 5)
+ -0.0955
+ >>> round(irr([-100, 100, 0, -7]), 5)
+ -0.0833
+ >>> round(irr([-100, 100, 0, 7]), 5)
+ 0.06206
+ >>> round(irr([-5, 10.5, 1, -8, 1]), 5)
+ 0.0886
(Compare with the Example given for numpy.lib.financial.npv)
"""
res = np.roots(values[::-1])
- # Find the root(s) between 0 and 1
- mask = (res.imag == 0) & (res.real > 0) & (res.real <= 1)
- res = res[mask].real
+ mask = (res.imag == 0) & (res.real > 0)
if res.size == 0:
return np.nan
+ res = res[mask].real
+ # NPV(rate) = 0 can have more than one solution so we return
+ # only the solution closest to zero.
rate = 1.0/res - 1
- if rate.size == 1:
- rate = rate.item()
+ rate = rate.item(np.argmin(np.abs(rate)))
return rate
def npv(rate, values):
diff --git a/numpy/lib/tests/test_financial.py b/numpy/lib/tests/test_financial.py
index 6b7c6ef53..41a060a3f 100644
--- a/numpy/lib/tests/test_financial.py
+++ b/numpy/lib/tests/test_financial.py
@@ -13,6 +13,21 @@ class TestFinancial(TestCase):
v = [-150000, 15000, 25000, 35000, 45000, 60000]
assert_almost_equal(np.irr(v),
0.0524, 2)
+ v = [-100, 0, 0, 74]
+ assert_almost_equal(np.irr(v),
+ -0.0955, 2)
+ v = [-100, 39, 59, 55, 20]
+ assert_almost_equal(np.irr(v),
+ 0.28095, 2)
+ v = [-100, 100, 0, -7]
+ assert_almost_equal(np.irr(v),
+ -0.0833, 2)
+ v = [-100, 100, 0, 7]
+ assert_almost_equal(np.irr(v),
+ 0.06206, 2)
+ v = [-5, 10.5, 1, -8, 1]
+ assert_almost_equal(np.irr(v),
+ 0.0886, 2)
def test_pv(self):
assert_almost_equal(np.pv(0.07, 20, 12000, 0),