Investment Performance Software

I am in the process of writing some software that will allow me to input the current market values of my investments every month according to my monthly statement and see the annualized performance over any period I want for any of all of my investments at a time, but it is slow-going. What is the difference between this and Quicken or Microsoft Money? Well first of all, it is free. What is the difference between free programs like Gnucash, etc…? Those programs cannot do this kind of thing in the way I want to just yet. The main difference in usage is that all you need to do is enter information from your monthly statements, such as current market values of your investments and your investment transactions as well. Then various annualized returns can be calculated from that for all your investments, or the aggregation of all your investments over time (for example). It explictly does not rely on daily prices of anything. That is to promote sound conservative investment practice: that daily fluctuations in the market do not matter. If I can get all that to work in a framework that is flexible then I should be able to do a lot more with it too. If anyone things this is interesting or thinks that I am re-inventing the wheel, please tell me.

8 thoughts on “Investment Performance Software”

  1. I think this is really interesting. I used to be a software developer before the big tech crash and love to use my knowledge to help me in my investments and tracking of them. What are you using to develop this?

  2. I’m using Python because it is one of the fastest languages to code in. I might put this project up on sourceforge or on the new google code site once I get something working.

  3. Python eh? I used to do a lot in Perl, mostly in Unix. Look foward to seeing what you can come up with!

  4. Yeah, Perl was pretty common to do things quickly back in the day (well it’s still the quickest for anything to do with string processing AFAIK) but nowadays Python is gaining in popularity over Perl.

  5. I hope you are doing this for the fun of it! It’s certainly not free (what’s your hourly rate worth?)

    I picked up a copy of Quicken 2006 for free (stuck on the front of a $6 investment magazine).

    ps. Even Quicken doesn’t calculate annualised returns perfectly. It gets very messy when you are adding to or selling part of an existing position – you have to track individual lots. You also can’t just use arithmetic averaging of returns.

    I think the easiest method to follow is to just pretend your portfolio is a big ‘black box’, and record all dollar amounts in and out and then iteratively calculate what annual rate of return applied to the model results in the same ending value as your real portfolio. However, unless you have kept a fairly constant amount invested over the total period, this figure is pretty meaningless. eg. If you’ve been investing for ten years but have built up the investment by adding to it each year, you could have the same average annualised return if the early years were excellent and the latter years poor, or vice versa. But althought the average annualised returns are the same the end result is different! To adjust for this you’d have to WEIGHT the return calculation based on the amount you had invested at any time… It all gets way too hard to be of use. You’re better off concentrating on saving more in the early years, and minimising transaction and management costs once you have a reasonable amount invested (say > 5x your annual salary).

  6. ralph: I am also using this type of “black box” method as you call it with the return being the only unknown. I basically use the XIRR function in Excel. I have now written this function in Python and it works and I will use that to calculate returns on an investment-by-investment basis as well as for the whole account.

    I don’t understand the problem you described whereby “you’ve been investing for ten years but have built up the investment by adding to it each year, you could have the same average annualised return if the early years were excellent and the latter years poor, or vice versa.”

    Maybe the XIRR function solves the problem you describe (I think it does).

    XIRR

    More on XIRR

    Anyways, yes I’m doing this for fun. 🙂

  7. Dave: did you ever publish your XIRR function in Python? Would love to have a look at it. I’m looking for an XIRR function in Python and all I have found is NumPy, but it looks like a PIA to install on my machine.

    -Carlos

  8. Carlos, here it is. It uses NumPy.

    from __future__ import division
    import unittest, csv, string, datetime
    from numpy import floor, reshape, size, array, arange
    from dateutil.relativedelta import relativedelta
    import sys
    
    def xirr(cash_flows, dates, yld=0.1, maxiter=50):
        """
        @param cash_flows list of cashflows
        @param dates list of datetime.date objects
        @param yld guess for rate of return
        @param maxiter maximum iterations
        """
        assert len(dates) == len(cash_flows)
        for date in dates:
            assert type(date) == datetime.date
    
        date_ordinals = array([x.toordinal() for x in dates])
        cash_flows = array(cash_flows)
    
        #number of years in cash flow FIXME: use max and min date, not first and last in list
        func = int(floor(yearfrac(dates[0], dates[-1])))
        if func == 0:
            func = 1
        #matlab: tf = func*(dates(:,loop)-dates(1,loop))/(datemnth(dates(1,loop),12*func,0,0)-dates(1,loop));
        tf = func*(date_ordinals - date_ordinals[0]) / (dates[0] + relativedelta(months = +12*func) - dates[0]).days
    
        # Determine the best guess for yld
        min_result = sys.maxint
        best_yld = None
        for yld in arange(-0.9, 1, 0.1):
            if yld == 0:
                continue
            result_f = abs(sum(cash_flows / ((1 + yld)**tf)))
            if result_f < min_result:
                min_result = result_f
                best_yld = yld
    
        yld = best_yld
        print "Using guess yld=", yld
    
        func = 2
        k = 1
        #Newton's Method
        while abs(func) > 1.e-6:
            #cash flow polynomial
            func = sum(cash_flows / ((1 + yld)**tf))
            #%(CF poly)'
            f_prime = -sum((cash_flows/((1 + yld)**tf)) * (tf/(1 +yld)))
            if f_prime == 0:
                yld = None
                break
    
            delta = -func/f_prime
            yld = yld + delta
            k += 1
            if k == maxiter + 1:
                print 'Number of maximum iterations reached.'
                print 'Please increase MAXITER or use different GUESS.'
                yld = None
                break
        return yld
    
    def yearfrac(date1, date2):
        wYears = int(floor(abs((date1 - date2).days) / 365.))
        date1W = datetime.date(date1.year + wYears, date1.month, date1.day)
        numerator = (date1W - date2).days
        try:
            denominator = (date1W - datetime.date(date1W.year + 1, date1W.month, date1W.day)).days
        #-----handle weird leap year case
        except ValueError:
            date1W = date1W + datetime.timedelta(1)
            denominator = (date1W - datetime.date(date1W.year + 1, date1W.month, date1W.day)).days
        yearFraction = numerator / float(denominator)
        return yearFraction + wYears

Leave a Reply

Your email address will not be published. Required fields are marked *