Algorithmic Trading: backtesting your algorithm
Tags: algotrading, investing, automation, python
Published: 2020-02-06 16:20:23

As I wrote in my previous article, [Algorithmic Trading: algorithms to beat the market](https://medium.com/@mrodz/algorithmic-trading-algorithms-to-beat-the-market-200c61ad84fc), if you are into writing code to buy and sell stocks, options, forex or whatnot, it's very important to consider backtesting your code.

## What is Backtesting?

Backtesting a trading algorithm means to run the algorithm against historical data and study its performance.

From [Investopedia](https://www.investopedia.com/terms/b/backtesting.asp):
> # Backtesting is the general method for seeing how well a strategy or model would have done ex-post. Backtesting assesses the viability of a trading strategy by discovering how it would play out using historical data. If backtesting works, traders and analysts may have the confidence to employ it going forward.

As an example, I’m going to share some lines of code on how to download minute data from 2016.

Next, we’ll do a simple custom backtest script.

## Open an Alpaca Account

First, we’ll need an Alpaca paper account. Head to [Alpaca](https://app.alpaca.markets/signup) and open a free account.

Next, log in to your Alpaca account and find or generate your API keys.

I like to create a file just to save this information.

So create a file alpaca_conf_paper.py to save our Alpaca API Keys for the paper account.

<iframe src="https://medium.com/media/626eb03462bdbbc42f76a827f832a234" frameborder=0></iframe>

## Installing Python dependencies

Let’s install Alpaca’s Python SDK and other dependencies:

* alpaca-trade-api is Alpaca’s Python SDK

* tqdm is a very nice library that will show a progress bar.

* pandas a great “library providing high-performance, easy-to-use data structures, and data analysis tools for [Python](https://www.python.org/)”

In your console, run:

    pip3 install alpaca-trade-api tqdm pandas

## Downloading data

It’s very easy to download data from Alpaca.

Let’s say we want data for a day, grouped by minutes. We can do this with a very simple script. I tried to make it very explicit.

Create a file named download_data.py and paste this code:

<iframe src="https://medium.com/media/b16b3c4cb373c9279b56cab9a79b4bca" frameborder=0></iframe>

If you run the code as-is, running python3 download_data.py will download OHLC minute data for AAPL for all 252 trading days of 2016 to your `../historical-market-data/` directory, in `CSV` format.

It looks like this in my WSL (Linux) console:

    $ ls ../historical-market-data/*AAPL*2016*
    AAPL-2016-01-04.csv  AAPL-2016-02-12.csv  AAPL-2016-03-24.csv  ...

    $ ls ../historical-market-data/*AAPL*2016* | wc
        252     252    5040

## Our first backtesting script

To backtest an algorithm we first need to have an algorithm. Since we don’t have one yet we just going to assume a “buy and hold” strategy.

Let’s start by seeing how well a buy & hold strategy looked for AAPL in 2016: buying the first day of the year and selling the last day.

To test a “buy and hold” strategy, we need to calculate the ratio of the last price of the year (when we would have sold) and the first price of the year (when we would have bought).

That is, 
```
profit_pc = price_last_day)/price_first_day
```

Below is a script that does just that.

If you want to run it, create a file named `backtest_buy_and_hold.py` with this content:

<iframe src="https://medium.com/media/adc58f932e798e30a12640cfd8999247" frameborder=0></iframe>

If we run the script, we get:

    $ python3 backtest-buy-and-hold.py
    AAPL's 2016's Buy-n-Hold strategy return profit is: 1.099

Which means that during 2016, AAPL grew 9.9%. [This checks out](https://finance.yahoo.com/chart/AAPL#eyJpbnRlcnZhbCI6ImRheSIsInBlcmlvZGljaXR5IjoxLCJjYW5kbGVXaWR0aCI6My45ODgwOTUyMzgwOTUyMzgsInZvbHVtZVVuZGVybGF5Ijp0cnVlLCJhZGoiOnRydWUsImNyb3NzaGFpciI6dHJ1ZSwiY2hhcnRUeXBlIjoibGluZSIsImV4dGVuZGVkIjpmYWxzZSwibWFya2V0U2Vzc2lvbnMiOnt9LCJhZ2dyZWdhdGlvblR5cGUiOiJvaGxjIiwiY2hhcnRTY2FsZSI6ImxpbmVhciIsInBhbmVscyI6eyJjaGFydCI6eyJwZXJjZW50IjoxLCJkaXNwbGF5IjoiQUFQTCIsImNoYXJ0TmFtZSI6ImNoYXJ0IiwidG9wIjowfX0sImxpbmVXaWR0aCI6Miwic3RyaXBlZEJhY2tncm91ZCI6dHJ1ZSwiZXZlbnRzIjp0cnVlLCJjb2xvciI6IiMwMDgxZjIiLCJldmVudE1hcCI6eyJjb3Jwb3JhdGUiOnsiZGl2cyI6dHJ1ZSwic3BsaXRzIjp0cnVlfSwic2lnRGV2Ijp7fX0sImN1c3RvbVJhbmdlIjp7InN0YXJ0IjoxNDUxODgzNjAwMDAwLCJlbmQiOjE0ODMwNzQwMDAwMDB9LCJzeW1ib2xzIjpbeyJzeW1ib2wiOiJBQVBMIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkFBUEwifSwicGVyaW9kaWNpdHkiOjEsImludGVydmFsIjoiZGF5IiwidGltZVVuaXQiOm51bGx9LHsic3ltYm9sIjoiVk9PIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IlZPTyJ9LCJwZXJpb2RpY2l0eSI6MSwiaW50ZXJ2YWwiOiJkYXkiLCJ0aW1lVW5pdCI6bnVsbCwiaWQiOiJWT08iLCJwYXJhbWV0ZXJzIjp7ImNvbG9yIjoiIzcyZDNmZiIsIndpZHRoIjoyLCJpc0NvbXBhcmlzb24iOnRydWUsImNoYXJ0TmFtZSI6ImNoYXJ0Iiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IlZPTyJ9LCJwYW5lbCI6ImNoYXJ0IiwiYWN0aW9uIjpudWxsLCJzaGFyZVlBeGlzIjp0cnVlLCJzeW1ib2wiOiJWT08iLCJnYXBEaXNwbGF5U3R5bGUiOiJ0cmFuc3BhcmVudCIsIm5hbWUiOiJLNUE0SkkxQzg3Iiwib3ZlckNoYXJ0Ijp0cnVlLCJ1c2VDaGFydExlZ2VuZCI6dHJ1ZSwiaGVpZ2h0UGVyY2VudGFnZSI6MC43LCJvcGFjaXR5IjoxLCJoaWdobGlnaHRhYmxlIjp0cnVlLCJ0eXBlIjoibGluZSIsInN0eWxlIjoic3R4X2xpbmVfY2hhcnQifX0seyJzeW1ib2wiOiJGVEVDIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkZURUMifSwicGVyaW9kaWNpdHkiOjEsImludGVydmFsIjoiZGF5IiwidGltZVVuaXQiOm51bGwsImlkIjoiRlRFQyIsInBhcmFtZXRlcnMiOnsiY29sb3IiOiIjYWQ2ZWZmIiwid2lkdGgiOjIsImlzQ29tcGFyaXNvbiI6dHJ1ZSwiY2hhcnROYW1lIjoiY2hhcnQiLCJzeW1ib2xPYmplY3QiOnsic3ltYm9sIjoiRlRFQyJ9LCJwYW5lbCI6ImNoYXJ0IiwiYWN0aW9uIjpudWxsLCJzaGFyZVlBeGlzIjp0cnVlLCJzeW1ib2wiOiJGVEVDIiwiZ2FwRGlzcGxheVN0eWxlIjoidHJhbnNwYXJlbnQiLCJuYW1lIjoiSzVBNE1ORzVBMCIsIm92ZXJDaGFydCI6dHJ1ZSwidXNlQ2hhcnRMZWdlbmQiOnRydWUsImhlaWdodFBlcmNlbnRhZ2UiOjAuNywib3BhY2l0eSI6MSwiaGlnaGxpZ2h0YWJsZSI6dHJ1ZSwidHlwZSI6ImxpbmUiLCJzdHlsZSI6InN0eF9saW5lX2NoYXJ0In19LHsic3ltYm9sIjoiViIsInN5bWJvbE9iamVjdCI6eyJzeW1ib2wiOiJWIn0sInBlcmlvZGljaXR5IjoxLCJpbnRlcnZhbCI6ImRheSIsInRpbWVVbml0IjpudWxsLCJpZCI6IlYiLCJwYXJhbWV0ZXJzIjp7ImNvbG9yIjoiI2ZmYmQ3NCIsIndpZHRoIjoyLCJpc0NvbXBhcmlzb24iOnRydWUsImNoYXJ0TmFtZSI6ImNoYXJ0Iiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IlYifSwicGFuZWwiOiJjaGFydCIsImFjdGlvbiI6ImFkZC1zZXJpZXMiLCJzaGFyZVlBeGlzIjp0cnVlLCJzeW1ib2wiOiJWIiwiZ2FwRGlzcGxheVN0eWxlIjoidHJhbnNwYXJlbnQiLCJuYW1lIjoiSzVBRTBBWUZTOSIsIm92ZXJDaGFydCI6dHJ1ZSwidXNlQ2hhcnRMZWdlbmQiOnRydWUsImhlaWdodFBlcmNlbnRhZ2UiOjAuNywib3BhY2l0eSI6MSwiaGlnaGxpZ2h0YWJsZSI6dHJ1ZSwidHlwZSI6ImxpbmUiLCJzdHlsZSI6InN0eF9saW5lX2NoYXJ0In19XSwicmFuZ2UiOnsiZHRMZWZ0IjoiMjAxNi0wMS0wMlQwNTowMDowMC4wMDBaIiwiZHRSaWdodCI6IjIwMTYtMTItMzFUMDU6MDA6MDAuMDAwWiIsInBlcmlvZGljaXR5Ijp7ImludGVydmFsIjoiZGF5IiwicGVyaW9kIjoxfSwicGFkZGluZyI6MH0sInRpbWVVbml0IjpudWxsLCJzdHVkaWVzIjp7InZvbCB1bmRyIjp7InR5cGUiOiJ2b2wgdW5kciIsImlucHV0cyI6eyJpZCI6InZvbCB1bmRyIiwiZGlzcGxheSI6InZvbCB1bmRyIn0sIm91dHB1dHMiOnsiVXAgVm9sdW1lIjoiIzAwYjA2MSIsIkRvd24gVm9sdW1lIjoiI0ZGMzMzQSJ9LCJwYW5lbCI6ImNoYXJ0IiwicGFyYW1ldGVycyI6eyJ3aWR0aEZhY3RvciI6MC40NSwiY2hhcnROYW1lIjoiY2hhcnQifX19fQ%3D%3D):

![AAPL grew 9.9% during 2016](https://cdn-images-1.medium.com/max/2124/1*XNjM49HKafkEXiV0d2wJuQ.png)*AAPL grew 9.9% during 2016*

So, great! We did our first backtesting script for a trivial strategy.

## Fancier strategies

As mentioned in my previous article, there are many strategies:
- Buy and Hold
- Mean reversion
- Scalping
- Fading
- Daily pivots
- Momentum
- Many, many other

In [my next article](https://medium.com/@mrodz/algo-trading-backtesting-an-intraday-scalping-strategy-with-a-simple-custom-script-fcd15642555) I’ll post some code that uses all we’ve built here, and extend the backtesting script to test a simple scalping algorithm.

See you next time!