In a previous post, we chose some growth stocks and compared a uniform weight Buy and Hold (BAH) portfolio with the S&P 500 as a benchmark to see how our chosen stocks perform. The simple BAH strategy ended us 67% cumulative return while the S&P ended with 41% during the period from 2013 to 2015.
from IPython.display import IFrame
IFrame('https://plot.ly/~ahmedas91/30.embed', width=950, height=450)
In this post, we are going to explore further portfolio allocation strategies and set the BAH with equal weights strategy as the benchmark using the same stocks. Specifically, we are going to explore OnLine Portfolio Selection (OLPS) algorithms on those stocks and see whether we can get even higher returns than the simple BAH strategy. We will also compare them with a uniform weight Constant Rebalanced Portfolio (CRP), a portfolio where the weighs of the stocks are rebalanced periodically to keep them equal.
OLPS aims to maximize commutative wealth by periodically updating the portfolio based on a specific algorithm that optimize asset weighs in the portfolio. Li and Hoi [1] provides a detailed comprehensive survey on those algorithms and Paul Perry's Ipythone notebook provides an excellent implementation of those algorithms in python. Those algorithms can be categorized by three categories: Follow the winner, Follow the loser, Pattern matching and meta-learning. Algorithms that we'll compare are summarized below.
algorithms that falls into this categories track the winning stocks and try to increase the weights of the winning stocks based on their historical performance.
Rather than tracking the winning stocks, Follow the loser algorithms track the losing stocks and increase their weighs while creasing the weighs of the winning stocks. The algorithms here are based on the idea of mean reversion where assets with low performance in the past will perform higher in the future and vice versa.
In general, Pattern matching-based algorithms mainly include pattern-matching and portfolio optimization steps and exploit recurring pattern over history.
We are going to use the same data from the previous post (available on github) and the same period (from 2013 to 2015). The csv file that contains the list of stocks available on the github repo.
import pandas as pd
import pandas_datareader.data as web
from datetime import datetime
from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
import cufflinks as cf
init_notebook_mode()
# Load the aggregated list of companies
data = pd.read_csv("TOP_COMP_2012.csv")
start = datetime(2013, 1, 1)
end = datetime(2015, 12, 31)
tickers = list(data['ticker'].unique())
data = web.DataReader(tickers, 'yahoo',start,end)['Adj Close']
We are going to use the universal-portfolios library which offers most of the main OLPS algorithms discussed above.
warnings.filterwarnings("ignore")
from universal import algos
import warnings
port_alogos = {'BAH': algos.BAH(),
'CRP': algos.CRP(),
'UP': algos.UP(),
'EG': algos.EG(),
'ONS': algos.ONS(),
'Anticor': algos.Anticor(),
'PAMR': algos.PAMR(),
'CWMR': algos.CWMR(),
'OLMAR': algos.OLMAR(),
'RMR': algos.RMR(),
'BNN': algos.BNN(),
'CORN': algos.CORN()}
result = {}
for i, j in enumerate(port_alogos):
result[j] = port_alogos[j].run(data)
returns = pd.DataFrame()
for i in result:
returns = pd.concat([returns, pd.DataFrame({i:(result[i].equity-1)*100})],1)
returns.iplot(dimensions=(950,500), layout={'yaxis': {'ticksuffix':'%'},
'title': 'Cumulative Returns'})
(refresh the page if you don't see the graph above)The above graph shows astonishing results for the two pattern matching algorithms BNN and CORN with cumulative returns of 420% and 241% respectively, beating our BAH benchmark of 66%. ONS also had a great returns of 102%. The other algorithms performed below the benchmark and some ended with significant negative returns. However, lets not forget that here we are assuming a frictionless liquid market. Moreover, the period from 2013 to 2015 does not include a backs swan event such as the 2008 financial crises. Therefore, we will also need to see if the algorithms are robust to those events. That is why we are going to use the same data starting from 2005 instead of 2013 to see how the algorithms perform during the financial crises. Note that some of the stocks used above will not be included since some of them weren't public or didn't exist in 2005. Therefore, we will not compare the results below with the one above since we are using different stocks.
start_2005 = datetime(2005, 1, 1)
data_2005 = web.DataReader(tickers, 'yahoo',start_2005,end)['Adj Close']
result_2005 = {}
for i, j in enumerate(port_alogos):
result_2005[j] = port_alogos[j].run(data_2005)
returns_2005 = pd.DataFrame()
for i in result_2005:
returns_2005 = pd.concat([returns_2005, pd.DataFrame({i:(result_2005[i].equity-1)*100})],1)
returns_2005.iplot(dimensions=(950,500),
layout={'yaxis': {'ticksuffix':'%'},
'title': 'Cumulative Returns'})
The results are interesting during the financial crises. If you zoom on the graph by simply hovering the mouse on the graph and select the area period from July 2008 to may 2009 (this is why I love plotting with plotly). During the crises, only three algorithms, PAMR, CWMR and RMR, beat the BAH strategy and they are all under follow the loser category. However, after the crises during a bull market, only the ONS (follow the winner) strategy beat the BAH. This suggests (but does not proves) that depending on market conditions, some algorithms perform better than the others. Note that non of the algorithms' parameters were tuned and the default ones were used. We could improve the algorithms by trying out different parameters on a training period. Let's check the weights of the best performing algorithm below.
result_2005['ONS'].weights.iplot(kind='bar',
barmode='stack',
dimensions=(950,500),
title='ONS Weights',
theme='white')
For comprehensive results that better demonstrate the effectiveness of those strategies, it is worth to check out Li and Hoi [12] chapter 13 on empirical results. The results in their textbook can be easily replicated using either the python library used here or the MATLAB OLPS toolbox and the dataset they used are available here.
[1] Li, B., & Hoi, S. C. (2014). Online portfolio selection. CSUR ACM Comput. Surv. ACM Computing Surveys, 46(3), 1-36.
[2] Cover, T. M. (1991). Universal Portfolios. Mathematical Finance, 1(1), 1-29.
[3] Agarwal, A., Hazan, E., Kale, S., & Schapire, R. E. (2006). Algorithms for portfolio management based on the Newton method. Proceedings of the 23rd International Conference on Machine Learning - ICML '06.
[4] Helmbold, D. P., Schapire, R. E., Singer, Y., & Warmuth, M. K. (1998). On-Line Portfolio Selection Using Multiplicative Updates. Mathematical Finance, 8(4), 325-347.
[5] Borodin, A., El-Yaniv, R., & Gogan, V. (2004). Can we learn to beat the best stock. Journal of Artificial Intelligence Research, 21, 579-594.
[6] Li, B., Zhao, P., Hoi, S. C., & Gopalkrishnan, V. (2012). PAMR: Passive aggressive mean reversion strategy for portfolio selection. Machine learning, 87(2), 221-258.
[7] Li, B., Hoi, S. C., Zhao, P., & Gopalkrishnan, V. (2013). Confidence weighted mean reversion strategy for online portfolio selection. ACM Transactions on Knowledge Discovery from Data (TKDD), 7(1), 4.
[8] Li, B., & Hoi, S. C. (2012). On-line portfolio selection with moving average reversion. arXiv preprint arXiv:1206.4626.
[9] Huang, D., Zhou, J., Li, B., Hoi, S. C., & Zhou, S. (2013). Robust Median Reversion Strategy for Online Portfolio Selection.
[10] Györfi, L., Lugosi, G., & Udina, F. (2006). NONPARAMETRIC KERNEL‐BASED SEQUENTIAL INVESTMENT STRATEGIES. Mathematical Finance, 16(2), 337-357.
[11] Li, B., Hoi, S. C., & Gopalkrishnan, V. (2011). Corn: Correlation-driven nonparametric learning approach for portfolio selection. ACM Transactions on Intelligent Systems and Technology (TIST), 2(3), 21.
[12] Li, B., & Hoi, S. C. H. (2015). Online Portfolio Selection: Principles and Algorithms. CRC Press.