Financial Portfolio rebalancing with Elixir.

What’s a portfolio?

A portfolio is a grouping of financial assets such as stocks, bonds, commodities, currencies and cash equivalents, as well as their fund counterparts, including mutual, exchange-traded and closed funds. A portfolio can also consist of non-publicly tradable securities, like real estate, art, and private investments.

Source: investopedia

The “Permanent Portfolio”

The “Permanent Portfolio” was created by Harry Browne in the 1980s. It assumes the economy has four possible states:

Prosperity : A period of economic growth, thriving business, low unemployment rates and low-interest rates.

: A period of economic growth, thriving business, low unemployment rates and low-interest rates. Inflation : A period when consumer prices generally are rising.

: A period when consumer prices generally are rising. Deflation : The opposite of inflation.

: The opposite of inflation. Recession: A significant decline in economic activity spread across the economy.

Distribution

Based on those economic conditions, Browne identified the most volatile asset classes, proposing the following distribution:

Prosperity : 25% Stocks

: 25% Stocks Inflation : 25% Gold

: 25% Gold Deflation : 25% Long term government bonds

: 25% Long term government bonds Recession: 25% Cash

The self-regulation factor of the “Permanent Portfolio” is one of the fundamental concepts of Browne’s idea. It covers the most different scenarios of the economy, looking for ways to compensate losses and increase returns. This concept makes the “Permanent Portfolio” appealing to people who don’t want to be actively managing a portfolio on a daily (or even monthly) basis.

Let’s take a look at the historical prices of Gold and S&P500 (an index that measures the stock performance of the 500 large companies listed on stock exchanges in the United States).

Source: Yahoo Finance

In 2008, the year of the global financial crisis, stock investors definitively got worried about the market, and as a result, the value of the S&P index plunges. For 4 years, the S&P value stayed low, only getting back to its pre-crisis value after 2013. In case your investments were purely stocks, it wouldn’t be a fun ride.

At the same time, around 2008, the price of gold has started rising. When comparing it to the S&P value at the same time, its behaviour presents almost an inverted shape. The gold value has not only covered the stock losses but also has contributed to a profitable year.

While many investors were incredibly affected by the 2008 crisis, “Permanent Portfolio” holders had the following returns:

2008: +1.97%

2009: +7.8%

2010: +14.5%

2011: +11.36%

2012: +6.8%

2013: -2.4%

2014: +9.1%

Despite a small glitch in 2013, the returns from the “Permanent Portfolio” were always positive. Considering the whole period between 2008 and 2014, the portfolio had an average return of 7% per year.

That’s one of the properties of the “Permanent Portfolio”, which makes its usage so appealing to more risk-averse humans like myself.

Fast forward to 2019, many people are concerned about a new financial crisis. Germany (where I live) is about to declare “technical recession” (two consecutive quarterly contractions in the economy). If you look at the chart, you can again see the unbalanced form between S&P and gold.

Of course that by looking at this chart, I (an amateur investor) can’t draw any conclusions about whether there’s a recession coming next or not. What’s essential to highlight is that the behaviour of the “Permanent Portfolio” is again supporting a potential crisis scenario.

Rebalancing a portfolio

The portfolio distribution (Stocks: 25%, Gold: 25%, Long term government bonds: 25%, Cash: 25%), will change over time. Some individual classes will increase, while others will decrease. That change shifts the asset classes desired allocation.

The “Permanent Portfolio” embraces the fact that the market is cyclical. There will be prosperity times where stocks value will rise and gold will plunge, but there will also be times where the stock market is not the best option.

Rebalancing a portfolio means getting the asset classes back to their desired allocations (25% each), by selling the ones that are overweight and buying the underweight ones.

The financial crisis in 2008 has created an unbalanced portfolio situation. It “forced” the portfolio holder to sell parts of the gold and use the profits to buy stocks (at an extremely low value) to balance it back to the desired weights.

In the long run (remember the market is cyclical), by continuously rebalancing a portfolio, you are using the built-in volatility of the portfolio to “buy cheap and sell high”.

Using Elixir to rebalance a “Permanent Portfolio”

Let’s use Elixir to rebalance a permanent portfolio. Those are the essential points when thinking about the optimal rebalancing strategy:

Sell overweight items (e.g. current allocation is higher than 25%)

Buy underweight items (e.g. current allocation is lower than 25%), using the profits from the overweight sell.

Reduce the number of operations (e.g. buy and sell), because every transaction also has a cost.

Take decisions based on real-time information.

Let’s imagine the following interface:

allocations = %{ " IAU" => 10 , " TLT" => 10 , " VGSH" => 10 , " VTI" => 10 } orders = Rebalancex . rebalance_portfolio ( allocations )

Based on a number of allocations (the amount of units that a specific item has), you can call the Rebalancex.rebalance_portfolio , which will return a number of orders to be performed.

Those orders contain information if a given symbol must be bought, sold or kept as it is:

[ [ :sell , " IAU" , 4 ], [ :sell , " TLT" , 1 ], [ :sell , " VGSH" , 1 ], [ :buy , " VTI" , 8 ] ]

Considering the points above, that’s the code responsible for rebalancing the portfolio:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 defmodule Rebalancex do alias Rebalancex . Quote @underweight 0.25 @overweight 0.27 def rebalance_portfolio ( allocations , quote_service \\ Quote ) do portfolio = %{ cash: 0 , allocations: allocations } prices = get_prices ( allocations , quote_service ) new_portfolio = do_rebalance_portfolio ( portfolio , prices ) create_order ( portfolio , new_portfolio ) end defp do_rebalance_portfolio ( portfolio , prices ) do positions = get_positions ( portfolio . allocations , prices ) weights = get_weights ( positions ) underweight_symbol = get_underweight ( weights ) overweight_symbol = get_overweight ( weights ) portfolio |> maybe_buy_underweight ( underweight_symbol , prices ) |> maybe_sell_overweight ( overweight_symbol , prices ) |> maybe_rebalance_again ( underweight_symbol , overweight_symbol , prices ) end defp get_prices ( allocations , quote_service ) do allocations |> Enum . reduce (%{}, fn { symbol , _ }, acc -> Map . put ( acc , symbol , quote_service . price_for ( symbol )) end ) end defp get_price ( prices , symbol ) do Map . fetch! ( prices , symbol ) end defp get_positions ( portfolio , prices ) do portfolio |> Enum . reduce (%{}, fn { symbol_name , units }, acc -> Map . put ( acc , symbol_name , get_price ( prices , symbol_name ) * units ) end ) end defp get_weights ( positions ) do total_value = Enum . reduce ( positions , 0 , fn { _ , position }, acc -> position + acc end ) positions |> Enum . reduce (%{}, fn { symbol_name , position }, acc -> Map . put ( acc , symbol_name , position / total_value ) end ) end defp get_underweight ( weights ) do { symbol , _weight } = weights |> Enum . filter ( fn { _ , value } -> value < @underweight end ) |> Enum . min_by ( fn { _ , value } -> value end , fn -> { nil , nil } end ) symbol end defp get_overweight ( weights ) do { symbol , _weight } = weights |> Enum . filter ( fn { _ , value } -> value > @overweight end ) |> Enum . max_by ( fn { _ , value } -> value end , fn -> { nil , nil } end ) symbol end defp maybe_buy_underweight ( portfolio , nil , _ ) do portfolio end defp maybe_buy_underweight ( portfolio , symbol , prices ) do price = get_price ( prices , symbol ) maybe_buy_underweight ( portfolio , symbol , price , portfolio . cash ) end defp maybe_buy_underweight ( portfolio , symbol , price , cash ) when cash > price do portfolio |> incr ( symbol ) |> withdraw ( price ) end defp maybe_buy_underweight ( portfolio , _symbol , _price , _cash ) do portfolio end defp maybe_sell_overweight ( portfolio , nil , _prices ) do portfolio end defp maybe_sell_overweight ( portfolio , symbol , prices ) do price = get_price ( prices , symbol ) portfolio |> decr ( symbol ) |> deposit ( price ) end defp maybe_rebalance_again ( portfolio , nil , nil , _prices ) do portfolio end defp maybe_rebalance_again ( portfolio , _ , _ , prices ) do do_rebalance_portfolio ( portfolio , prices ) end defp incr (%{ allocations: allocations } = portfolio , symbol ) do new_allocations = Map . put ( allocations , symbol , allocations [ symbol ] + 1 ) %{ portfolio | allocations: new_allocations } end defp decr (%{ allocations: allocations } = portfolio , symbol ) do new_allocations = Map . put ( allocations , symbol , allocations [ symbol ] - 1 ) %{ portfolio | allocations: new_allocations } end defp deposit (%{ cash: cash } = portfolio , amount ), do : %{ portfolio | cash: cash + amount } defp withdraw (%{ cash: cash } = portfolio , amount ), do : %{ portfolio | cash: cash - amount } defp create_order (%{ allocations: old_allocations }, %{ allocations: new_allocations }) do Enum . map ( old_allocations , fn { symbol , old_units } -> cond do new_allocations [ symbol ] > old_units -> [ :buy , symbol , new_allocations [ symbol ] - old_units ] new_allocations [ symbol ] < old_units -> [ :sell , symbol , old_units - new_allocations [ symbol ]] true -> [ :keep , symbol ] end end ) end end

Some things to point out:

The Rebalancex.Quote module fetches real-time prices using the AlphaVantage API.

module fetches real-time prices using the AlphaVantage API. It buys or sells single units at a time and re-evaluates how the weights were affected.

It keeps rebalancing the portfolio until there’s no underweight or overweight item in it.

The order is created by comparing the original portfolio to the rebalanced one.

Demo

I created a project to visualize the evolution of a “Permanent Portfolio” value over time. Starting with the amount of $10k, you can change different variables like monthly deposits, rebalancing strategy, region and see the impact on the final value.

The demo project is:

An API built using Elixir and Plug.

A frontend application built using React and Redux.

Data visualization using D3.

Visit https://elviovicosa.com/permanent-portfolio to test it live.