Bootstrapping method
Definition
Faced with growing uncertainty in financial markets, investors are worried about the future of their investments. Travelling in time to check the future reality is not yet a possibility. For that reason, we use techniques and create measures to gain confidence in our investments’ future behaviour.
Bootstrapping is a financial technique that allows us to get a return confidence interval for a certain time horizon given the distribution of a sample of historical portfolio returns. We have to keep in mind this method doesn’t predict future results but it gives us an idea of the expected returns based on the historical behaviour of our portfolio.
Supposing that the portfolio launch date was on 1st January 2010 and we had this asset universe:
import pandas as pd import numpy as np import pandas_datareader.data as web import datetime import random import matplotlib.pyplot as plt import matplotlib as mpl from cycler import cycler from scipy.stats.kde import gaussian_kde from scipy.stats import norm start, end = datetime.datetime(2009, 12, 30), datetime.datetime(2016, 12, 31) tickers = ["TLT", "HYG", "^GSPC", "^STOXX50E", "^N225", "^FTSE"] universe = pd.DataFrame([web.DataReader(t, 'yahoo', start, end).loc[:, 'Adj Close'] for t in tickers], index=tickers).T.fillna(method='ffill') universe = universe/universe.iloc[0,:]-1
We talked with our favourite monkey advisor Jeff to give each asset a weight in order to beat our benchmark, an equally weighted portfolio:
equally_weights = pd.DataFrame(1./len(universe.columns), index=universe.index, columns=universe.columns) monkey_weights = pd.DataFrame(np.random.uniform(low=0, high=1, size=universe.shape),index=universe.index, columns=universe.columns) monkey_weights = monkey_weights/pd.DataFrame(monkey_weights.sum(1).repeat(6).values.reshape(universe.shape), index=universe.index, columns=universe.columns) returns = (1+universe).pct_change(periods=1).fillna(0) benchmark_returns = (returns*equally_weights).sum(1) benchmark = (1+benchmark_returns).cumprod()-1 portfolio_returns = (returns*monkey_weights).sum(1) portfolio = (1+portfolio_returns).cumprod()-1
How do I do it?
We have the following return distribution for our universe, benchmark and portfolio:
For the Bootstrapping we randomly select 261 returns from each distribution multiple times (in this case I did 1000 repetitions). Accumulating these returns we achieve new random samples as possible curves in one year.
benchmark_bootstrapping = (1+pd.DataFrame([random.sample(list(benchmark_returns.values), 261) for i in range(1000)]).T.shift(1).fillna(0)).cumprod()-1 portfolio_bootstrapping = (1+pd.DataFrame([random.sample(list(portfolio_returns.values), 261) for i in range(1000)]).T.shift(1).fillna(0)).cumprod()-1
Removing the outliers, our portfolio could get a yearly return between -5% and 30%, clearly beating our benchmark (from -7.5% to 24.5%):
benchmark_bootstrapping_prc = benchmark_bootstrapping.quantile([0.05, 0.50, 0.95], axis=1).T portfolio_bootstrapping_prc = portfolio_bootstrapping.quantile([0.05, 0.50, 0.95], axis=1).T
Good job Jeff!!