[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