In finance, the net present value (NPV) of a time series of cash flows, both inflow and outflow, is defined as the sum of the present values (PVs) of the individual cash flows. In the case when all future or expected cash flows are:
- inflow (e.g as coupons, dividend etc) and;
- outflow of cash is the purchase price (normally we use negative sign for the outflow).
NPV is a central tool in discounted cash flow (DCF) analysis, and is a standard method for using the time value of money to appraise LONG-TERM PROJECTS. Used for capital budgeting, and widely throughout economics, finance, and accounting, it measures the excess or shortfall of cash flows, in present value terms, once financing charges are met.
Figure 1: To calculate the net present value for a series of cash flows that is regularly periodic, NPV function is used. Graphical illustration of net present value NPV - total sum of discounted individual cash flow to present day with the given expected rate. And, net future value NFV - total sum of compounded individual cash flow to future end date of the project with the given expected rate.
For NPV>0 with a given expected rate, the investment would add value to the firm, thus the project may be accepted.
For NPV<0 with a given expected rate, the investment would subtract value from the firm, thus the project should be rejected.
For NPV = 0 with the expected rate, the investment would neither gain nor lose value for the firm. We should be indifferent in the decision whether to accept or reject the project. This project adds no monetary value. And, the given expected rate is now called as IRR - internal rate of return.
Figure 2: Returns the net present value for a schedule of cash flows that is not necessarily periodic, XNPV is used. Graphical illustration of net present value XNPV - total sum of discounted individual cash flow to present day with the given expected rate. And, net future value XNFV - total sum of compounded individual cash flow to future end date of the project with the given expected rate.
By taking XNPV = 0, XIRR is defined as below:
2.0 Methodology
2.1 Net present value - NPV Android Java source code
dbnpv = 0;
for(i=0;i<=5;i++)
dbnpv = dbnpv + dbcf[i]/(Math.pow((1+dbrate/100), i));
if (v==NPV)
{
if(dbnpv<=0)
{
answernpv = "NPV = " + currency.format(dbnpv) +" , project/investment rejected.";
result.setText(answernpv);
}
else
{
answernpv = "NPV = " + currency.format(dbnpv) +" , project/investment accepted.";
result.setText(answernpv);
}
}//NPV calculation closing
2.2 Internal rate of return - IRR Android Java source code
{
{
final double estimateddbirr = 0;
Double dbirr = Double.NaN;
if (dbcf != null && dbcf.length > 0)
{
//check if business startup costs is not zero:
if (dbcf[0] != 0.0)
{
final double noOfdbcf = dbcf.length;
double sumdbcf = 0.0;
//check if at least 1 positive and 1 negative cash flow exists:
int noOfNegativedbcf = 0;
int noOfPositivedbcf = 0;
for (int i1 = 0; i1 < noOfdbcf; i1++)
{
sumdbcf += dbcf[i1];
if (dbcf[i1] > 0)
{
noOfPositivedbcf++;
}
else if (dbcf[i1] < 0)
{
noOfNegativedbcf++;
}
}
if (noOfNegativedbcf > 0 && noOfPositivedbcf > 0)
{ //at least 1 negative and 1 positive cash flow available?
//set estimated dbirr:
double irrGuess = 0.1; //default: 10%
if (estimateddbirr != Double.NaN)
{
irrGuess = estimateddbirr;
if (irrGuess <= 0.0) irrGuess = 0.5;
}
//initialize first IRR with estimated dbirr:
double irr = 0.0;
if (sumdbcf < 0)
{ //sum of cash flows negative?
irr = -irrGuess;
}
else
{ //sum of cash flows not negative
irr = irrGuess;
}
//iteration Newton-Raphson method:
final double minDistance = .0000000001; //the smaller the distance, the smaller the interpolation error
final double dbcftart = dbcf[0]; //business startup costs
final int maxIteration = 50;
boolean wasHi = false;
double cashValue = 0.0;
for (int i1 = 0; i1 <= maxIteration; i1++)
{ //for each iteration
//calculate cash value with current irr:
cashValue = dbcftart; //init value with startup costs
for (int j1 = 1; j1 < noOfdbcf; j1++)
{ //for each cash flow
cashValue += dbcf[j1] / Math.pow(1.0 + irr, j1);
}//next cash flow
if (Math.abs(cashValue) < 0.01)
{ //cash value is nearly zero
dbirr = irr;
break;
}
//adjust irr for next iteration:
if (cashValue > 0.0)
{ //cash value > 0 => next irr > current irr
if (wasHi)
{
irrGuess /= 2;
}
irr += irrGuess;
if (wasHi)
{
irrGuess -= minDistance;
wasHi = false;
}
}
else
{ //cash value < 0 => next irr < current irr
irrGuess /= 2;
irr -= irrGuess;
wasHi = true;
}
if (irrGuess <= minDistance)
{ //estimated dbirr too small to continue => end calculation
dbirr = irr;
break;
}
}//next iteration
}//else: noOfNegativedbcf == 0 || noOfPositivedbcf == 0
}//else: first cash flow is 0
}//else: dbcf unavailable
answerirr = "IRR(%) = " + formatter.format(dbirr*100) + "%";
result.setText((String) answerirr.toString());
//return ir;
}//getIRR()
} //IRR calculation closing
2.3 Net future value - NFV Android Java source code
{
dbnfv = dbnpv*Math.pow(1+dbrate/100,number-1);
answernfv = "NFV = " + currency.format(dbnfv);
result.setText(answernfv);
} //NFV calculation closing
2.4 Net present value - XNPV Android Java source code
dbnpv = 0;
for(i=0;i<=5;i++)
dbnpv = dbnpv + dbcf[i]/(Math.pow((1+dbrate/100),ddiff[i]/365));
if (v==NPV)
{
if(ddiff[5]<0||ddiff[4]<0||ddiff[3]<0||ddiff[2]<0||ddiff[1]<0||ddiff[0]<0)
{
new AlertDialog.Builder(this)
.setTitle("Error Message")
.setMessage("Please key in date in ascending order!")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do nothing – it will close on its own
}
})
.show();
}
else
{
if(dbnpv<=0)
{
answernpv = "NPV = " + currency.format(dbnpv) +" , project/investment rejected.";
result.setText(answernpv);
}
else
{
answernpv = "NPV = " + currency.format(dbnpv) +" , project/investment accepted.";
result.setText(answernpv);
}
}//Error message closing
}//NPV calculation closing
2.5 Internal rate of return - XIRR Android Java source code
{
{
final double estimateddbirr = 0;
Double dbirr = Double.NaN;
if (dbcf != null && dbcf.length > 0)
{
//check if business startup costs is not zero:
if (dbcf[0] != 0.0)
{
final double noOfdbcf = dbcf.length;
double sumdbcf = 0.0;
//check if at least 1 positive and 1 negative cash flow exists:
int noOfNegativedbcf = 0;
int noOfPositivedbcf = 0;
for (int i1 = 0; i1 < noOfdbcf; i1++)
{
sumdbcf += dbcf[i1];
if (dbcf[i1] > 0)
{
noOfPositivedbcf++;
}
else if (dbcf[i1] < 0)
{
noOfNegativedbcf++;
}
}
if (noOfNegativedbcf > 0 && noOfPositivedbcf > 0)
{ //at least 1 negative and 1 positive cash flow available?
//set estimated dbirr:
double irrGuess = 0.1; //default: 10%
if (estimateddbirr != Double.NaN)
{
irrGuess = estimateddbirr;
if (irrGuess <= 0.0) irrGuess = 0.5;
}
//initialize first IRR with estimated dbirr:
double irr = 0.0;
if (sumdbcf < 0)
{ //sum of cash flows negative?
irr = -irrGuess;
}
else
{ //sum of cash flows not negative
irr = irrGuess;
}
//iteration Newton-Raphson method:
final double minDistance = .0000000001; //the smaller the distance, the smaller the interpolation error
final double dbcftart = dbcf[0]; //business startup costs
final int maxIteration = 50;
boolean wasHi = false;
double cashValue = 0.0;
for (int i1 = 0; i1 <= maxIteration; i1++)
{ //for each iteration
//calculate cash value with current irr:
cashValue = dbcftart; //init value with startup costs
for (int j1 = 1; j1 < noOfdbcf; j1++)
{ //for each cash flow
cashValue += dbcf[j1] / Math.pow(1.0 + irr, ddiff[j1]/365);
}//next cash flow
if (Math.abs(cashValue) < 0.01)
{ //cash value is nearly zero
dbirr = irr;
break;
}
//adjust irr for next iteration:
if (cashValue > 0.0)
{ //cash value > 0 => next irr > current irr
if (wasHi)
{
irrGuess /= 2;
}
irr += irrGuess;
if (wasHi)
{
irrGuess -= minDistance;
wasHi = false;
}
}
else
{ //cash value < 0 => next irr < current irr
irrGuess /= 2;
irr -= irrGuess;
wasHi = true;
}
if (irrGuess <= minDistance)
{ //estimated dbirr too small to continue => end calculation
dbirr = irr;
break;
}
}//next iteration
}//else: noOfNegativedbcf == 0 || noOfPositivedbcf == 0
}//else: first cash flow is 0
}//else: dbcf unavailable
answerirr = "IRR(%) = " + formatter.format(dbirr*100) + "%";
result.setText((String) answerirr.toString());
//return ir;
}//getIRR()
}//error message closing
} //IRR calculation closing
2.6 Net future value - XNFV Android Java source code
{
dbnfv = dbnpv*Math.pow(1+dbrate/100,ddiff[number-1]/365);
answernfv = "NFV = " + currency.format(dbnfv);
result.setText(answernfv);
}//Error message closing
} //NFV calculation closing
else if (v==IRR)
{if(ddiff[5]<0||ddiff[4]<0||ddiff[3]<0||ddiff[2]<0||ddiff[1]<0||ddiff[0]<0)
{
new AlertDialog.Builder(this)
.setTitle("Error Message")
.setMessage("Please key in date in ascending order!")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do nothing – it will close on its own
}
})
.show();
}
3.0 Excel Example:
3.1 Net present value - NPV
3.2 Internal rate of return - IRR
3.3 Net future value - NFV
3.4 Net present value - XNPV
3.5 Internal rate of return - XIRR
3.6 Net future value - XNFV
4.0 Practical Application
4.1 Regular Period - Highway Project
4.2 Irregular Period - Stock's return calculation
4.3 Bonus - Number of day between two dates calculation
5.0 Download - It is available at Android Market now. Search for FREENPVIRR from Application>Finance - Just in for free download. Enjoy!