Wednesday, September 15, 2010

Android Application FREENPVIRR 2.19 Tutorial - A Free NPV, IRR, XNPV, XIRR and Date Different Calculator

1.0 BACKGROUND

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.


Decision making criteria:
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!






2 comments:

Small Cat said...

This is my first Android Application. I am debugging it now. Hopefully it will be available at Android market and Maxis store.

Unknown said...

Hey Thanks for this awesome code.Can you please tell me what are the variable "v" and "NPV" that you used during the NPV calculation??(The very first one)