@@ -708,8 +708,26 @@ def rate(
708
708
rn [~ close ] = np .nan
709
709
return rn
710
710
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 )]
711
729
712
- def irr (values , * , raise_exceptions = False ):
730
+ def irr (values , * , raise_exceptions = False , selection_logic = irr_default_selection ):
713
731
r"""Return the Internal Rate of Return (IRR).
714
732
715
733
This is the "average" periodically compounded rate of return
@@ -824,23 +842,8 @@ def irr(values, *, raise_exceptions=False):
824
842
if len (eirr ) == 1 :
825
843
return eirr [0 ]
826
844
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
844
847
845
848
846
849
def npv (rate , values ):
0 commit comments