Line 0
Link Here
|
|
|
1 |
/* ==================================================================== |
2 |
Licensed to the Apache Software Foundation (ASF) under one or more |
3 |
contributor license agreements. See the NOTICE file distributed with |
4 |
this work for additional information regarding copyright ownership. |
5 |
The ASF licenses this file to You under the Apache License, Version 2.0 |
6 |
(the "License"); you may not use this file except in compliance with |
7 |
the License. You may obtain a copy of the License at |
8 |
|
9 |
http://www.apache.org/licenses/LICENSE-2.0 |
10 |
|
11 |
Unless required by applicable law or agreed to in writing, software |
12 |
distributed under the License is distributed on an "AS IS" BASIS, |
13 |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 |
See the License for the specific language governing permissions and |
15 |
limitations under the License. |
16 |
==================================================================== */ |
17 |
|
18 |
package org.apache.poi.ss.formula.functions; |
19 |
|
20 |
import org.apache.poi.ss.formula.TwoDEval; |
21 |
import org.apache.poi.ss.formula.eval.ErrorEval; |
22 |
import org.apache.poi.ss.formula.eval.NumberEval; |
23 |
import org.apache.poi.ss.formula.eval.ValueEval; |
24 |
|
25 |
/** |
26 |
* Calculates the internal rate of return. |
27 |
* |
28 |
* Syntax is IRR(values) or IRR(values,guess) |
29 |
* |
30 |
* @author Marcel May |
31 |
* @see <a href="http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution">Wikipedia on IRR</a> |
32 |
* @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a> |
33 |
*/ |
34 |
public final class Irr implements Function { |
35 |
|
36 |
public ValueEval evaluate(final ValueEval[] args, final int srcRowIndex, final int srcColumnIndex) { |
37 |
if (args.length == 1 && args[0] instanceof TwoDEval) { |
38 |
// Use default estimate |
39 |
double[] numbers = extractNumbers((TwoDEval) args[0]); |
40 |
return new NumberEval( irr(numbers)); |
41 |
} else if (args.length == 2 && args[0] instanceof TwoDEval && args[1] instanceof NumberEval ) { |
42 |
double[] numbers = extractNumbers((TwoDEval) args[0]); |
43 |
return new NumberEval( irr(numbers, extractDouble(args[1]))); |
44 |
} else { |
45 |
// Wrong number of arguments |
46 |
return ErrorEval.NA; |
47 |
} |
48 |
} |
49 |
|
50 |
private double[] extractNumbers(final TwoDEval pArg) { |
51 |
// Validate |
52 |
if (!pArg.isColumn() && !pArg.isRow()) { |
53 |
throw new RuntimeException("area" + pArg.getWidth() + "x" + pArg.getHeight() + " must be either row or column"); |
54 |
} |
55 |
double[] res = new double[Math.max(pArg.getHeight(), pArg.getWidth())]; |
56 |
if (pArg.isRow()) { |
57 |
for (int i = 0; i < res.length; i++) { |
58 |
res[i] = extractDouble(pArg.getValue(i, 0)); |
59 |
} |
60 |
} else { |
61 |
for (int i = 0; i < res.length; i++) { |
62 |
res[i] = extractDouble(pArg.getValue(0, i)); |
63 |
} |
64 |
} |
65 |
return res; |
66 |
} |
67 |
|
68 |
private double extractDouble(final ValueEval pValue) { |
69 |
if (pValue instanceof NumberEval) { |
70 |
return ((NumberEval) pValue).getNumberValue(); |
71 |
} |
72 |
throw new RuntimeException("Can not convert to number: " + pValue); |
73 |
} |
74 |
|
75 |
|
76 |
/** |
77 |
* Computes the internal rate of return using an estimated irr of 10 percent. |
78 |
* |
79 |
* @param income the income values. |
80 |
* @return the irr. |
81 |
*/ |
82 |
public static double irr(double[] income) { |
83 |
return irr(income, 0.1d); |
84 |
} |
85 |
|
86 |
/** |
87 |
* Computes the internal rate of return using an estimated irr. |
88 |
* |
89 |
* @param income the income values. |
90 |
* @param estimatedIrr the optional estimated irr. |
91 |
* @return the irr. |
92 |
* @see {http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution} |
93 |
*/ |
94 |
public static double irr(double[] income, double estimatedIrr) { |
95 |
double r_prev = estimatedIrr / 2d; |
96 |
double npv_prev = FinanceLib.npv(r_prev, income); |
97 |
double r = estimatedIrr; |
98 |
|
99 |
// Stop iteration by iteration count or delta |
100 |
int iter = 0; |
101 |
while (Math.abs(r - r_prev) > 0.00001d && iter <= 20) { |
102 |
double npv = FinanceLib.npv(r, income); |
103 |
double old_r = r; |
104 |
r -= npv * (r - r_prev) / (npv - npv_prev); |
105 |
npv_prev = npv; |
106 |
r_prev = old_r; |
107 |
iter++; |
108 |
} |
109 |
return r; |
110 |
} |
111 |
} |
0 |
+ text/plain |
112 |
+ text/plain |
1 |
+ Date Revision |
113 |
+ Date Revision |
2 |
+ native |
114 |
+ native |