First time here? Check out the Help page!
1 | initial version |
Here is the MIRR calculation in BEopt:
public double CalculateModifiedInternalRateOfReturn(OutputPoint outputPt, OutputPoint refOutputPt)
{
float[] NegativeCashFlows = new float[AnalysisPd + 1];
float[] PositiveCashFlows = new float[AnalysisPd + 1];
for (int year = 0; year <= AnalysisPd; year++)
{
float NetCashFlow = (float)(CalculateHomeownerCashFlowForYear(refOutputPt, year) - CalculateHomeownerCashFlowForYear(outputPt, year));
if (NetCashFlow > 0)
PositiveCashFlows[year] = NetCashFlow;
else
NegativeCashFlows[year] = NetCashFlow;
}
double PresentValue = CalculatePresentValueOfCosts(NegativeCashFlows, null);
double FutureValue = CalculateFutureValueOfCosts(PositiveCashFlows, null);
if (PresentValue == 0)
return double.NaN; // Infinite MIRR
double mirr = (Math.Pow(-FutureValue / PresentValue, (1.0 / AnalysisPd)) - 1) * 100;
return mirr;
}
CalculateHomeownerCashFlowForYear is simply:
private double CalculateHomeownerCashFlowForYear(OutputPoint outputPt, int year)
{
return outputPt.NominalCashFlow(year).Incentives +
outputPt.NominalCashFlow(year).LoanInterest +
outputPt.NominalCashFlow(year).LoanPrincipal +
outputPt.NominalCashFlow(year).LoanTaxDeduction +
outputPt.NominalCashFlow(year).ReplacementCost +
outputPt.NominalCashFlow(year).ResidualValue +
outputPt.NominalCashFlow(year).FederalTaxCredits +
outputPt.NominalCashFlow(year).NonFederalTaxCredits +
outputPt.NominalCashFlow(year).UtilityBill +
outputPt.NominalCashFlow(year).CashPayment;
}
2 | No.2 Revision |
Edit: Sorry, you wanted modified payback and not modified internal rate of return.
Here is the MIRR calculation in BEopt:modified payback calculation:
public double CalculateModifiedInternalRateOfReturn(OutputPoint CalculateModifiedPayback(OutputPoint outputPt, OutputPoint refOutputPt)
{
// Calculate total of cash outflows
float TotalCashOutflow = 0;
for (int year = 0; year <= AnalysisPd; year++)
{
TotalCashOutflow += (float)GetPresentValueGivenFutureCost(CalculateNetHomeownerCashFlowForYear(outputPt, refOutputPt, year, false), year, GetNominalDiscountRate());
}
// Calculate cumulative positive cash flows
float[] NegativeCashFlows CumulativePositiveCashFlows = new float[AnalysisPd + 1];
float[] PositiveCashFlows = new float[AnalysisPd + 1];
for (int year = 0; year <= AnalysisPd; year++)
{
float NetCashFlow CumulativePositiveCashFlows[year] = (float)(CalculateHomeownerCashFlowForYear(refOutputPt, year) - CalculateHomeownerCashFlowForYear(outputPt, year));
-1 * (float)GetPresentValueGivenFutureCost(CalculateNetHomeownerCashFlowForYear(outputPt, refOutputPt, year, true), year, GetNominalDiscountRate());
if (NetCashFlow (year > 0)
PositiveCashFlows[year] CumulativePositiveCashFlows[year] += CumulativePositiveCashFlows[year - 1];
}
// Find year where cumulative positive cash flow exceeds the total cash outflow
for (int year = NetCashFlow;
else
NegativeCashFlows[year] = NetCashFlow;
}
double PresentValue = CalculatePresentValueOfCosts(NegativeCashFlows, null);
double FutureValue = CalculateFutureValueOfCosts(PositiveCashFlows, null);
0; year <= AnalysisPd; year++)
{
if (PresentValue (CumulativePositiveCashFlows[year] >= TotalCashOutflow)
{
if (year == 0)
return double.NaN; 0;
// Infinite MIRR
double mirr = (Math.Pow(-FutureValue Interpolate between previous year and this year to obtain
// a non-integer payback value
return year - 1 + (TotalCashOutflow - CumulativePositiveCashFlows[year - 1]) / PresentValue, (1.0 / AnalysisPd)) (CumulativePositiveCashFlows[year] - 1) * 100;
CumulativePositiveCashFlows[year - 1]);
}
}
return mirr;
double.NaN;
}
CalculateHomeownerCashFlowForYear is simply:
private double CalculateHomeownerCashFlowForYear(OutputPoint outputPt, int year)
{
return outputPt.NominalCashFlow(year).Incentives +
outputPt.NominalCashFlow(year).LoanInterest +
outputPt.NominalCashFlow(year).LoanPrincipal +
outputPt.NominalCashFlow(year).LoanTaxDeduction +
outputPt.NominalCashFlow(year).ReplacementCost +
outputPt.NominalCashFlow(year).ResidualValue +
outputPt.NominalCashFlow(year).FederalTaxCredits +
outputPt.NominalCashFlow(year).NonFederalTaxCredits +
outputPt.NominalCashFlow(year).UtilityBill +
outputPt.NominalCashFlow(year).CashPayment;
}
3 | No.3 Revision |
Edit: Sorry, you wanted modified payback and not modified internal rate of return.
Here is the modified payback calculation:
public double CalculateModifiedPayback(OutputPoint outputPt, OutputPoint refOutputPt)
{
// Calculate total of cash outflows
float TotalCashOutflow = 0;
for (int year = 0; year <= AnalysisPd; year++)
{
TotalCashOutflow += (float)GetPresentValueGivenFutureCost(CalculateNetHomeownerCashFlowForYear(outputPt, refOutputPt, year, false), year, GetNominalDiscountRate());
}
// Calculate cumulative positive cash flows
float[] CumulativePositiveCashFlows = new float[AnalysisPd + 1];
for (int year = 0; year <= AnalysisPd; year++)
{
CumulativePositiveCashFlows[year] = -1 * (float)GetPresentValueGivenFutureCost(CalculateNetHomeownerCashFlowForYear(outputPt, refOutputPt, year, true), year, GetNominalDiscountRate());
if (year > 0)
CumulativePositiveCashFlows[year] += CumulativePositiveCashFlows[year - 1];
}
// Find year where cumulative positive cash flow exceeds the total cash outflow
for (int year = 0; year <= AnalysisPd; year++)
{
if (CumulativePositiveCashFlows[year] >= TotalCashOutflow)
{
if (year == 0)
return 0;
// Interpolate between previous year and this year to obtain
// a non-integer payback value
return year - 1 + (TotalCashOutflow - CumulativePositiveCashFlows[year - 1]) / (CumulativePositiveCashFlows[year] - CumulativePositiveCashFlows[year - 1]);
}
}
return double.NaN;
}
CalculateNetHomeownerCashFlowForYear method:
private double CalculateNetHomeownerCashFlowForYear(OutputPoint outputPt, OutputPoint refOutputPt, int year, bool PositiveOnly)
{
double retval = 0;
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).Incentives, refOutputPt.NominalCashFlow(year).Incentives, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).LoanInterest, refOutputPt.NominalCashFlow(year).LoanInterest, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).LoanPrincipal, refOutputPt.NominalCashFlow(year).LoanPrincipal, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).LoanTaxDeduction, refOutputPt.NominalCashFlow(year).LoanTaxDeduction, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).ReplacementCost, refOutputPt.NominalCashFlow(year).ReplacementCost, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).ResidualValue, refOutputPt.NominalCashFlow(year).ResidualValue, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).FederalTaxCredits, refOutputPt.NominalCashFlow(year).FederalTaxCredits, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).NonFederalTaxCredits, refOutputPt.NominalCashFlow(year).NonFederalTaxCredits, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).UtilityBill, refOutputPt.NominalCashFlow(year).UtilityBill, PositiveOnly);
retval += CalculateNetCashFlowForYear(outputPt.NominalCashFlow(year).CashPayment, refOutputPt.NominalCashFlow(year).CashPayment, PositiveOnly);
return retval;
}
CalculateNetCashFlowForYear method:
private double CalculateNetCashFlowForYear(float outputPtVal, float refOutputPtVal, bool PositiveOnly)
{
double diff = outputPtVal - refOutputPtVal;
if ((diff < 0 && PositiveOnly) || (diff > 0 && !PositiveOnly))
return diff;
return 0;
}
GetPresentValueGivenFutureCost method:
public static double GetPresentValueGivenFutureCost(double Cost, double YearOfCost, double DiscountRate)
{
return (Cost / (Math.Pow((1 + DiscountRate), YearOfCost)));
}