Python - Draw zigzag trendline of stock prices

By xngo on June 18, 2019

In Python, to draw a zigzag trendline of stock prices, you need to first find the peak and valley values of the chart. This can be done by using scipy.signal.argrelextrema() function. Then, you have to combine them together and sort them in chronological order. After this, you end up forming a zigzag trendline. The code below show you how to draw a zigzag trendline of Apple stock prices. It is assumed that you have the following libraries installed on your computer:

  • numpy: pip install numpy
  • matplotlib: pip install matplotlib
  • pandas: pip install pandas
  • scipy: pip install scipy

The code

#!/usr/bin/python3
import matplotlib
matplotlib.use('Agg') # Bypass the need to install Tkinter GUI framework
 
# Avoid FutureWarning: Pandas will require you to explicitly register matplotlib converters.
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
 
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
 
import pandas as pd
 
# Load data from CSV file.
##########################
my_headers = ['date', 'open', 'high', 'low', 'close', 'volume']
my_dtypes = {'date': 'str', 'open': 'float', 'high': 'float', 'low': 'float', 
                                                'close': 'float', 'volume': 'int'}
my_parse_dates = ['date']
loaded_data = pd.read_csv('apple.csv', sep='\t', header=1, names=my_headers, 
                            dtype=my_dtypes, parse_dates=my_parse_dates)
 
 
# Convert 'Timestamp' to 'float'.
#   Need time be in float days format - see date2num.
loaded_data['date'] = [mdates.date2num(d) for d in loaded_data['date']]
 
# Re-arrange so that each line contains values of a day: 'date','open','high','low','close'.
quotes = [tuple(x) for x in loaded_data[['date','open','high','low','close']].values]
 
 
# Create zigzag trendline.
########################################
# Find peaks(max).
data_x = loaded_data['date'].values
data_y = loaded_data['close'].values
peak_indexes = signal.argrelextrema(data_y, np.greater)
peak_indexes = peak_indexes[0]
 
# Find valleys(min).
valley_indexes = signal.argrelextrema(data_y, np.less)
valley_indexes = valley_indexes[0]
 
# Instantiate axes.
(fig, ax) = plt.subplots()
 
# Merge peaks and valleys data points using pandas.
df_peaks = pd.DataFrame({'date': data_x[peak_indexes], 'zigzag_y': data_y[peak_indexes]})
df_valleys = pd.DataFrame({'date': data_x[valley_indexes], 'zigzag_y': data_y[valley_indexes]})
df_peaks_valleys = pd.concat([df_peaks, df_valleys], axis=0, ignore_index=True, sort=True)
 
# Sort peak and valley datapoints by date.
df_peaks_valleys = df_peaks_valleys.sort_values(by=['date'])
 
# Plot zigzag trendline.
ax.plot(df_peaks_valleys['date'].values, df_peaks_valleys['zigzag_y'].values, 
                                                        color='red', label="zigzag")
 
# Plot close price line.
ax.plot(data_x, data_y, linestyle='dashed', color='black', label="Close Price", linewidth=1)
 
 
# Customize graph.
##########################
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Apple share prices - ZigZag trendline')
 
# Format time.
ax.xaxis_date()
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
 
plt.gcf().autofmt_xdate()   # Beautify the x-labels
plt.autoscale(tight=True)
 
plt.legend(loc='best')
plt.grid(True, linestyle='dashed')
 
# Save graph to file.
plt.savefig('argrelextrema-zigzag.png')

Output

Output zigzag trendline

apple.csv sample data

date open    high    low close   volume
2001-01-02  1.062500    1.089286    1.040179    1.062500    113078000
2001-01-03  1.035714    1.191964    1.031250    1.169643    204268400
2001-01-04  1.295757    1.321429    1.200893    1.218750    184849000
2001-01-05  1.209821    1.241071    1.147321    1.169643    103089000
2001-01-08  1.209821    1.213164    1.138393    1.183036    93424800

About the author

Xuan Ngo is the founder of OpenWritings.net. He currently lives in Montreal, Canada. He loves to write about programming and open source subjects.