Algorithmic Trading - Backtesting a strategy in python

Share:
Photo by Maxim Hopman on Unsplash

Intro
The goal of this article is to describe how to back-test a technical indicator-based strategy on python. I will specifically use a Bollinger band-based strategy to create signals and positions.

Description of strategy
Create 20-day (+/- 2 standard deviations) Bollinger bands on the adjusted close price. Buy, when the price crosses the lower band from the top and hold until the price crosses the upper band from below the next time. Sell when the price crosses the upper band from below and hold until the price crosses the lower band from the top the next time.

Here are the steps to create your own back-testing code.

  1. Import necessary libraries
  2. Download OHLCV Data
  3. Calculate daily returns
  4. Create strategy-based data columns
  5. Create strategy indicators
  6. Create signals and positions
  7. Analyze results

Step 1: Import necessary libraries

Step 2: Download OHLCV: (Open, High, Low, Close, Volume) data
I use yahoo finance python API — yfinance to get the data. There are a lot of resources to get historical data in order to backtest your strategies.

[*********************100%***********************] 1 of 1 completed

Step 3: Calculate daily returns
This step calculates daily returns for comparing performance with the buy and hold strategy. A buy and hold strategy becomes a benchmark or comparing the strategy. In other words, it checks if the strategy performed better than simply buying and holding the stock. A good strategy would essentially perform better than a buy-and-hold strategy.

png

Step 4: Create strategy-based data columns
The next step is to create indicators to generate conditions of the strategy. For Bollinger band strategy, involves the 20-day moving average, the standard deviation of the 20 days moving average, upper band, and lower band of the standard deviation. [ma20,std,upper_band,lower_band]

png

Step 5: Create strategy indicators
The following is the most crucial part of creating the strategy. It involves

  • generating long and short signals as mentioned in the strategy
  • replacing zeros with forwarding fill, to generate long and short positions
  • shifting positions by 1 to signify return calculations done from close of a day to the next day close price

Signals are essentially indicators that signify the action that needs to be taken (ie: to buy or sell). Positions are what you maintain after buying or selling (ie: going long or short).

png

Step 6: Create signals and positions
The next step is to compare the strategy performance using cumulative returns.
This involves element-wise multiplication of the positions with the daily returns.

Buy and hold returns: 1.4441301364703079
Strategy returns: 0.3712255745848457

<AxesSubplot:xlabel='Date'>
png

Step 7: Analyze results

For this step I use pyfolio. Pyfolio is a Python library for performance and risk analysis of financial portfolios

pf.create_simple_tear_sheet(df['strategy_returns'].diff())
pyfolio results
png

Comments
The results from pyfolio are self-explanatory.

The ‘Bollinger band’ strategy on the historical data did not perform better than the buy & hold strategy. The cumulative daily returns for buy and hold accounts for 1.44 times the initial investment and the Bollinger band strategy returns account for 0.37 times the initial investment.

For obvious reasons, one should not take a strategy live, even if it gives great returns on back-testing. There are various risks involved such as not accounting for transaction costs and momentum in stock price.

The performance of a strategy can also be optimized by checking the returns on various strategy parameters.

Various other technical indicators can be used in conjunction to create signals which can reduce risks and improve performance. Live strategies should implement stop loss and kill switches in case the strategy goes of hand.

This code snippet can be found at: https://github.com/karthikramx/Algorithmic-Trading-Backtesting-python-example