Asset Management

How to… use bootstrapping in portfolio management

Pablo Sánchez

29/03/2017

No Comments

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

Bootstrapping_Universe

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

Bootstrapping_Portfolio_Benchmark

How do I do it?

We have the following return distribution for our universe, benchmark and portfolio:

Bootstrapping_Distribution

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

Bootstrapping_series

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

Bootstrapping_quantile

Good job Jeff!!

Jeff

0 Comments
Inline Feedbacks
View all comments