Skip to content

BUG: npf.pmt() algorithm future value sign is flipped. #130

@RlndVt

Description

@RlndVt

Describe the issue:

When calculating the payment required to end with a remaining open balance, aka with a final_value, the calculated payments are larger than the payments required for a achieving final_value=0.

Workaround is inputting the final_value in a flipped state.

In the current state, if a positive pv means a outstanding loan, a negative fv means a remaining outstanding debt; whilst a positive fv implies having 'overpaid' the loan. This is confusing.

Either the algorithm is wrong, and the sign should be flipped; or the documentation should be updated to clarify that pv and fv signs have opposite meaning.

Reproduce the code example:

import numpy_financial as npf

interest_rate = 0.05 / 12
principal_loan = 200_000
compounding_periods = 360
payment_value_fv0 = npf.pmt(
    interest_rate,
    compounding_periods,
    principal_loan,
    0,
)
payment_value_fv50 = npf.pmt(
    interest_rate,
    compounding_periods,
    principal_loan,
    50_000,
)
payment_value_fvn50 = npf.pmt(
    interest_rate,
    compounding_periods,
    principal_loan,
    -50_000,
)
print("{:.2f}".format(payment_value_fv50))
print("{:.2f}".format(payment_value_fv0))
print("{:.2f}".format(payment_value_fvn50))

assert abs(payment_value_fv50) < abs(payment_value_fv0),\
       "Payment with remaining balance should be lower than fully paying off loan, but found {:.2f} > {:.2f}".format(abs(payment_value_fv50),abs(payment_value_fv0))

Error message:

-1133.72
-1073.64
-1013.57
Traceback (most recent call last):
  File "[...]/debugPmt.py", line 28, in <module>
    assert abs(payment_value_fv50) < abs(payment_value_fv0),\
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Payment with remaining balance should be lower than fully paying off loan, but found 1133.72 > 1073.64

Runtime information:

2.1.1
3.12.6 (main, Sep 9 2024, 00:00:00) [GCC 14.2.1 20240801 (Red Hat 14.2.1-1)]
[{'numpy_version': '2.1.1',
'python': '3.12.6 (main, Sep 9 2024, 00:00:00) [GCC 14.2.1 20240801 (Red '
'Hat 14.2.1-1)]',
'uname': uname_result(system='Linux', node='[...]', release='6.10.9-200.fc40.x86_64', version='#1 SMP PREEMPT_DYNAMIC Sun Sep 8 17:23:55 UTC 2024', machine='x86_64')},
{'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
'found': ['SSSE3',
'SSE41',
'POPCNT',
'SSE42',
'AVX',
'F16C',
'FMA3',
'AVX2'],
'not_found': ['AVX512F',
'AVX512CD',
'AVX512_KNL',
'AVX512_KNM',
'AVX512_SKX',
'AVX512_CLX',
'AVX512_CNL',
'AVX512_ICL']}},
{'architecture': 'Haswell',
'filepath': '/home/[...]/.local/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-ff651d7f.so',
'internal_api': 'openblas',
'num_threads': 8,
'prefix': 'libscipy_openblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.27'}]
None

Context for the issue:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions