Averaging stocks: Time series analysis with Python

Regarding investments in the stock market, one of the most prevalent tips you’ll hear is that of averaging. What you do is this: You decide on an amount of money that you periodically have available for investing, e.g. weekly or monthly. Then you choose a certain stock or basket of stocks (e.g. an ETF) you believe will grow over the long term. Subsequently, you consistently invest that money in the stock, regardless of market conditions.

If you keep the amount of input consistent, that should result in a portfolio containing lots of cheap stock and little expensive stock. Let me explain. Say, you have $100 to spend monthly on investments. This month, a certain stock is valued at €5, so you buy 20. Next month, the same stock is valued at €10, so you buy 10. So you bought 30 stocks at €5 and €10, however your average buying price is (20 x 5 + 10 x 10) / 30 =  €6.67. Over the long term, your average buying price should be quite low compared to the general market. The cheaper a certain fund becomes, the more of that fund you’ll acquire. And the opposite of course.

This results in not having to time the correct moment for buying and selling, and your average buying price should be well below the average market price. Thus, your portfolio should outperform both the market, and stock picking in the long term. Of course, you won’t make any money in a market that has a long-term downtrend, but you’ll outperform a market that is moving sideward for a long period of time. Moreover, you actually capitalize on volatility in that situation.

The concept of averaging stocks is theoretically sound. However, I’d like to know:

  1. How does an averaged portfolio behave over the long term?
  2. How much of the time will my portfolio be worth more than what I put in? In other words; if I cash out at a random point, what are my odds of returning a profit?

I’ll use Amsterdam Exchange (AEX) data for the past 25 years to answer these questions. First, we’ll need some data. This is how you acquire stock data from Yahoo Finance:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import random
import fix_yahoo_finance as yf  
import datetime

start = datetime.datetime(1993,1,1)
end = datetime.datetime(2018,1,1)
data = yf.download('^AEX',start,end)

Now, we’ll need to write a definition that builds up a ‘portfolio’ based on a certain stock time series, certain periodic budget, and certain interval.

def avg_buy(series, budget, interval): 
    
    ##compute daily amounts bought
    amount_acquired = [int(budget / price) for price in series]

    ##compute avg price series
    avg_price_market, avg_price_bought, portfolio, portfolio_worth = [],[],[],[]

    for day, amount in enumerate(amount_acquired): 
        if day % interval == 0: 
            ##list of individual stocks acquired on that day with price 
            acquired = [series[day] for stock in range(amount)]
            ##compute portfolio
            portfolio = portfolio + acquired
            ##compute the actual value of the portfolio
            portfolio_worth.append(int(series[day] * len(portfolio)))
            ##compute mean price of portfolio
            for i in range(interval): 
                ##append the mean price of the portfolio
                avg_price_bought.append(np.mean(portfolio))
                ##append the mean price of the market
                avg_price_market.append(np.mean(series[:day+1]))
    
    return avg_price_bought, avg_price_market, portfolio_worth

The definition returns a list of average buying prices, a list of average market prices, and a list of portfolio values, for each day in the dataset.

Let’s apply the definition to the AEX data, with a 20-day interval and €10000 for monthly investments. Of course that amount is large, but the budget to stock value ratio should be quite large for this to work.

budget = 10000
timespan = 20

avg_price_bought, avg_price_market, portfolio_worth = avg_buy(AEX,budget, timespan)

Now, that already answers some questions. It is clearly visible that averaging in this situation outperforms the average market price. Also, the portfolio becomes more stable over time. When you acquire a larger portfolio, price movements aren’t going to make big dents into it anymore. Only three periods are visible during which you would have lost money on selling the portfolio.

This is what it looks like when you compare the amount invested to portfolio worth:

invested = [10000*i/20 for i in range(1,len(AEX),20)]

Now for determining exactly by how much averaging outperforms the market, I’ll first take some random subsets from the AEX series. Then, I’ll compute for each of the subsets the percentage of time the portfolio outperformed the AEX. I keep the portfolio at 10000, set the interval to weekly, and take 50 samples:

ratios = []
for i in range(50): 
    ##random start date
    start = random.randint(0, len(AEX))
    ##random end date, after the start date
    end = random.randint(start, len(AEX))
    ##take a subset, and if it's not too short, apply our definition
    subset = AEX[start:end]
    if len(subset) > 1000: 
        avg_price_bought, avg_price_market, portfolio_worth = avg_buy(subset,10000, 5)
        print(len(avg_price_bought), len(subset))
    ##compute proportion of time the portfolio is worth more than the original investment: 
        x = 0
        for idx, j in enumerate(subset): 
            if j > avg_price_bought[idx]: 
                x+=1

        ratio = x / len(subset)
        ratios.append(ratio)

print(np.mean(ratios))

This returns an average ratio of 0.61. Therefore, if you randomly sell your averaged portfolio at any time, you’ll turn a profit 61% of the time.

So there you have it! Blindly averaging your stocks and ignoring timing and market conditions, beats the market most of the time. In a next post, I’ll show what another common investment technique, compound interest, looks like.