Skip to content

Commit

Permalink
BUG: Changed ipmt to accept array_like arguments.
Browse files Browse the repository at this point in the history
The ipmt function was also fixed to handle broadcasting. The tests
were improved and extended to cover the broadcasting capability.
  • Loading branch information
timcera authored and charris committed May 20, 2012
1 parent b081857 commit ebffab2
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 11 deletions.
28 changes: 17 additions & 11 deletions numpy/lib/financial.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
'finish':0}

def _convert_when(when):
#Test to see if when has already been converted to ndarray
#This will happen if one function calls another, for example ppmt
if isinstance(when, np.ndarray):
return when
try:
return _when_to_num[when]
except KeyError:
except (KeyError, TypeError):
return [_when_to_num[x] for x in when]


Expand Down Expand Up @@ -236,8 +240,8 @@ def nper(rate, pmt, pv, fv=0, when='end'):
If you only had $150/month to pay towards the loan, how long would it take
to pay-off a loan of $8,000 at 7% annual interest?
>>> np.nper(0.07/12, -150, 8000)
64.073348770661852
>>> print round(np.nper(0.07/12, -150, 8000), 5)
64.07335
So, over 64 months would be required to pay off the loan.
Expand Down Expand Up @@ -354,17 +358,19 @@ def ipmt(rate, per, nper, pv, fv=0.0, when='end'):
12 -216.26 -1.49 -0.00
>>> interestpd = np.sum(ipmt)
>>> interestpd
-112.98308424136215
>>> np.round(interestpd, 2)
-112.98
"""
when = _convert_when(when)
if when == 1 and per == 1:
return 0.0
rate, per, nper, pv, fv, when = np.broadcast_arrays(rate, per, nper, pv, fv, when)
total_pmt = pmt(rate, nper, pv, fv, when)
ipmt = _rbl(rate, per, total_pmt, pv, when)*rate
if when == 1:
return ipmt/(1 + rate)
try:
ipmt = np.where(when == 1, ipmt/(1 + rate), ipmt)
ipmt = np.where(np.logical_and(when == 1, per == 1), 0.0, ipmt)
except IndexError:
pass
return ipmt

def _rbl(rate, per, pmt, pv, when):
Expand Down Expand Up @@ -620,8 +626,8 @@ def irr(values):
Examples
--------
>>> np.irr([-100, 39, 59, 55, 20])
0.2809484211599611
>>> print round(np.irr([-100, 39, 59, 55, 20]), 5)
0.28095
(Compare with the Example given for numpy.lib.financial.npv)
Expand Down
80 changes: 80 additions & 0 deletions numpy/lib/tests/test_financial.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,86 @@ def test_mirr(self):
val = [39000,30000,21000,37000,46000]
assert_(np.isnan(np.mirr(val, 0.10, 0.12)))

def test_when(self):
#begin
assert_almost_equal(np.rate(10,20,-3500,10000,1),
np.rate(10,20,-3500,10000,'begin'), 4)
#end
assert_almost_equal(np.rate(10,20,-3500,10000),
np.rate(10,20,-3500,10000,'end'), 4)
assert_almost_equal(np.rate(10,20,-3500,10000,0),
np.rate(10,20,-3500,10000,'end'), 4)

# begin
assert_almost_equal(np.pv(0.07,20,12000,0,1),
np.pv(0.07,20,12000,0,'begin'), 2)
# end
assert_almost_equal(np.pv(0.07,20,12000,0),
np.pv(0.07,20,12000,0,'end'), 2)
assert_almost_equal(np.pv(0.07,20,12000,0,0),
np.pv(0.07,20,12000,0,'end'), 2)

# begin
assert_almost_equal(np.fv(0.075, 20, -2000,0,1),
np.fv(0.075, 20, -2000,0,'begin'), 4)
# end
assert_almost_equal(np.fv(0.075, 20, -2000,0),
np.fv(0.075, 20, -2000,0,'end'), 4)
assert_almost_equal(np.fv(0.075, 20, -2000,0,0),
np.fv(0.075, 20, -2000,0,'end'), 4)

# begin
assert_almost_equal(np.pmt(0.08/12,5*12,15000.,0,1),
np.pmt(0.08/12,5*12,15000.,0,'begin'), 4)
# end
assert_almost_equal(np.pmt(0.08/12,5*12,15000.,0),
np.pmt(0.08/12,5*12,15000.,0,'end'), 4)
assert_almost_equal(np.pmt(0.08/12,5*12,15000.,0,0),
np.pmt(0.08/12,5*12,15000.,0,'end'), 4)

# begin
assert_almost_equal(np.ppmt(0.1/12,1,60,55000,0,1),
np.ppmt(0.1/12,1,60,55000,0,'begin'), 4)
# end
assert_almost_equal(np.ppmt(0.1/12,1,60,55000,0),
np.ppmt(0.1/12,1,60,55000,0,'end'), 4)
assert_almost_equal(np.ppmt(0.1/12,1,60,55000,0,0),
np.ppmt(0.1/12,1,60,55000,0,'end'), 4)

# begin
assert_almost_equal(np.ipmt(0.1/12,1,24,2000,0,1),
np.ipmt(0.1/12,1,24,2000,0,'begin'), 4)
# end
assert_almost_equal(np.ipmt(0.1/12,1,24,2000,0),
np.ipmt(0.1/12,1,24,2000,0,'end'), 4)
assert_almost_equal(np.ipmt(0.1/12,1,24,2000,0,0),
np.ipmt(0.1/12,1,24,2000,0,'end'), 4)

# begin
assert_almost_equal(np.nper(0.075,-2000,0,100000.,1),
np.nper(0.075,-2000,0,100000.,'begin'), 4)
# end
assert_almost_equal(np.nper(0.075,-2000,0,100000.),
np.nper(0.075,-2000,0,100000.,'end'), 4)
assert_almost_equal(np.nper(0.075,-2000,0,100000.,0),
np.nper(0.075,-2000,0,100000.,'end'), 4)

def test_broadcast(self):
assert_almost_equal(np.nper(0.075,-2000,0,100000.,[0,1]),
[ 21.5449442 , 20.76156441], 4)

assert_almost_equal(np.ipmt(0.1/12,range(5), 24, 2000),
[-17.29165168, -16.66666667, -16.03647345,
-15.40102862, -14.76028842], 4)

assert_almost_equal(np.ppmt(0.1/12,range(5), 24, 2000),
[-74.998201 , -75.62318601, -76.25337923,
-76.88882405, -77.52956425], 4)

assert_almost_equal(np.ppmt(0.1/12,range(5), 24, 2000, 0,
[0,0,1,'end','begin']),
[-74.998201 , -75.62318601, -75.62318601,
-76.88882405, -76.88882405], 4)

if __name__ == "__main__":
run_module_suite()

0 comments on commit ebffab2

Please sign in to comment.