Skip to content

Instantly share code, notes, and snippets.

@haran090
Last active July 14, 2024 11:21
Show Gist options
  • Select an option

  • Save haran090/dd0434bc505b96b5cdc0096b467bcc44 to your computer and use it in GitHub Desktop.

Select an option

Save haran090/dd0434bc505b96b5cdc0096b467bcc44 to your computer and use it in GitHub Desktop.
Internal Rate of Return Method (IRR)
import java.math.BigDecimal;
public class IRR {
//Approximate number of days between 2 successive cash flows. Eg. For monthly cash flows interval will be 30
private static final int INTERVAL = 30;
public static BigDecimal getAnnualIrr(double[] cash_flows) {
return calculateIrrRecursively(BigDecimal.valueOf(1.0), BigDecimal.valueOf(100.0), BigDecimal.valueOf(1.0), cash_flows);
}
public static BigDecimal calculateIrrRecursively(BigDecimal start, BigDecimal end, BigDecimal precision, double[] cash_flows) {
BigDecimal test_rate = start;
BigDecimal sum;
Double previous_diff = null;
double final_cash_flow = cash_flows[cash_flows.length - 1];
while (test_rate.compareTo(end) != 1) {
sum = new BigDecimal(0);
for (int i = 0; i < cash_flows.length - 1; i++) {
double current_cash_flow = cash_flows[i];
int days_in_between = getDaysInbetween(i, cash_flows.length);
BigDecimal calc_value = (BigDecimal.valueOf(1).add(test_rate.divide(BigDecimal.valueOf(100))));
sum = sum.add(BigDecimal.valueOf(current_cash_flow * Math.pow(calc_value.doubleValue(), (days_in_between / 365.0))));
}
double difference = (Math.abs(final_cash_flow) - Math.abs(sum.doubleValue()));
if (previous_diff == null) {
previous_diff = difference;
}
if (difference < 1 && difference > -1) {
return returnCorrectTestRate(precision, test_rate, previous_diff, difference);
} else if ((previous_diff < 0 && difference > 0) || (previous_diff > 0 && difference < 0)) {
if ((precision.divide(BigDecimal.valueOf(10))).compareTo(BigDecimal.valueOf(0.001)) == -1) {// precision/10 < 0.001
return returnCorrectTestRate(precision, test_rate, previous_diff, difference);
} else {
return calculateIrrRecursively(test_rate.subtract(precision), test_rate, precision.divide(BigDecimal.valueOf(10)), cash_flows);
}
} else {
previous_diff = difference;
test_rate = test_rate.add(precision);
}
}
return end.subtract(precision);
}
private static BigDecimal returnCorrectTestRate(BigDecimal precision, BigDecimal test_rate, double previous_diff, double difference) {
if (Math.abs(difference) < Math.abs(previous_diff)) {
return test_rate;
} else {
return test_rate.subtract(precision);
}
}
private static int getDaysInbetween(int current_iteration, int total_cash_flows) {
return (total_cash_flows - current_iteration) * INTERVAL;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment