# [Numpy-discussion] mirr test correctly fails for given input.

josef.pktd@gmai... josef.pktd@gmai...
Wed Aug 26 00:45:53 CDT 2009

```On Tue, Aug 25, 2009 at 11:38 PM, Charles R
Harris<charlesr.harris@gmail.com> wrote:
> So is it a bug in the test or a bug in the implementation? The problem is
> that the slice values[1:] when
> values =  [-120000,39000,30000,21000,37000,46000] contains no negative
> number and a nan is returned. This looks like a bug in the test. The
> documentation also probably needs fixing.
>
> Chuck

There is a bug in the code, the nan is incorrectly raised. After
correcting the nan (checking on the original, instead of shortened
values), I got one failing test, that I corrected with the matching
number from Openoffice.

(The main problem that the function is more complicated than
necessary, is because np.npv doesn't allow the inclusion of the
investment in the initial period)

This needs reviewing, since it's late here.

Josef

import numpy as np
from numpy.testing import assert_almost_equal, assert_

from numpy import npv

def mirr(values, finance_rate, reinvest_rate):
"""
Modified internal rate of return.

Parameters
----------
values : array_like
Cash flows (must contain at least one positive and one negative value)
or nan is returned.
finance_rate : scalar
Interest rate paid on the cash flows
reinvest_rate : scalar
Interest rate received on the cash flows upon reinvestment

Returns
-------
out : float
Modified internal rate of return

"""

values = np.asarray(values, dtype=np.double)
initial = values[0]
values1 = values[1:]
n = values1.size
pos = values1 > 0
neg = values1 < 0
if not (np.sum(values[values>0]) > 0 and np.sum(values[values<0]) < 0):
return np.nan
numer = np.abs(npv(reinvest_rate, values1*pos))
denom = np.abs(npv(finance_rate, values1*neg))
if initial > 0:
return ((initial + numer) / denom)**(1.0/n)*(1 + reinvest_rate) - 1
else:
return ((numer / (-initial + denom)))**(1.0/n)*(1 + reinvest_rate) - 1

#tests from testsuite and Skipper plus isnan test

v1 = [-4500,-800,800,800,600,600,800,800,700,3000]
print mirr(v1,0.08,0.055)
assert_almost_equal(mirr(v1,0.08,0.055),
0.0666, 4)

#incorrect test ? corrected
v2 = [-120000,39000,30000,21000,37000,46000]
print mirr(v2,0.10,0.12)
assert_almost_equal(mirr(v2,0.10,0.12), 0.126094, 6)  # corrected from OO

v2 = [39000,30000,21000,37000,46000]
assert_(np.isnan(mirr(v2,0.10,0.12)))

v3 = [100,200,-50,300,-200]
print mirr(v3,0.05,0.06)
assert_almost_equal(mirr(v3,0.05,0.06), 0.3428, 4)

#--------------
print mirr([100, 200, -50, 300, -200], .05, .06)
assert_almost_equal(mirr((100, 200,-50, 300,-200), .05, .06),
0.342823387842, 4)

V2 = [-4500,-800,800,800,600,600,800,800,700,3000]
print mirr(V2, 0.08, 0.055)
assert_almost_equal(mirr(V2, 0.08, 0.055), 0.06659718, 4)
```