Home

Awesome

#visualize_wealth README.md Build Status

A library built in Python to construct, backtest, analyze, and evaluate portfolios and their benchmarks, with comprehensive documentation and manual calculations to illustrate all underlying methodologies and statistics.

##License

This program is free software and is distrubuted under the GNU General Public License version 3 ("GNU GPL v3")

© Benjamin M. Gross 2013

NOTE: Because so much of the underlying technology I'm continuing to build has become the building blocks for my financial technology startup, I've forked this repo (as of 5.2015) and made new changes private. I might continue to push some of the bigger changes to this repo to keep it open source, but we'll see.

##Dependencies

For a full list of dependencies, see the requirements.txt file in the root folder.

##Installation

To install the visualize_wealth modules onto your computer, go into your desired folder of choice (say Downloads), and:

  1. Clone the repository

     $ cd ~/Downloads
     $ git clone https://github.com/benjaminmgross/wealth-viz
    
  2. cd into the wealth-viz directory

     $ cd wealth-viz
    
  3. Install the package

     $ python setup.py install
    
  4. Check your install. From anywhere on your machine, be able to open iPython and import the library, for example:

     $ cd ~/
     $ ipython
    
     IPython 1.1.0 -- An enhanced Interactive Python.
     ?         -> Introduction and overview of IPython's features.
     %quickref -> Quick reference.
     help      -> Python's own help system.
     object?   -> Details about 'object', use 'object??' for extra details.
    
     In [1]: import visualize_wealth
    

"Ligget Se!"

##Documentation

The README.md file has fairly good examples, but I've gone to great lengths to autogenerate documentation for the code using Sphinx. Therefore, aside from the docstrings, when you git clone the repository, use these instructions to generate the auto-documentation:

1. `cd /path-to-wealth-viz/`
2. `sphinx-build -b html ./docs/source/ ./docs/build/`

Now that the autogenerated documentation is complete, you can cd into:

$ cd visualize_wealth/docs/build/

and find full .html browseable code documentation (that's pretty beautiful... if I do say so my damn self) with live links, function explanations (that also have live links to their respective definition on the web), etc.

Also I've created an Excel spreadsheet that illustrates almost all of the analyze.py portfolio statistic calculations. That spreadsheet can be found in:

visualize_wealth > tests > test_analyze.xlsx

In fact, the unit testing for the analyze.py portfolio statistics tests the python calculations against this same excel spreadsheet, so you can really get into the guts of how these things are calculated.

##Portfolio Construction Examples

Portfolios can (generally) be constructed in one of three ways:

  1. The Blotter Method
  2. Weight Allocation Method
  3. Initial Allocation with specific Rebalancing Period Method

1. The Blotter Method

The blotter method: In finance, a spreadsheet of "buys/sells", "Prices", "Dates" etc. is called a "trade blotter." This also would be the easiest way for an investor to actually analyze the past performance of her portfolio, because trade confirmations provide this exact data.

This method is most effectively achieved by providing an Excel / .csv file with the following format:

DateBuy / SellPriceTicker
9/4/200150123.45EFA
5/5/200365107.71EEM
6/6/2003-15118.85EEM

where "Buys" can be distinguished from "Sells" because buys are positive (+) and sells are negative (-).

For example, let's say I wanted to generate a random portfolio containing the following tickers and respective asset classes, using the generate_random_portfolio_blotter method

TickerDescriptionAsset ClassPrice Start
IWBiShares Russell 1000US Equity5/19/2000
IWRiShares Russell MidcapUS Equity8/27/2001
IWMiShares Russell 2000US Equity5/26/2000
EFAiShares EAFEForeign Dev Equity8/27/2001
EEMiShares EAFE EMForeign EM Equity4/15/2003
TIPiShares TIPSFixed Income12/5/2003
TLTiShares LT TreasuriesFixed Income7/31/2002
IEFiShares MT TreasuriesFixed Income7/31/2002
SHYiShares ST TreasuriesFixed Income7/31/2002
LQDiShares Inv GradeFixed Income7/31/2002
IYRiShares Real EstateAlternative6/19/2000
GLDiShares Gold IndexAlternative11/18/2004
GSGiShares CommoditiesAlternative7/21/2006

I could construct a portfolio of random trades (i.e. the "blotter method"), say 20 trades for each asset, by executing the following:

        #import the modules
In [5]: import vizualize_wealth.construct_portfolio as vwcp

In [6]: ticks = ['IWB','IWR','IWM','EFA','EEM','TIP','TLT','IEF',
                 'SHY','LQD','IYR','GLD','GSG']		
In [7]: num_trades = 20

        #construct the random trade blotter
In [8]: blotter = vwcp.generate_random_portfolio_blotter(ticks, num_trades)

        #construct the portfolio panel
In [9]: port_panel = vwcp.panel_from_blotter(blotter)

Now I have a pandas.Panel. Before we constuct the cumulative portfolio values, let's examine the dimensions of the panel (which are generally the same for all construction methods, although the columns of the minor_axis are different because the methods call for different optimized calculations) with the following dimensions:

#tickers are `panel.items`
In [10]: port_panel.items
Out[10]: Index([u'EEM', u'EFA', u'GLD', u'GSG', u'IEF', u'IWB', u'IWM', u'IWR', 
			u'IYR', u'LQD', u'SHY', u'TIP', u'TLT'], dtype=object)

#dates are along the `panel.major_axis`
In [12]: port_panel.major_axis
Out[12]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2000-07-06 00:00:00, ..., 2013-10-30 00:00:00]
Length: 3351, Freq: None, Timezone: None

#price data, cumulative investment, dividends, and split ratios are `panel.minor_axis`
In [13]: port_panel.minor_axis
Out[13]: Index([u'Open', u'High', u'Low', u'Close', u'Volume', u'Adj Close',
	u'Dividends',u'Splits', u'contr_withdrawal', u'cum_investment', 
	u'cum_shares'], dtype=object)

There is a lot of information to be gleaned from this data object, but the most common goal would be to convert this pandas.Panel to a Portfolio pandas.DataFrame with columns ['Open', 'Close'], so it can be compared against other assets or combination of assets. In this case, use pfp_from_blotter(which stands for "portfolio_from_panel" + portfolio construction method [i.e. blotter, weights, or initial allocaiton] which in this case was "the blotter method").

	#construct_the portfolio series
	In [14]: port_df = vwcp.pfp_from_blotter(panel, 1000.)

	In [117]: port_df.head()
	Out[117]: 
    	          Close         Open
	Date                                
	2000-07-06  1000.000000   988.744754
	2000-07-07  1006.295307  1000.190767
	2000-07-10  1012.876765  1005.723006
	2000-07-11  1011.636780  1011.064479
	2000-07-12  1031.953453  1016.978253

###2. The Weight Allocation Method

A commonplace way to test portoflio management strategies using a group of underlying assets is to construct aggregate portofolio performance, given a specified weighting allocation to specific assets on specified dates. Specifically, those (often times) percentage allocations represent a recommended allocation at some point in time, based on some "view" derived from either the output of a model or some qualitative analysis. Therefore, having an engine that is capable of taking in a weighting file (say, a .csv) with the following format:

DateTicker 1Ticker 2Ticker 3Ticker 4
1/1/20025%20%30%45%
6/3/200340%10%40%10%
7/8/200325%25%25%25%

and turning the above allocation file into a cumulative portfolio value that can then be analyzed and compared (both in isolation and relative to specified benchmarks) is highly valuable in the process of portfolio strategy creation.

A quick example of a weighting allocation file can be found in the Excel File visualize_wealth/tests/panel from weight file test.xlsx, where the tab rebal_weights represents one of these specific weighting files.

To construct a portfolio of using the Weighting Allocation Method, a process such as the following would be carried out.

#import the library
import visualize_wealth.construct_portfolio as vwcp

If we didn't have the prices already, there's a function for that

#fetch the prices and put them into a pandas.Panel
price_panel = vwcp.fetch_data_for_weight_allocation_method(weight_df)

#construct the panel that will go into the portfolio constructor

 port_panel = vwcp.panel_from_weight_file(weight_df, price_panel,
     start_value = 1000.)

Construct the pandas.DataFrame for the portfolio, starting at start_value of 1000 with columns ['Open', Close']

portfolio = vwcp.pfp_from_weight_file(port_panel)

Now a portfolio with index of daily values and columns ['Open', 'Close'] has been created upon which analytics and performance analysis can be done.

3. The Initial Allocation & Rebalancing Method

The standard method of portoflio construction that pervades in many circles to this day is static allocation with a given interval of rebalancing. For instance, if I wanted to implement Oppenheimers' The New 60/40 static portfolio, rebalancing on a yearly interval, my weighting scheme would be as follows:

TickerNameAsset ClassAllocation
IWBiShares Russell 1000US Equity15%
IWRiShares Russell MidcapUS Equity7.5%
IWMiShares Russell 2000US Equity7.5%
SCZiShares EAFE Small CapForeign Dev Equity7.5%
EFAiShares EAFEForeign Dev Equity12.5%
EEMiShares EAFE EMForeign EM Equity10%
TIPiShares TIPSFixed Income5%
TLTiShares LT TreasuriesFixed Income2.5%
IEFiShares MT TreasuriesFixed Income2.5%
SHYiShares ST TreasuriesFixed Income5%
HYGiShares High YieldFixed Income2.5%
LQDiShares Inv GradeFixed Income2.5%
PCYPowerShares EM SovereignFixed Income2%
BWXSPDR intl TreasuriesFixed Income2%
MBBiShares MBSFixed Income1%
PFFiShares Preferred EquityAlternative2.5%
IYRiShares Real EstateAlternative5%
GLDiShares Gold IndexAlternative2.5%
GSGiShares CommoditiesAlternative5%

To implement such a weighting scheme, we can use the same worksheet visualize_wealth/tests/panel from weight file test.xlsx, and the tab. static_allocation. Note there is only a single row of weights, as this will be the "static allocation" to be rebalanced to at some given interval.

#import the construct_portfolio library
import visualize_wealth.construct_portfolio as vwcp

Let's use the static_allocation provided in the panel from weight file.xlsx workbook

f = pandas.ExcelFile('tests/panel from weight file test.xlsx')
static_alloc = f.parse('static_allocation', index_col = 0,
    header_col = 0)

Again, assume we don't have the prices and need to donwload them, use the fetch_data_for_initial_allocation_method

price-panel = vwcp.fetch_data_for_initial_allocation_method(static_alloc)

Construct the panel for the portoflio while determining the desired rebalance frequency

panel =	vwcp.panel_from_initial_weights(weight_series = static_alloc,
	static_alloc, price_panel = price_panel, rebal_frequency = 'quarterly')

Construct the final portfolio with columns ['Open', 'Close']

portfolio = vwcp.pfp_from_weight_file(panel)

Take a look at the portfolio series:

In [10:] portfolio.head()
Out[11:]

            Close        Open
Date
2007-12-12  1000.000000  1007.885932
2007-12-13   991.329125   990.717915
2007-12-14   978.157960   983.057829
2007-12-17   961.705069   969.797167
2007-12-18   969.794966   972.365687