8000 BUG: removed unnecesary warning from financial.pmt method by githubmlai · Pull Request #6073 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: removed unnecesary warning from financial.pmt method #6073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
8000 Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
BUG: removed unnecesary warning from financial.pmt method
Previous implementation would cause divide by zero and hence warning since
"fact" variable was calculated for all rates (both zero and non-zero) but then
zero rates would be masked with a where equality.

Changed implementation to apply non-zero rates using "np.divide( numerator,
denominator, where=mask_of_zero_values)"and then apply zero rates with "np.copyto".

Also updated documentation to show exact formulas that are being calculated.

Done with help of Sebastian Berg in Austin,TX!

7/13/15 Added in parenthesis for reability per Nathaniel Smith comment e.g.
    zero_rate_mask = (rate == 0)

Fixes issue #5046
  • Loading branch information
githubmlai committed Jul 13, 2015
commit 05587f9f071408084ca643d81e9bfa1d112303b8
30 changes: 20 additions & 10 deletions numpy/lib/financial.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def pmt(rate, nper, pv, fv=0, when='end'):
Number of compounding periods
pv : array_like
Present value
fv : array_like, optional
fv : array_like (optional)
Future value (default = 0)
when : {{'begin', 1}, {'end', 0}}, {string, int}
When payments are due ('begin' (1) or 'end' (0))
Expand All @@ -163,17 +163,24 @@ def pmt(rate, nper, pv, fv=0, when='end'):

Notes
-----
The payment is computed by solving the equation::
When `rate != 0``: the payment is computed by solving the equation::

fv +
pv*(1 + rate)**nper +
pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1) == 0

or, when ``rate == 0``::
Solving for pmt yields::

pmt = -(fv + pv*(1 + rate)**nper) * rate / ( (1 + rate*when) * ((1 + rate)**nper -1) )

When ``rate == 0``:the payment is computed by instead solving the equation::

fv + pv + pmt * nper == 0

for ``pmt``.
Solving for pmt yields::

pmt = -(fv + pv) / nper


Note that computing a monthly mortgage payment is only
one use for this function. For example, pmt returns the
Expand Down Expand Up @@ -208,12 +215,15 @@ def pmt(rate, nper, pv, fv=0, when='end'):
"""
when = _convert_when(when)
(rate, nper, pv, fv, when) = map(np.asarray, [rate, nper, pv, fv, when])
temp = (1 + rate)**nper
mask = (rate == 0.0)
np.copyto(rate, 1.0, where=mask)
z = np.zeros(np.broadcast(rate, nper, pv, fv, when).shape)
fact = np.where(mask != z, nper + z, (1 + rate*when)*(temp - 1)/rate + z)
return -(fv + pv*temp) / fact

# use different payment if rate == 0
zero_rate_mask = (rate == 0)
compounded_rate = (1 + rate)**nper
payment = np.asarray(np.divide(-(fv + pv*compounded_rate)*rate,
(1 + rate*when)*(compounded_rate - 1),
where=~zero_rate_mask))
np.copyto(payment, -(fv + pv)/nper, where=zero_rate_mask)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sorry, got interrupted half-way through reviewing :-))
I'd put spaces around most or all of these binary operators (e.g. (1 + rate * when) * (compounded_rate - 1)), though in this case it's more a matter of personal taste than rigid policy. (In general spaces around operators is PEP8's recommendation, but there's an escape clause for higher-priority operators that could apply here if one wanted.)

return payment

def nper(rate, pmt, pv, fv=0, when='end'):
"""
Expand Down
0