Question

Can anyone help me with a method that calculates the IRR of a series of stock trades?

Let's say the scenario is:

$10,000 of stock #1 purchased 1/1 and sold 1/7 for $11,000 (+10%)
$20,000 of stock #2 purchased 1/1 and sold 1/20 for $21,000 (+5%)
$15,000 of stock #3 purchased on 1/5 and sold 1/18 for $14,000 (-6.7%)

This should be helpful: http://www.rubyquiz.com/quiz156.html

But I couldn't figure out how to adapt any of the solutions since they assume the period of each return is over a consistent period (1 year).

Was it helpful?

Solution

I finally found exactly what I was looking for: http://rubydoc.info/gems/finance/1.1.0/Finance/Cashflow

gem install finance

To solve the scenario I posted originally:

include Finance
trans = []
trans << Transaction.new( -10000, date: Time.new(2012,1,1) )
trans << Transaction.new( 11000, date: Time.new(2012,1,7) )
trans << Transaction.new( -20000, date: Time.new(2012,1,1) )
trans << Transaction.new( 21000, date: Time.new(2012,1,20) )
trans << Transaction.new( -15000, date: Time.new(2012,1,5) )
trans << Transaction.new( 14000, date: Time.new(2012,1,18) )

trans.xirr.apr.to_f.round(2)

I also found this simple method: https://gist.github.com/1364990

However, it gave me some trouble. I tried a half dozen different test cases and one of them would raise an exception that I was never able to debug. But the xirr() method in this Finance gem worked for every test case I could throw at it.

OTHER TIPS

For an investment that has an initial value and final value, as is the case with your example data that includes purchase price, sell price and a holding period, you only need to find holding period yield.

Holding period yield is calculated by subtracting 1 from holding period return

HPY = HPR - 1
HPR = final value/initial value
HPY = 11,000/10,000 - 1 = 1.1 - 1 = 0.10 = 10%
HPY = 21,000/20,000 - 1 = 1.05 - 1 = 0.05 = 5%
HPY = 14,000/15,000 - 1 = 0.9333 - 1 = -0.0667 = -6.7%

This article explains holding period return and yield

You can also annualize the holding period return and holding period yield using following formula AHPR = HPR^(1/n) AHPY = AHPR - 1

The above formulas only apply if you have a single period return as is the case with your example stock purchase and sale.

Yet if you had multiple returns, for example, you purchased a stock A on 1/1 for 100 and it's closing price over the next week climbed and fell to 98, 103, 101, 100, 99, 104

Then you will have to look beyond what HPR and HPY for multiple returns. In this case you can calculate ARR and GRR. Try out these online calculators for arithmetic rate of return and geometric rate of return.

But then if you had a date schedule for your investments then none of these would apply. You would then have to resort to finding IRR for irregular cash flows. IRR is the internal rate of return for periodic cash flows. For irregular cash flows such as for stock trade, the term XIRR is used. XIRR is an Excel function that calculates internal rate of return for irregular cash flows. To find XIRR you would need a series of cash flows and a date schedule for the cash flows.

Finance.ThinkAndDone.com explains IRR in much more detail than the articles you cited on RubyQuiz and Wiki. The IRR article on Think & Done explains IRR calculation with Newton Raphson method and Secant method using either the NPV equation set to 0 or the profitability index equation set to 1. The site also provides online IRR and XIRR calculators

I don't know anything about finance, but it makes sense to me that if you want to know the rate of return over 6 months, it should be the rate which equals the yearly rate when compounded twice. If you want to know the rate for 3 months, it should be the rate which equals the yearly rate when compounded 4 times, etc. This implies that converting from a yearly return rate to a rate for an arbitrary period is closely related to calculating roots. If you express the yearly return rate as a proportion of the original amount (i.e. express 20% return as 1.2, 100% return as 2.0, etc), then you can get the 6-month return rate by taking the square root of that number.

Ruby has a very handy way to calculate all kinds of complex roots: the exponentiation operator, **.

n ** 0.5       # square root
n ** (1.0/3.0) # 3rd root

...and so on.

So I think you should be able to convert a yearly rate of return to one for an arbitrary period by:

yearly_return ** (days.to_f / 365)

Likewise to convert a daily, weekly, or monthly rate or return to a yearly rate:

yearly_return = daily_return ** 365
yearly_return = weekly_return ** 52
yearly_return = monthly_return ** 12

...and so on.

As far as I can see (from reading the Wikipedia article), the IRR calculation is not actually dependent on the time period used. If you give a series of yearly cash flows as input, you get a yearly rate. If you give a series of daily cash flows as input, you get a daily rate, and so on.

I suggest you use one of the solutions you linked to to calculate IRR for daily or weekly cash flows (whatever is convenient), and convert that to a yearly rate using exponentiation. You will have to add 1 to the output of the irr() method (so that 10% return will be 1.1 rather than 0.1, etc).

Using the daily cash flows for the example you gave, you could do this to get daily IRR:

irr([-30000,0,0,0,-15000,0,11000,0,0,0,0,0,0,0,0,0,0,14000,0,21000])

You can use the Exonio library:

https://github.com/Noverde/exonio

and use it like this:

Exonio.irr([-100, 39, 59, 55, 20]) # ==> 0.28095

I believe that the main problem in order to be able to understand your scenario is the lack of a cash flow for each of the stocks, which is an essential ingredient for computing any type of IRR, without these, none of the formulas can be used. If you clarify this I can help you solve your problem

Heberto del Rio

There is new gem 'finance_math' that solves this problem very easy

https://github.com/kolosek/finance_math

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top