Periodically Rebalanced Static Allocation 'Buy and Hold' Strategies in QSTrader

In this article we outline a useful helper script provided with QSTrader to quickly simulate monthly rebalanced 'buy and hold' strategies on collections of ETFs.

For those systematic traders who are considering a long-term investment horizon one of the most common forms of generating a portfolio involves static proportional capital allocation amongst a collection of (hopefully) diversifying asset classes, which is periodically rebalanced to maintain the allocation. Such portfolios are often termed 'buy and hold' despite the fact that the rebalancing can involve asset sales.

One of the most popular portfolios of this type is the 60/40 US equities/bonds portfolio, often implemented via broad stock and bond index ETFs, such as SPY and AGG.

Another famous portfolio in this area is the All Weather Portfolio of Ray Dalio (founder of Bridgewater Associates). The approach of the portfolio is to tilt the majority of the allocation towards bonds, with the remainder in commodities and equities. This is an attempt to 'risk weight' the portfolio by increasing the allocation to lower volatility assets.

A retail-oriented implementation of such a portfolio involves a selection of ETFs to represent the main asset classes of US equities, long- and intermediate-term US bonds, commodities and gold. A selection of ETFs that may be appropriate for this includes VTI, TLT, IEI, GLD and GSG[1].

Given the prevalence of such investment approaches it makes sense to ensure it is straightforward as possible to simulate their performance with QSTrader.

With the recent release of QSTrader v0.1.0 we included a helpful command line script that can backtest such rebalanced 'buy and hold' strategies with ease. The source code for the script can be found here.

In the following sections we will describe how to utilise the script to carry out your own backtests.

Simulating 'Buy and Hold' Strategies with QSTrader

Firstly, ensure that QSTrader is properly installed via:

pip install qstrader

Secondly, choose an appropriate directory where the ETF CSV files will be located for each of the ETFs and set the following environment variable to this directory. For instance, in Unix-based systems such as macOS or Linux typing the following into the terminal will (temporarily) tell QSTrader where to find the necessary data:


Thirdly, navigate to your code directory (replacing /MY/CODE/DIR with your chosen directory) and download the static backtest script:


We are now ready to begin carrying out a backtest on an example 'buy and hold' strategy.

Simulating the All Weather Portfolio

In this section we will backtest Ray Dalio's All Weather Portfolio on the selection of five ETFs described above.

The particular static allocation utilised is taken from here [1] and is reprinted in the following table:

Ticker Description Allocation
VTI US Total Stock Market 30%
TLT US Long-Term Bonds 40%
IEI US Intermediate-Term Bonds 15%
GLD Gold 7.5%
GSG Commodities 7.5%

Make sure to download the historical data for each ETF from Yahoo Finance. For example, the data for VTI can be found here.

Note: It will also be necessary to download the historical data for both SPY and AGG in order to create the appropriate 60/40 benchmark portfolio.

Place the downloaded CSV files into the directory specified above making sure to replace /PATH/TO/MY/CSV/DATA with your chosen directory.

Ensure your Python virtual environment (or Anaconda environment) is active and then run the following command:

python --start-date="2007-01-31" --allocations=VTI:0.3,TLT:0.4,IEI:0.15,GLD:0.075,GSG:0.075 --title="All Weather Portfolio" --id="all-weather-portfolio" --tearsheet

The command tells the backtest to begin on the 31st January 2007 and end on the latest available data within the CSV files.

The percentage allocations are specified as a comma-separated list of tickers and percentage values between 0.0 and 1.0.

The title for the backtest tearsheet is also provided, as is the file identifier for the JSON statistics that are output at the completion of the backtest.

Once the backtest has run to completion a tearsheet should be visible, which looks similar to the following:

To create your own bespoke portfolios it is necessary to modify the --allocations parameter to provide the list of tickers and their percentage allocations in a similar format to the All Weather Portfolio above.

Note that it is not actually necessary to ensure that the allocations sum to 100% since the default portfolio construction mechanism in QSTrader will re-scale the values accordingly. It is however necessary to ensure all the allocations are positively-valued. QSTrader does not yet support shorting in v0.1.0.

In this manner it is possible to rapidly simulate many 'buy and hold' style backtests and thus compare many long-term investment approaches on historical ETF data.

Backtest Details

The following provides more details on the specifics of the backtest:

  • The script is actually creating two backtests—one for the primary strategy and one for the 60/40 benchmark.
  • Each backtest is rebalanced once at the end of the calendar month with instantaneous market order execution occuring at the next weekday open.
  • A cash buffer of 1% is maintained throughout both backtests to avoid target orders exceeding current cash through significant overnight price changes.
  • The script makes use of a Python library called click to allow straightforward parsing of command line arguments.


We have provided a useful helper script to carry out backtests on statically-allocated monthly-rebalanced 'buy and hold' portfolios commonly implemented via low-cost ETFs.

The script is designed to be easily modified such that alternative rebalance periods can be applied. QSTrader v0.1.0 supports daily and weekly rebalancing as can be seen here.

With some modification it is possible to compare two 'buy and hold' strategies directly, by changing the second benchmark strategy used within the script.

If you have any questions about the script or QSTrader in general please feel free to email us at