avatarMario Rodriguez

Summarize

Evaluation of Rebalancing Methods for the Permanent Portfolio in Python

Which rebalancing method is the most profitable for the permanent portfolio? Python backtesting results

Photo by Towfiqu barbhuiya on Unsplash

It’s important to note that a investment strategy may not be suitable for every investor. Individuals should consider their financial goals, risk tolerance, and time horizon before implementing any investment approach. Consulting with a financial advisor can help tailor the strategy to individual needs and circumstances.

Permanent Portfolio

As we have seen before in this article, the Permanent Portfolio consists of four main asset classes:

  1. Stocks: Representing the growth component of the portfolio, stocks provide potential capital appreciation. They are typically represented by a broad-based equity index or a selection of individual stocks.
  2. Bonds: Acting as a hedge against deflation and economic downturns, bonds provide income and stability. They are usually represented by high-quality government bonds or Treasury bonds.
  3. Gold: Serving as a hedge against inflation and currency devaluation, gold provides a store of value. It can be represented by physical gold or gold-backed exchange-traded funds (ETFs).
  4. Cash: Providing liquidity and stability, cash acts as a safe haven during times of uncertainty. It is typically held in the form of short-term government securities or cash equivalents.

Rebalancing in the permanent portfolio

Each of these four assets excels in one of the four predominant states of the economy, allowing the earnings from the strong-performing asset to offset the losses incurred by the other assets. But to do so, the Permanent Portfolio should maintain an equal allocation of 25% to each of these asset classes. However, due to market fluctuations, the portfolio’s actual allocation may deviate from the target weights over time. Rebalancing is the process of bringing the portfolio back to its original target allocation.

Rebalancing in the Permanent Portfolio refers to the process of adjusting the allocation of assets within the portfolio to maintain the desired target weights. An important point to decide is the frequency or some specific rules for rebalancing, which vary depending on an individual’s investment strategy and preferences. Some investors may choose to rebalance annually, while others may rebalance more frequently or based on specific thresholds or triggers. The decision to rebalance should consider transaction costs, tax implications, and the investor’s long-term goals and risk tolerance. But what’s the best option if we want to increase our investment returns?

Python Backtesting

In the previous article, this code was proposed to simulate the permanent portfolio:

# Gather data for stocks, bonds, gold and cash
period = "10y"
STOCKS = yf.Ticker("^GSPC").history(period=period)
STOCKS = STOCKS.drop(columns=['Dividends', 'Stock Splits'])
plt.plot(STOCKS['Close']/STOCKS['Close'][0])

BONDS = yf.Ticker("VBLLX").history(period=period)
BONDS = BONDS.drop(columns=['Dividends', 'Stock Splits'])
plt.plot(BONDS['Close']/BONDS['Close'][0])

GOLD = yf.Ticker("IGLN.L").history(period=period)
GOLD = GOLD.drop(columns=['Dividends', 'Stock Splits'])
plt.plot(GOLD['Close']/GOLD['Close'][0])

CASH = pd.DataFrame({'Close' : np.ones(GOLD['Close'].shape)})
CASH = CASH.set_index(GOLD.index)
plt.plot(CASH['Close']/CASH['Close'][0])

STOCKS_weigth = np.array([0.25])
GOLD_weigth = np.array([0.25])
CASH_weigth = np.array([0.25])
BONDS_weigth = np.array([0.25])

result = np.array([1])
STOCKS_shares = np.array(result*STOCKS_weigth[0]/STOCKS['Close'][0])
GOLD_shares = np.array(result*GOLD_weigth[0]/GOLD['Close'][0])
CASH_shares = np.array(result*CASH_weigth[0]/CASH['Close'][0])
BONDS_shares = np.array(result*BONDS_weigth[0]/BONDS['Close'][0])

for i in range(1,len(BONDS['Close'])):
    # Daily results computation
    result = np.append(result, STOCKS_shares[i-1]*STOCKS['Close'][i] +
                       GOLD_shares[i-1]*GOLD['Close'][i] +
                       CASH_shares[i-1]*CASH['Close'][i] +
                       BONDS_shares[i-1]*BONDS['Close'][i])
    
    # Daily weitgh computation
    STOCKS_weigth = np.append(STOCKS_weigth, STOCKS_shares[i-1]*STOCKS['Close'][i]/result[i])
    GOLD_weigth = np.append(GOLD_weigth, GOLD_shares[i-1]*GOLD['Close'][i]/result[i])
    CASH_weigth = np.append(CASH_weigth, CASH_shares[i-1]*CASH['Close'][i]/result[i])
    BONDS_weigth = np.append(BONDS_weigth, BONDS_shares[i-1]*BONDS['Close'][i]/result[i])
    
    # Check if we need to rebalance the assets
    if BONDS.index[i].year > BONDS.index[i-1].year:                
        # Rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1]-(STOCKS_weigth[i]-STOCKS_weigth[0])*result[i]/STOCKS['Close'][i])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1]-(GOLD_weigth[i]-GOLD_weigth[0])*result[i]/GOLD['Close'][i])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1]-(CASH_weigth[i]-CASH_weigth[0])*result[i]/CASH['Close'][i])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1]-(BONDS_weigth[i]-BONDS_weigth[0])*result[i]/BONDS['Close'][i])
    else:
        # No rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1])

S&P500, USA long-term bonds, iShares Physical Gold ETC and cash (always worth the same) data was used for stocks, bonds, gold and cash. Then, results and assets weight is computed every day, checking if rebalancing is required. In this code, the condition to rebalance is if a new year has started. That is, this strategy rebalances the portfolio annually. Any other periods for rebalancing are possible, such as monthly:

for i in range(1,len(BONDS['Close'])):
    # Daily results computation
    result = np.append(result, STOCKS_shares[i-1]*STOCKS['Close'][i] +
                       GOLD_shares[i-1]*GOLD['Close'][i] +
                       CASH_shares[i-1]*CASH['Close'][i] +
                       BONDS_shares[i-1]*BONDS['Close'][i])
    
    # Daily weitgh computation
    STOCKS_weigth = np.append(STOCKS_weigth, STOCKS_shares[i-1]*STOCKS['Close'][i]/result[i])
    GOLD_weigth = np.append(GOLD_weigth, GOLD_shares[i-1]*GOLD['Close'][i]/result[i])
    CASH_weigth = np.append(CASH_weigth, CASH_shares[i-1]*CASH['Close'][i]/result[i])
    BONDS_weigth = np.append(BONDS_weigth, BONDS_shares[i-1]*BONDS['Close'][i]/result[i])
    
    # Check if we need to rebalance the assets
    if BONDS.index[i].month != BONDS.index[i-1].month:
        # Rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1]-(STOCKS_weigth[i]-STOCKS_weigth[0])*result[i]/STOCKS['Close'][i])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1]-(GOLD_weigth[i]-GOLD_weigth[0])*result[i]/GOLD['Close'][i])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1]-(CASH_weigth[i]-CASH_weigth[0])*result[i]/CASH['Close'][i])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1]-(BONDS_weigth[i]-BONDS_weigth[0])*result[i]/BONDS['Close'][i])
    else:
        # No rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1])

The condition now is the month, if a new month starts the portfolio is rebalanced.

But there is a slightly different solution, if we decide to rebalance just if one of the assets exceeds a limit in terms of its weight in the portfolio. Lets say we want to rebalance when one of the assets exceeds a 10% of the initial 25%. That is, we will rebalance when the weight of one asset is higher than 35% or lower than 15%. The Python code to backtest this option is:

threshold = 0.1
for i in range(1,len(BONDS['Close'])):
    # Daily results computation
    result = np.append(result, STOCKS_shares[i-1]*STOCKS['Close'][i] +
                       GOLD_shares[i-1]*GOLD['Close'][i] +
                       CASH_shares[i-1]*CASH['Close'][i] +
                       BONDS_shares[i-1]*BONDS['Close'][i])
    
    # Daily weitgh computation
    STOCKS_weigth = np.append(STOCKS_weigth, STOCKS_shares[i-1]*STOCKS['Close'][i]/result[i])
    GOLD_weigth = np.append(GOLD_weigth, GOLD_shares[i-1]*GOLD['Close'][i]/result[i])
    CASH_weigth = np.append(CASH_weigth, CASH_shares[i-1]*CASH['Close'][i]/result[i])
    BONDS_weigth = np.append(BONDS_weigth, BONDS_shares[i-1]*BONDS['Close'][i]/result[i])
    
    # Check if we need to rebalance the assets
    if abs(STOCKS_weigth[-1]-0.25)>threshold or abs(GOLD_weigth[-1]-0.25)>threshold or abs(CASH_weigth[-1]-0.25)>threshold  or abs(BONDS_weigth[-1]-0.25)>threshold :
        # Rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1]-(STOCKS_weigth[i]-STOCKS_weigth[0])*result[i]/STOCKS['Close'][i])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1]-(GOLD_weigth[i]-GOLD_weigth[0])*result[i]/GOLD['Close'][i])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1]-(CASH_weigth[i]-CASH_weigth[0])*result[i]/CASH['Close'][i])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1]-(BONDS_weigth[i]-BONDS_weigth[0])*result[i]/BONDS['Close'][i])
    else:
        # No rebalancing
        STOCKS_shares = np.append(STOCKS_shares, STOCKS_shares[i-1])
        GOLD_shares = np.append(GOLD_shares, GOLD_shares[i-1])
        CASH_shares = np.append(CASH_shares, CASH_shares[i-1])
        BONDS_shares = np.append(BONDS_shares, BONDS_shares[i-1])

In this case, a new parameter has been set to define the 10% of margin. Also, this margin may be set to the desired value established by the investor.

Backtesting Results

Results for each strategy are shown in the following graph:

Returns are so similar, and differences are not well visible in this graph. Furthermore, it seems that some strategies are better in some periods and worse in other. Therefore, let’s get the date yearly to compare. The following table shows returns for each strategy:

Whose results shows that the Margin 5% strategy is the best option with a return of 54.64%. Although all the options are quite similar, leading to slightly differences in 20 years, margin-based strategies get highest performance.

And you? Do you follow the permanent portfolio as your investment stragy? Which balancing method do you usually use? Share your opinion on the comments!

More articles about investment strategies:

Do you want to learn Python:

Have you spent your learning budget for this month, you can join Medium here:

Subscribe to DDIntel Here.

DDIntel captures the more notable pieces from our main site and our popular DDI Medium publication. Check us out for more insightful work from our community.

Register on AItoolverse (alpha) to get 50 DDINs

Support DDI AI Art Series: https://heartq.net/collections/ddi-ai-art-series

Join our network here: https://datadriveninvestor.com/collaborate

Follow us on LinkedIn, Twitter, YouTube, and Facebook.

Permanent Portfolio
Invest
Investing
Investment
Investors
Recommended from ReadMedium