Go, RBSA and Fortran

Dec 21, 2013 at 8:56AM
Caleb Doxsey

After doing some project cleanup recently I ran across this repository and it occurred to me that this project would make for an interesting blog post. It involves a difficult financial analysis problem and cross-language integration. A demo of the application is available here. This post is broken into 3 parts: a description of a problem, an explanation of the solution to that problem and a code walkthrough.

The Problem

Style analysis is often an important part of making financial decisions. From Investopedia:

Definition of 'Style Analysis'

The process of determining what type of investment behavior an investor or money manager employs when making investment decisions. Virtually all investors subscribe to a form of investment philosophy, and a prudent analysis of a money manager's style needs to be performed before an investor can determine whether the manager will be good fit for his or her personal investment goals and preferences. investopedia | Style Analysis

Determining the style of a mutual fund is traditionally done using Holdings-Based Style Analysis (HBSA). HBSA works like this: Take the underlying securities of a mutual fund, bucket them according to their asset class (large cap, small cap, fixed income, etc...), and finally aggregate their relative weights into a fund level style breakdown. In other words a 'large value' mutual fund is made up of largely 'large value' holdings.

Though straightforward, HBSA has some problems:

In 1988 William F. Sharpe proposed an alternative solution to the problem called Returns-Based Style Analysis (RBSA). As the name would indicate, RBSA uses the returns of a mutual fund to determine its style. Conceptually the basic idea is represented like this:

Here's an alternative visual representation of what we're trying to do: (from the Handbook of Equity Style Management)

The Solution

According to several sources this is a quadratic optimization problem. Quadratic optimization is anything but trivial, but there are freely available algorithms which can solve problems like this. In this case I used quadprog from the R statistical programming environment. Released under the GPL license this algorithm solves problems of this form:

this routine uses the Goldfarb/Idnani algorithm to solve the following minimization problem:

minimize  -dTx + ½ xTDx
   where  A1Tx = b1
          A2Tx ≥ b2

the matrix D is assumed to be positive definite. Especially, w.l.o.g. D is assumed to be symmetric.

Transforming our equation into this form we end up with the following.

| var(M)         0              0      ...          0    |
|   0    2⋅cov(R1, R1)   2⋅cov(R1, R2)  ...  2⋅cov(R1, RN) |
|   0    2⋅cov(R2, R1)   2⋅cov(R2, R2)  ...  2⋅cov(R2, RN) |
|   0                          ...                       |
|   0    2⋅cov(RN, R1)   2⋅cov(RN, R2)  ...  2⋅cov(RN, RN) |
|   2⋅var(M)   |
| 2⋅cov(R1, M) |
| 2⋅cov(R2, M) |
|      ...     |
| 2⋅cov(RN, M) |
| 1 0 ... 0 | = | 1 |
| 0 1 ... 1 |   | 1 |
| 1 0 0 ... 0 | = | 0 |
| 0 1 0 ... 0 |   | 0 |
|     ...     |   | 0 |
| 0 0 0 ... 1 |   | 0 |

Or at least it's something like that.

The Code

So how does one build a solution to this problem?

My goal was to build a Go package that when given a series of index and manager returns it would hand me back the corresponding weights. Like this:

package rbsa

...

type (
    ReturnsBasedStyleAnalysis struct {
        indices []string
        returns map[string]Vector
    }
)
func (this *ReturnsBasedStyleAnalysis) AddIndex(id string, returns Vector)
func (this *ReturnsBasedStyleAnalysis) Run(returns Vector) (map[string]float64, error)

I made 3 additional packages: lalg (for constructing vectors & matrices), quadprog (for calling the underlying library) and statistics (for computing variance, covariance, etc...). lalg and statistics are straightforward, but quadprog is not since it's not native Go code.

As previously stated the optimizer (which actually does most of the work) comes from R and is written in fortran. I don't know fortran, and in my admittedly non-exhaustive search I've not found any documentation for how to call fortran from Go. That said it's not altogether different from calling C.

With quadprog ready there were 3 remaining tasks:

And there you have it a complete, working, hybrid go-fortran, web-based, financial analysis tool.

Notes

A version of this project was originally done for client work using C#, and then later Node.js here. (source for the latter is available here)