How to code a backtest?

Because I love programming since my first experiences at the age of six I wanted to explain you how you can code your own backtests.

Did you find a signal you would like to know how it worked in the past 20 years?
We do that know together!

First the candlesticks

At first we need the candlestick data with date, open, high, low, close and volume of each day.
You can get the data from your broker, for example through the API of Interactive Brokers or the csv-file export of TC2000, or you use one of the free or cheap APIs (IEX, Quandl, …).
For our example you can download the needed data here.

… and the import in your program

Now you’re thinking: Hey, I didn’t code anything yet! No problem, it’s not that difficult.
I know many coding languages like JavaScript or PHP but after programming my tools for stocks and trading around 5 years I can recommend to you:

The best language for programming with financial data is Python!

Let’s start our example with the SPY, daily candles and a simple moving average crossing strategy.

To read the data of our source file (SPY.csv, located in the same folder), we just need write this line into a text file named “backtest.py”:

data = pd.read_csv("SPY.csv")

The “pd” stands for pandas, a library for data calculations and comparison which we have to integrate in our code before the line above:

import pandas as pd

To check the data by printing the last 5 rows/days on the screen we can add

print(data.tail())

The strategy

The simple moving average over 200 days (200 SMA) for all rows can be calculated by

data['SMA200'] = data.Close.rolling(200).mean()

and to check if the close is above the SMA 200 just type

data['above']  = data.Close > data.SMA200

Now we have 2 new columns with ‘SMA200‘ and ‘above‘ in our dataset. We will add three more for the “not above” and for the buy and sell signal when crossing (- stands for not and here we have to use & instead of and):

data['notabove'] = -data.above
data['buy']  = data.above & data.notabove.shift(1)
data['sell'] = data.notabove & data.above.shift(1)

Checking each day with one loop

The ‘shift‘ moves a column one row up (shift(-1)) or down (shift(1)), so here we can compare with the day before.
But how to code the backtest for every row of data? While iterating through the rows, we invest at the buy signal and close the position at the sell signal while setting the variable invest true or false:

total_return = 0.0
invested = False
for index, row in data.iterrows():
    if row.buy and not invested:
        entry = row.Close
        invested = True
    if row.sell and invested:
        exit = row.Close
        trade_return = exit/entry - 1
        total_return += trade_return
        invested = False

Show our result

And finally we just have to output the total return:

print("Total return from", data.index[0], "to", data.index[-1], "is", round(total_return*100, 2), "%.")

Now you start our program with this command – and hopefully the same output if you used the source file of the above link:

>> python3 backtest.py
Total return from 1993-01-29 to 2019-10-08 is 172.33 %.

Therefore you had profits of 172.33% if you invested the same amount with our buy signal since 1993. It’s not difficult to change it to the cumulative return or to compare with a buy & hold strategy.

If there are any questions, experiences or wishes about how to code a backtest I would like to read your comment below. I wish you good results with your code, fun with many combinations and a strategy that fits best to you!

Alexander

Alexander bought his first stock in October 2009 without knowing about the luck for this point of time. In 2016 he started to trade, since 2017 he notes down watchlists and statistics every day and because he knows how to code since he was a child, he uses Python, PHP, HTML5 and JS for making the daily to-dos easier. Because many of his friends wanted him not to stop writing about the markets he started this blog to share his ideas and tools.

2 Comments

  • dear Alexander,

    could you explain, why (and “if”) it is important to forward test a strategy which showed positive results in the backtest? And if yes, for how long should the forward test last?

    And could you explain the concept of “curve fitting” in simple words?

    • Because I did many backtests but I am not an expert for backtesting and working strategies yet, I can only write my opinion:

      1. Why forward test?
      All kinds of strategy tests can only cover an area and not the whole scope of a strategy. Therefore I recommend to use all possibilities to test a strategy before trading it. And therefore after backtesting a collection of contracts in a period of time you should trade it in a paper account for some months. Why? Then you can compare your statistics of the paper trades with those of your backtests. If the two kinds of tests will give you the same conclusions and results there’s a higher probability of being successful with your strategy.

      2. How long to forward test?
      How long did you backtest? 10 years? 20 years? If you tested daily candles you should have tested about 500 or more rows of data and maybe 300 to 1000 trades. How many trades should you trade to compare the forward test with your backtest? Several hundreds.
      But of course, you will recognize after 50-100 trades when the forward test is running in another direction than you expected. So, you can just start with your forward test and decide when you’re confident that results in live trading will be as expected.

      3. Curve fitting
      Simple words? Uh, I will try: If you change your conditions for a backtest to get perfect results you have to pay attention on not changing too many details because your past trades do not cover the whole scope of possible trades. But when it’s the improvement of a strategy and when it’s curve fitting? Nobody knows. But you can take several areas maybe stocks of different sectors or some stocks and compare the results of this section with the whole backtest. It’s a good sign when everything follows the same rules and results. Or you forward test (see (2)) your strategy and compare those results with your backtest.

      I hope now you understand the details of backtests, forward tests and curve fitting much better?

Leave a Reply

Your email address will not be published. Required fields are marked *