When it comes to constructing a multi-asset portfolio, utilizing a powerful backtesting engine can determine the viability of your investment strategy. Zipline, an open-source backtesting framework originally developed by Quantopian, provides the tools necessary to run event-driven backtests on financial algorithms.
In this tutorial, we'll guide you through the steps to create a simple yet effective multi-asset investment strategy. This portfolio will diversify its risk across multiple asset classes, such as stocks, bonds, and commodities, and test its effectiveness using Zipline. Let’s dive into the process step by step.
Prerequisites
To work effectively with Zipline, ensure you have the following set up:
- Python (at least version 3.6)
- Zipline library installed (pip install zipline-reloaded)
- A Jupyter Notebook environment or an IDE like PyCharm or VS Code
- Basic familiarity with Python programming
Setting Up Your Environment
First, make sure you have Zipline installed. This can be done via pip:
pip install zipline-reloaded
Next, set up your IDE or Jupyter Notebook as your working environment to execute the forthcoming code snippets.
Define The Strategy
Begin by defining the universe of assets you wish to include in your portfolio. For simplicity, let’s consider a mix of stock indices, bonds, and a commodity ETF:
from zipline.api import order_target_percent, symbol, record
def initialize(context):
context.assets = [symbol('SPY'), # S&P 500 ETF
symbol('TLT'), # 20+ Year Treasuries ETF
symbol('GLD')] # Gold Trust ETF
context.target_weights = {symbol('SPY'): 0.5, # 50% Stocks
symbol('TLT'): 0.3, # 30% Bonds
symbol('GLD'): 0.2} # 20% Commodities
In this snippet, our portfolio consists of 50% stocks, 30% bonds, and 20% commodities.
Rebalance Strategy
We will rebalance the portfolio once a month:
from zipline.api import schedule_function, date_rules
def rebalance(context, data):
for asset, target_weight in context.target_weights.items():
if data.can_trade(asset):
order_target_percent(asset, target_weight)
schedule_function(rebalance, date_rules.month_start())
Explanation: This function checks if each asset can be traded (based on data availability and other factors) and then places orders to adjust the portfolio's weights according to predefined target values.
Recording And Analyzing Results
The following function illustrates capturing portfolio performance metrics to analyze later:
def record_vars(context, data):
record(Leverage=context.account.leverage,
SPY=data.current(symbol('SPY'), 'price'))
schedule_function(record_vars, date_rules.every_day())
Finally, run the backtest and examine the output. Using the following command, we can execute and visualize our strategy performance:
from zipline import run_algorithm
start = pd.Timestamp('2015-01-01', tz='utc')
end = pd.Timestamp('2020-01-01', tz='utc')
result = run_algorithm(start=start,
end=end,
initialize=initialize,
capital_base=10000,
handle_data=None,
bundle='quantopian-quandl')
result.to_pickle('zipline_backtest_result.pkl')
Conclusion
This tutorial provides a foundational understanding of creating a multi-asset portfolio management strategy using Zipline. While our example is rudimentary and primarily educational, it offers insights into how you can scale this up for more complex assets and custom rules. Experiment with different assets, rebalancing strategies, and rebuy thresholds to optimize your portfolio’s performance.