Internal Rate of Return (#156)

The three rules of Ruby Q.:

  1. Please do not post any solutions or spoiler discussion for this quiz
    until
    48 hours have passed from the time on this message.

  2. Support Ruby Q. by submitting ideas as often as you can:

http://www.rubyquiz.com/

  1. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps
everyone
on Ruby T. follow the discussion. Please reply to the original quiz
message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Harrison R.

Internal Rate of Return (IRR –
Internal rate of return - Wikipedia) is a common
financial
metric, used by investment firms to predict the profitability of a
company or
project. Finding the IRR of a company amounts to solving for it in the
equation
for Net Present Value (NPV –
Net present value - Wikipedia),
another valuable decision-making metric:

     N      C_t

NPV = Σ ------------
t=0 (1 + IRR)**t

This week’s quiz is to calculate the IRR for any given variable-length
list of
numbers, which represent yearly cash flows, the C_t’s in the formula
above: C_0,
C_1, etc. (C_0 is typically a negative value, corresponding to the
initial
investment into the project.) From the example in the Wikipedia article
(Internal rate of return - Wikipedia), for instance,
you should
be able to produce a rate of 17.09% (to four decimal places, let’s say)
from
this or a similar command:

irr([-100,+30,+35,+40,+45])
=> 0.1709…

Keep in mind that an IRR greater than 100% is possible. Extra credit if
you can
also correctly handle input that produces negative rates, disregarding
the fact
that they make no sense.

This week’s quiz is to calculate the IRR for any given variable-length list of
numbers, which represent yearly cash flows, the C_t’s in the formula above: C_0,
C_1, etc. (C_0 is typically a negative value, corresponding to the initial
investment into the project.) From the example in the Wikipedia article
(Internal rate of return - Wikipedia), for instance, you should
be able to produce a rate of 17.09% (to four decimal places, let’s say) from
this or a similar command:

    irr([-100,+30,+35,+40,+45])
    => 0.1709...

I think one point, which isn’t brought out here and not well in the
wikipedia article either, is that given all of the C_t, you still have
two unknowns: IRR (which we are attempting to solve for) and NPV.

In this case, you want NPV set to zero in order to solve for IRR. Or
did I miss something?

On Feb 8, 2008 3:01 PM, Ruby Q. [email protected] wrote:

metric, used by investment firms to predict the profitability of a company or
C_1, etc. (C_0 is typically a negative value, corresponding to the initial
that they make no sense.

This must be a strange moment for you or maybe it is too early to say
THANK YOU FOR ALL THE FISH ;), as you still have a summary to do, but
I feel very strange by reading the “last Ruby Q.”.

Robert


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

On Feb 8, 2008, at 9:48 AM, Robert D. wrote:

This must be a strange moment for you

Yes, it was odd to think as I launched the quiz this morning, this is
the last time I will do this.

I will miss it, for sure. I am glad to be stopping while it’s still
going strong though; we all would have enjoyed it a lot less if I had
let it beat me down.

or maybe it is too early to say THANK YOU FOR ALL THE FISH ;), as
you still have a summary to do,

Well, I appreciate the thought anyway.

but I feel very strange by reading the “last Ruby Q.”.

I think of it more as James’s last Ruby Q…

I’m switching sides. I’ll be solving and occasionally contributing
now. I’m looking forward to that.

I’m sure the new team will take great care of the quiz. I have faith.

James Edward G. II

I think one point, which isn’t brought out here and not well in the
wikipedia article either, is that given all of the C_t, you still have
two unknowns: IRR (which we are attempting to solve for) and NPV.

In this case, you want NPV set to zero in order to solve for IRR. Or
did I miss something?

Yes. At least I get the right answer if the “irr” function solves for
NPV=0. :slight_smile:

Paolo

James G. wrote:

by Harrison R.
(…)
This week’s quiz is to calculate the IRR for any given variable-length
list of numbers, which represent yearly cash flows,

In real life, it’s not yearly. IIR needs a time dimension.

irr([-100, a_date],[+30,another_date],[+35,yet_a _date])

James, I learned a LOT thanks to you.

regards,

Siep

On Feb 8, 8:11 am, Matthew M. [email protected] wrote:

In this case, you want NPV set to zero in order to solve for IRR. Or
did I miss something?

That’s correct. I forgot to add that detail when I submitted the
question. Sorry!

Harrison R.

On Feb 8, 4:01 pm, Ruby Q. [email protected] wrote:

Keep in mind that an IRR greater than 100% is possible. Extra credit if you can
also correctly handle input that produces negative rates, disregarding the fact
that they make no sense.

Can we return 1/0.0 if NPV does not evaluate to 0 for a reasonably
large IRR?

irr([+100,+10,+10,+10])
=> Infinity

Many thanks to James for your great job as the Quizmaster! :slight_smile:

How should the following values be handeld? According to some info I
found somewhere, 0…2 should be considered illegal, which doesn’t
quite match my computations though.

[-1.0, 1.0]
[-1000.0, 999.99]
[-1000.0, 999.0]
[0.0]
[]

Regards,
Thomas.

2008/2/8 Matthew M. [email protected]:

This week’s quiz is to calculate the IRR for any given variable-length list of

I think one point, which isn’t brought out here and not well in the
wikipedia article either, is that given all of the C_t, you still have
two unknowns: IRR (which we are attempting to solve for) and NPV.

In this case, you want NPV set to zero in order to solve for IRR. Or
did I miss something?

Isn’t IRR defined as the discount rate that results in an NPV of 0?

Yes, you want the NPV to be zero… so you really just have to solve
for IRR. Another good thing pointed out in the article which I wish
I’d read before trying to solve it generally is that you can’t solve
it in general with a formula :stuck_out_tongue:

On Feb 9, 2:08 pm, ThoML [email protected] wrote:

How should the following values be handeld? According to some info I
found somewhere, 0…2 should be considered illegal, which doesn’t
quite match my computations though.

[-1.0, 1.0]

0

[-1000.0, 999.99]

-0.00001

[-1000.0, 999.0]

-0.001

[0.0]

does not find a solution (mine returns nil)

[]

division by zero. (nil after I add a begin…rescue…end :slight_smile:

Paolo

On Feb 9, 6:08 am, ThoML [email protected] wrote:

Regards,
Thomas.

Yes, (0…2) doesn’t make any sense at all, nor does anything that has
an initial investment of $0. The IRR would be 0/0, which can be
anything, and so you may return anything (or throw an error) if the
first element is a 0. An input list of less than two elements is
similarly ambiguous. As for the others, they do in fact have real
IRRs:

[-1.0, 1.0] => 0.0%
[-1000.0, 999.99] => -0.0001%
[-1000.0, 999.0] => -0.01%

The first case is interesting, however, because you will not be able
to find an IRR of 0% exactly if you are using an iterative solution,
only approach it, depending on how many iterations you use. Also, the
formula does not allow -100% IRR, even though it may be possible.

Harrison R.

On Feb 9, 2008 9:44 AM, [email protected] wrote:

-0.00001

[-1000.0, 999.0]

-0.001

[0.0]

does not find a solution (mine returns nil)

Its a meaningless input anyway, but wouldn’t any rate be a solution?
Since you are looking for the discount rate at which the NPV is 0, if
the only flow is an initial investment of 0, any discount rate will
produce an NPV of 0. (Mine produces 0 for this case.)

[]

division by zero. (nil after I add a begin…rescue…end :slight_smile:

I would think this would be equivalent to the preceding case and,
likewise, any discount rate you try would be a valid solution. (And,
again, mine produces 0 here.)

On Feb 9, 5:48 am, Alex S. [email protected] wrote:

irr([+100,+10,+10,+10])
=> Infinity

Many thanks to James for your great job as the Quizmaster! :slight_smile:

Alex

Such cases have an undefined IRR, and thus the behavior is undefined.

Harrison R.

On Feb 9, 2008 11:44 AM, [email protected] wrote:

[]

[-1.0, 1.0] => 0.0%
[-1000.0, 999.99] => -0.0001%
[-1000.0, 999.0] => -0.01%

The first case is interesting, however, because you will not be able
to find an IRR of 0% exactly if you are using an iterative solution,
only approach it, depending on how many iterations you use.

Is that really a special result of the first case? It seems to me any
iterative method is likely to only approximate any result except for
the one used as the initial starting point (of course, if zero is the
initial starting point, then it can get zero exactly).

On Feb 8, 4:43 pm, Siep K. [email protected] wrote:

James, I learned a LOT thanks to you.

regards,

Siep


Posted viahttp://www.ruby-forum.com/.

I was hoping someone would try this! It wouldn’t be very difficult to
adapt an existing yearly algorithm to do it; all that changes is the
exponent for each term. I’d take only two arguments, though: the
starting date and {dates => cash flows}.

Harrison R.

On Feb 9, 1:02 pm, Christopher D. [email protected] wrote:

Is that really a special result of the first case? It seems to me any
iterative method is likely to only approximate any result except for
the one used as the initial starting point (of course, if zero is the
initial starting point, then it can get zero exactly).

Heheh, dur…I’m fairly new to iterative solutions. Pardon my
naiveness.

irr([+100,+10,+10,+10])
=> Infinity

Such cases have an undefined IRR, and thus the behavior is undefined.

I assume IRR=-1.4228295850 -> -2.8421709430404e-14 wouldn’t qualify as
a solution?

On Feb 9, 9:14 pm, [email protected] wrote:

On Feb 9, 5:48 am, Alex S. [email protected] wrote:

Can we return 1/0.0 if NPV does not evaluate to 0 for a reasonably
large IRR?

irr([+100,+10,+10,+10])
=> Infinity

Such cases have an undefined IRR, and thus the behavior is undefined.

Is it OK to format user’s hard drive then? :wink: