123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
-
-
- package org.apache.poi.ss.formula.functions;
-
- import java.util.Arrays;
-
- import org.apache.poi.ss.formula.eval.ErrorEval;
- import org.apache.poi.ss.formula.eval.EvaluationException;
-
- /**
- * Calculates Modified internal rate of return. Syntax is MIRR(cash_flow_values, finance_rate, reinvest_rate)
- *
- * <p>Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both the cost
- * of the investment and the interest received on reinvestment of cash.</p>
- *
- * Values is an array or a reference to cells that contain numbers. These numbers represent a series of payments (negative values) and income (positive values) occurring at regular periods.
- * <ul>
- * <li>Values must contain at least one positive value and one negative value to calculate the modified internal rate of return. Otherwise, MIRR returns the #DIV/0! error value.</li>
- * <li>If an array or reference argument contains text, logical values, or empty cells, those values are ignored; however, cells with the value zero are included.</li>
- * </ul>
- *
- * Finance_rate is the interest rate you pay on the money used in the cash flows.
- * Reinvest_rate is the interest rate you receive on the cash flows as you reinvest them.
- *
- * @author Carlos Delgado (carlos dot del dot est at gmail dot com)
- * @author Cedric Walter (cedric dot walter at gmail dot com)
- *
- * @see <a href="http://en.wikipedia.org/wiki/MIRR">Wikipedia on MIRR</a>
- * @see <a href="http://office.microsoft.com/en-001/excel-help/mirr-HP005209180.aspx">Excel MIRR</a>
- * @see Irr
- */
- public class Mirr extends MultiOperandNumericFunction {
-
- public Mirr() {
- super(false, false);
- }
-
- @Override
- protected int getMaxNumOperands() {
- return 3;
- }
-
- @Override
- protected double evaluate(double[] values) throws EvaluationException {
-
- double financeRate = values[values.length-1];
- double reinvestRate = values[values.length-2];
-
- double[] mirrValues = Arrays.copyOf(values, values.length - 2);
-
- boolean mirrValuesAreAllNegatives = true;
- for (double mirrValue : mirrValues) {
- mirrValuesAreAllNegatives &= mirrValue < 0;
- }
- if (mirrValuesAreAllNegatives) {
- return -1.0d;
- }
-
- boolean mirrValuesAreAllPositives = true;
- for (double mirrValue : mirrValues) {
- mirrValuesAreAllPositives &= mirrValue > 0;
- }
- if (mirrValuesAreAllPositives) {
- throw new EvaluationException(ErrorEval.DIV_ZERO);
- }
-
- return mirr(mirrValues, financeRate, reinvestRate);
- }
-
- private static double mirr(double[] in, double financeRate, double reinvestRate) {
- double value = 0;
- double numOfYears = in.length - 1;
- double pv = 0;
- double fv = 0;
-
- int indexN = 0;
- for (double anIn : in) {
- if (anIn < 0) {
- pv += anIn / Math.pow(1 + financeRate + reinvestRate, indexN++);
- }
- }
-
- for (double anIn : in) {
- if (anIn > 0) {
- fv += anIn * Math.pow(1 + financeRate, numOfYears - indexN++);
- }
- }
-
- if (fv != 0 && pv != 0) {
- value = Math.pow(-fv / pv, 1d / numOfYears) - 1;
- }
- return value;
- }
- }
|