Skip to content
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

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

Open
RlndVt opened this issue Sep 22, 2024 · 5 comments
Open

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

RlndVt opened this issue Sep 22, 2024 · 5 comments

Comments

@RlndVt
Copy link

RlndVt commented Sep 22, 2024

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

@RlndVt
Copy link
Author

RlndVt commented Sep 22, 2024

FWIW libreoffice calc and MS Excel show the same behaviour. To stay in line with those implementations, updating the documentation may be the better solution.

I still find it a confusing configuration and would argue that having the PV and FV signs represent the same is more correct, but I can understand the argument that keeping the implementation inline with other is desirable.


Examining Calc's and Excel's documentation; Calc:

PV is [...] the present value of the amount borrowed or invested.

FV is [...] the future value of the cash balance desired at the end of the term.

Excel:

Pv The present value, or the total amount that a series of future payments is worth now; also known as the principal.

Fv The future value, or a cash balance you want to attain after the last payment is made.

A distinction is made between the two types of 'value'. PV describing the borrowed/invested amount, and FV the final cash balance. Again, I would argue confusing; but nonetheless correct distinction.

@parikhvedant2003
Copy link

Hey @RlndVt 😊,

I noticed your issue, and it's definitely an interesting one! I’d love to help clarify how the monthly payment value is calculated based on the code you shared.

To give you the best guidance, I need to know if the code you’re using is the standard implementation at your organization or if you’ve made any tweaks to it for your own purposes. As far as I can see, you’ve just used the pmt function of the numpy_financial library in your code. So let me know about the given code so I can assist you well and sort this out! 🚀

@RlndVt
Copy link
Author

RlndVt commented Oct 29, 2024

Hi @parikhvedant2003

No guidance required thank you; I was confused by the different definitions of value. By implementing the definitions as described in Calc and Excel my code works as expected.

The code provided was just a minimal working example for my (originally) expected behaviour.

As I suggested in my previous post, I think updating the documentation is the solution.

@shivkatira
Copy link

@RlndVt
Hey, how can we export Runtime information information as you stated in your issue description?

@RlndVt
Copy link
Author

RlndVt commented Nov 3, 2024

@RlndVt
Hey, how can we export Runtime information information as you stated in your issue description?

From the create new bug report/issue interface:

Runtime information:

Output from import sys, numpy; print(numpy.__version__); print(sys.version) If you are running NumPy 1.24+, also show print(numpy.show_runtime())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants