# How I Build A Profitable ATR-Based Trading Strategy With Python

In this tutorial, we will implement a trading strategy using the ATR indicator. The first part will explain this indicator. Then, we will show a practical example in Python using the SPY data. Throughout this tutorial, we will implement various Python functions. This is **how I build a profitable ATR-based trading strategy with Python**.

**Related reading:**

**Looking for a good, robust, and profitable trading strategy? (Hundreds in that link)**- ….
**and a few trading strategies for sale** **Plenty examples of profitable and robust Python trading strategies**

**Average True Range**

ATR is a volatility indicator that captures how much fluctuates the price in a day. It aims to identify periods with high uncertainty.

To calculate the ATR, the maximum, minimum, and closing prices are necessary. We calculate the True Range (TR) as follows:

Where:

H = Maximum price of the day

L = Minimum price of the day

= Previous day’s closing price

With the previous result, the ATR is:

The first ATR value is:

**Practical Example in Python**

Let’s show you how I build a profitable ATR-based trading strategy with Python.

**Data and Financial instruments**

In this tutorial, we will use the following financial instruments:

The start and end periods of our analysis are “2021-01-01” and “2023-10-23″, respectively.

**Data Download and Analysis:**

As in our previous tutorials, we first import the Python libraries:

Next, we download the data using the following function:

The function * download_data* takes three arguments:

*,*

**stock_name***, and*

**start***. In the function body, we download the data, and finally, the variable*

**end***is returned.*

**data**The implementation and results of the previous function are:

**ATR Implementation**

We will use the * ta* library to calculate the ATR. The following image shows the

*function, which takes two parameters:*

**get_atr***and*

**data***. Inside the function, the*

**window***method from the*

**AverageTrueRange****ta**package estimates the Average True Range. Finally, the variable

*containing the data of this indicator is returned.*

**atr**In the previous image, you can also see the implementation of * get_atr* with its first five results; note that the ATR has a 14-day window length.

In the following image, you can see the function that calculates the 14-day SMA using values from result[“ATR”]:

**Price and ATR Chart**

This section involves plotting both the closing price and ATR to draw insight from our data. We will plot the closing price at the top and ATR below it.

The following image shows the * plot_data* function, which has two parameters:

*and*

**data***. Inside the function, you can see*

**ticker***, the first two arguments indicate we want the two graphs in a vertical orientation. The*

**plt.subplots(2, 1, gridspec_kw={‘height_ratios’: [3, 1]})***indicates that the first graph is three times larger than the second one. The*

**height_ratios***expression is used to hide the horizontal axis in the first graph. We have explained the other commands in other tutorials:*

**NullFormatter()**- How I Made a Weighted Moving Average Trading Strategy Using Python (Rules, Backtest)
- How to Build a Simple SMA Trading Strategy Using Python

Implementing * plot_data* with parameters

*and*

**result***yields the following:*

**stock_name**The image above shows high volatility throughout 2022, with periods of sharp price increases and decreases. When we observe the ATR series, we can see the highest values in the same period.

In addition, in the previous image, we computed a 14-day SMA with the ATR values, an essential component to find periods of high price variation. It is possible to observe that every time the ATR surpasses SMA, it is likely a sharp increase or decrease in the price.

**Backtesting the ATR Trading Strategy**

One of the key components of backtesting our strategy is the signals. The signals show the time for having a long or short position. To obtain these signals, we express the following trading rules.

## Trading Rules

The primary purpose of this article is to show how it can be done, e.g., codingwise, so the strategy is primarily for illustrative purposes.

**Trading Rules – Buy:**

- When the closing price is higher than the closing price of the previous three days, and ATR is higher than its 14-day historical average.

**Trading Rules – Sell:**

- When the closing price is lower than the closing price of the previous three days, and ATR is higher than its 14-day historical average.

The idea is simple: when ATR is higher than its SMA, it shows a sudden price movement. Meanwhile, the price change of the last 5 days identifies the trend, whether the price is decreasing or increasing.

In the following image, to estimate its function, a loop is necessary to get, for each day, the closing price, the closing price of the previous 5 days, and the ATR value.

The following image shows the * get_signals* function, which takes two arguments:

*and*

**data***. Inside the function, the first step is to get the positions of the columns*

**size***,*

**Close***, and*

**ATR***with*

**ATR_SMA***. Then, the variable*

**.get_loc***is created, showing a long position with 1 and a short position with -1. Subsequently, we create the*

**signal_***to record buy or sell operations. Inside the loop, you can see how the first*

**values_list***values are skipped. Then, the difference between closing prices,*

**size***(in the example*

**price_diff***, meaning three days) is calculated. Next, the ATR values and their averages in*

**size=3***and*

**atr_value***are obtained. It’s important to remember that*

**atr_sma_value***means that we will find the value located in row*

**.iloc[i, patr]***with column*

**i***. Then, we implement the conditions*

**patr****price_diff < 0 and atr_value > atr_sma_value**and

*, indicating a buy*

**price_diff > 0 and atr_value > atr_sma_value***and a short position*

**(signal_=1)***, respectively.*

**(signal_=-1)****Getting Returns and Results**

The following image shows the return calculations, and plots them:

We explained the previous code in another article. You can find examples with similar codes in the following articles:

- How to Build a Simple SMA Trading Strategy Using Python
- How I Made a Weighted Moving Average Trading Strategy Using Python (Rules, Backtest)

The equity curve of the strategy looks like this (for SPY):

Our strategy generates a cumulative return of approximately 50%, which is higher than the return obtained from SPY. Similarly, our strategy’s returns grow steadily over time with less variation.

**The same Strategy for Four ETFs**

In this section, we will explore the utility of the functions created in Python. First, we create another function:

If we compare the * equity_curve_2* function with

*, we see they are similar but not identical. The new function uses*

**equity_curve****plt.plot**which plots multiple graphs on one chart.

The following image implements the previously created functions. First, we make a list with four ETFs. Inside the loop, we add the functions. Notice how we need only a few lines of code to obtain results for four ETFs.

Using the functions created, we can automatize the task of plotting the equity curve in less time and with fewer lines of code. You can add 10 or more financial tickers and analyze them with the previous function.

The following image shows the equity curve for the four ETFs: