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

josef.pktd at gmail.com josef.pktd at gmail.com
Wed Aug 26 01:45:53 EDT 2009


On Tue, Aug 25, 2009 at 11:38 PM, Charles R
Harris<charlesr.harris at 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)



More information about the NumPy-Discussion mailing list