Skip to content

Commit b765948

Browse files
committed
ENH: Refactored IRR function to include default selection logic
Created function to store default selection logic to allow user to insert their own selection logic for more than 1 real solution
1 parent 6c40b8e commit b765948

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

numpy_financial/_financial.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,26 @@ def rate(
708708
rn[~close] = np.nan
709709
return rn
710710

711+
# default selection logic for IRR function when there are > 2 real solutions
712+
def irr_default_selection(eirr):
713+
# check sign of all IRR solutions
714+
same_sign = np.all(eirr > 0) if eirr[0] > 0 else np.all(eirr < 0)
715+
716+
# if the signs of IRR solutions are not the same, first filter potential IRR
717+
# by comparing the total positive and negative cash flows.
718+
if not same_sign:
719+
pos = sum(eirr[eirr > 0])
720+
neg = sum(eirr[eirr < 0])
721+
if pos >= neg:
722+
eirr = eirr[eirr >= 0]
723+
else:
724+
eirr = eirr[eirr < 0]
725+
726+
# pick the smallest one in magnitude and return
727+
abs_eirr = np.abs(eirr)
728+
return eirr[np.argmin(abs_eirr)]
711729

712-
def irr(values, *, raise_exceptions=False):
730+
def irr(values, *, raise_exceptions=False, selection_logic=irr_default_selection):
713731
r"""Return the Internal Rate of Return (IRR).
714732
715733
This is the "average" periodically compounded rate of return
@@ -824,23 +842,8 @@ def irr(values, *, raise_exceptions=False):
824842
if len(eirr) == 1:
825843
return eirr[0]
826844

827-
# below is for the situation when there are more than 2 real solutions.
828-
# check sign of all IRR solutions
829-
same_sign = np.all(eirr > 0) if eirr[0] > 0 else np.all(eirr < 0)
830-
831-
# if the signs of IRR solutions are not the same, first filter potential IRR
832-
# by comparing the total positive and negative cash flows.
833-
if not same_sign:
834-
pos = sum(values[values>0])
835-
neg = sum(values[values<0])
836-
if pos >= neg:
837-
eirr = eirr[eirr>=0]
838-
else:
839-
eirr = eirr[eirr<0]
840-
841-
# pick the smallest one in magnitude and return
842-
abs_eirr = np.abs(eirr)
843-
return eirr[np.argmin(abs_eirr)]
845+
eirr = selection_logic(eirr)
846+
return eirr
844847

845848

846849
def npv(rate, values):

0 commit comments

Comments
 (0)