Understanding the ADX Indicator using Python

ADX

Many seasoned swing traders use the ADX indicator to gauge the stock market’s momentum. ADX stands for Average Directional Index, and it helps determine the strength of the underlying trend.

In this article, we will learn about the ADX indicator and how it works. We will also look at the Python implementation of this indicator in the Python programming language.

Recommended: (3/5) Relative Strength Index (RSI): A Powerful Trading Indicator Implemented in Python

Recommended: (4/5) MACD Indicator: Python Implementation and Technical Analysis

What is the ADX indicator?

As mentioned before, the ADX indicator tells us about the strength of a trend. It is also one of the directional movement indicators, just like the Simple Moving Average (SMA) and Exponential Moving Average ( EMA ). It is very easy to understand that a rising line indicates that the stock is rallying and going on a bull run, whereas a dropping or falling line indicates that the stock is weakening and going on a bearish run. Let us look at the ADX indicator to understand it further.

ADX Indicator
ADX Indicator

You can see that ADX tends to go on a bull run when it crosses a certain limit. In the above image, the black dotted line is the limit, which ranges from 20 to 70. Between the values of 20 and 70, the stock is said to move sideways; below 20, it is said to buy the stock, and above 70, it is advised to sell it. Let us now move on to the Python implementation of the indicator.

Implementing ADX in Python

import numpy as np
import matplotlib.pyplot as plt

def generate_stock_prices(num_prices=100, initial_price=100, volatility=0.05):
    prices = [initial_price]
    for _ in range(1, num_prices):
        price_change = np.random.normal(0, volatility)
        prices.append(prices[-1] + price_change * prices[-1])
    return prices

In the above block, we have imported the required libraries and generated random stock prices to plot them using matplotlib.

def calculate_directional_movement(prices):
    dm_pos = []
    dm_neg = []
    for i in range(1, len(prices)):
        price_diff = prices[i] - prices[i - 1]
        if price_diff > 0:
            dm_pos.append(price_diff)
            dm_neg.append(0)
        elif price_diff < 0:
            dm_pos.append(0)
            dm_neg.append(-price_diff)
        else:
            dm_pos.append(0)
            dm_neg.append(0)
    return dm_pos, dm_neg

We have calculated the ADX value by using the difference of consecutive prices. This difference is adjusted on the basis of certain parameters ( directional index ) and the same process is repeated for every consecutive pair of prices.

def calculate_true_range(prices):
    true_ranges = []
    for i in range(1, len(prices)):
        high_low = prices[i] - prices[i - 1]
        high_close = abs(prices[i] - prices[i - 1])
        low_close = abs(prices[i] - prices[i - 1])
        true_ranges.append(max(high_low, high_close, low_close))
    return true_ranges

def calculate_directional_index(dm_pos, dm_neg, true_ranges, window):
    atr = [np.mean(true_ranges[:window])]
    di_pos = [np.mean(dm_pos[:window])]
    di_neg = [np.mean(dm_neg[:window])]
    for i in range(window, len(dm_pos)):
        atr.append((atr[-1] * (window - 1) + true_ranges[i]) / window)
        di_pos.append((di_pos[-1] * (window - 1) + dm_pos[i]) / window)
        di_neg.append((di_neg[-1] * (window - 1) + dm_neg[i]) / window)
    di_pos = np.array(di_pos)
    di_neg = np.array(di_neg)
    dx = np.abs((di_pos - di_neg) / (di_pos + di_neg)) * 100
    adx = [np.mean(dx[:window])]
    for i in range(window, len(dx)):
        adx.append((adx[-1] * (window - 1) + dx[i]) / window)
    return adx

We calculate the difference between the high and close of the day to calculate the directional index. We then adjust the ADX value calculated in the previous step with the directional index to complete the process of calculating the ADX indicator value.

# Generate stock prices
stock_prices = generate_stock_prices()

# Calculate ADX
window = 14  # ADX window
dm_pos, dm_neg = calculate_directional_movement(stock_prices)
true_ranges = calculate_true_range(stock_prices)
adx = calculate_directional_index(dm_pos, dm_neg, true_ranges, window)

# Plotting
plt.figure(figsize=(12, 6))
plt.subplot(2, 1, 1)
plt.plot(stock_prices, label='Stock Prices')
plt.title('Stock Prices')
plt.legend()

plt.subplot(2, 1, 2)
plt.plot(adx, label='ADX', color='red')
plt.axhline(y=20, color='gray', linestyle='--')
plt.axhline(y=50, color='gray', linestyle='--')
plt.axhline(y=70, color='gray', linestyle='--')
plt.title('ADX')
plt.legend()

plt.show()

Finally, we decide on the window of price points, generally 14, and then plot the whole thing using matplotlib. Let us look at the output of the above code.

ADX Indicator Output
ADX Indicator Output

The stock price has consistently been in a bearish trend, as the ADX line is below 20. It is advised to buy the stock as it will rise because it has reached its low and will rally up.

Conclusion

You now understand how the ADX indicator functions and how to implement it in Python to gauge the strength of market trends. The ability to discern between different market conditions using the ADX can significantly enhance your trading strategies. What other indicators could be combined with the ADX to further refine your market analysis and decision-making processes?

Recommended: (1/5) Understanding Technical Analysis and Indicators using Python

Recommended: (2/5) Moving Average Crossover Strategy: Python Implementation