Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Financial.IRR not calculated in C#

Tags:

c#

irr

I am not able to calculate IRR. I am usign Microsoft.VisualBasic to calculate IRR. Here is a case:

using Microsoft.VisualBasic;

...

static void Main(string[] args)
        {
            double[] tmpCashflows = new double[] {
                -480117.0,
                4471.5158140594149,
                6841.5950239895265,
                6550.383550359461,
                6295.8611873818609,
                6074.6070899770129,
                5883.532880960287,
                6006.9907860976427,
                6133.1633945923877
                ,6262.1156759885489
                //,6393.9143799520116            
            };

            decimal irr = 0;
            try
            {
                double tmpIrr = Financial.IRR(ref tmpCashflows);                
                ...
            }
            catch (Exception ex)
            {
                irr = 0;
            }


        }

It gives exception of type "Argument is not valid" (at Microsoft.VisualBasic.Financial.IRR(Double[]& ValueArray, Double Guess)). However, this doesn't show any errors if I do calculations inside Excel.

like image 730
renathy Avatar asked Apr 04 '14 08:04

renathy


People also ask

Why is my IRR formula not working?

And it is the source of problems because rows with empty cells are left out of Excel IRR calculation. To fix this, just enter zero values in all blank cells. Excel will now see the correct time intervals and compute the internal return rate correctly.

When can IRR not be calculated?

Limitations of IRRIn the case of positive cash flows followed by negative ones and then by positive ones, the IRR may have multiple values. Moreover, if all cash flows have the same sign (i.e., the project never turns a profit), then no discount rate will produce a zero NPV.

What is the IRR for project C?

Project C's NPV is positive, it has an IRR of 16 percent, and the payback period is 18 months.

How is IRR calculated manually?

For each amount (either coming in, or going out) work out its Present Value, then: Add the Present Values you receive. Subtract the Present Values you pay.


2 Answers

You need to provide a good Guess value as the 2nd parameter to this API. The default value of 0.1 fails for your inputs.

Try this:

double tmpIrr = Financial.IRR(ref tmpCashflows, 0.3);

and you should get back an IRR of -0.2987

It looks like the API handles only specific cases of inputs and fails on others for any guess. This is an IRR API Bug for Microsoft acknowledged here.

You're better off calculating IRR using a 3rd party reliable library,if Guess becomes an issue.

http://connect.microsoft.com/VisualStudio/feedback/details/781299/microsoft-visualbasic-financial-irr-doesnt-solve-for-irr-correctly-in-certain-cases-with-any-guess

The reason you get an Argument is not valid exception is because the IRR cannot be calculated for the default Guess value of 0.1. Note that the given values satisfy the condition of one negative value (payment) and one positive value. (receipt)

Internally, **Microsoft.VisualBasic.Financial.IRR** goes through the input values and tries to calculate the IRR over 40 iterations. It never encounters the breaking condition for valid IRR and hence finally throws this error.

Note that Excel gives a value of -30%.

At the same time, trying the IRR for an array like

tmpCashflows = new double[] { -100, 200, 300 };
double tmpIrr = Microsoft.VisualBasic.Financial.IRR(ref tmpCashflows);

gives an IRR of 2.0 or 200%. (both via code and Excel)

like image 64
Raja Nadar Avatar answered Oct 24 '22 20:10

Raja Nadar


public static class Interpolation
{
    public static double IRR(this Dictionary<double, double> cashFlow)  //term in years, amount
    {
        int count = 0;
        double r1=0.1d, r2=0.05d, v1, v2, r = 0, v;
        v1 = cashFlow.DiscountedValue(r1);
        v2 = cashFlow.DiscountedValue(r2); 
        while (Math.Abs(v2 - v1) > .001 && count < 1000)
        {
            count++;
            r = (0 - v1) / (v1-v2) * (r1 - r2) + r1;
            v = cashFlow.DiscountedValue(r);
            v1 = v2;
            r1 = r2;
            v2 = v;
            r2 = r;
        }
        if (count == 1000) return -1;
        return r;
    }



    public static double DiscountedValue(this Dictionary<double, double> cashFlow, double rate)
    {
        double dv = 0d;
        for (int i = 0; i < cashFlow.Count; i++)
        {
            var element = cashFlow.ElementAt(i);
            dv += element.Value * Math.Pow(1 + rate, -(element.Key));
        }
        return dv;   
    }
}
like image 42
Mark Avatar answered Oct 24 '22 20:10

Mark