title: ZigZag indicator in Python
body: <p>I would like to create a zigzag indicator for stocks. I'm working with python and my english is bad so my appologies for that.
  I took part of my code from: <a href="https://stackoverflow.com/questions/59559788/pandas-zigzag-segmentation-of-data-based-on-local-minima-maxima">Pandas: Zigzag segmentation of data based on local minima-maxima</a></p>
  
  <p>The problem is the zigzag I would like is this (Metastock zigzag indicator):
  <a href="https://i.stack.imgur.com/2NW2O.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/2NW2O.png" alt="enter image description here"></a>
  And my zigzag code looks like(note you can change the percent with a filter):
  <a href="https://i.stack.imgur.com/21zDH.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/21zDH.png" alt="enter image description here"></a></p>
  
  <pre><code>from pandas_datareader import data
  import pandas as pd
  from datetime import date
  from pandas_datareader.nasdaq_trader import get_nasdaq_symbols
  from scipy import signal
  import pandas as pd
  import numpy as np
  import matplotlib.pyplot as plt
  import matplotlib.dates as mdates
  np.random.seed(0)
  
  def filter(values, percentage):
      previous = values[0] 
      mask = [True]
      for value in values[1:]: 
          relative_difference = np.abs(value - previous)/previous
          if relative_difference &gt; percentage:
              previous = value
              mask.append(True)
          else:
              mask.append(False)
      return mask
  
  
  def main(stock=None, start_date=None, end_date=None):
      df = data.DataReader(
          stock, 
          start=start_date, end=end_date,
          data_source='yahoo'
      )
      return df
  
  
  if __name__ == '__main__':
      today = '{}'.format(date.today())
      stocks = ['BLL']
      cont = 0
      for stock in stocks:
          cont += 1
          try:
              serie = main(stock=stock, start_date='2018-1-1', end_date=today)
              serie.insert(loc=0, column='Date', value=serie.index)
              serie = serie.reset_index(drop=True)
              # Create zigzag trendline.
              ########################################
              # Find peaks(max).
              data_x = serie.index.values
              data_y = serie['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]          
              # 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'])
              p = 0.1 # 20% 
              filter_mask = filter(df_peaks_valleys.zigzag_y, p)
              filtered = df_peaks_valleys[filter_mask]
  
               # Instantiate axes.
              (fig, ax) = plt.subplots(figsize=(10,10))
              # Plot zigzag trendline.
              ax.plot(df_peaks_valleys['date'].values, df_peaks_valleys['zigzag_y'].values, 
                                                                      color='red', label="Extrema")
              # Plot zigzag trendline.
              ax.plot(filtered['date'].values, filtered['zigzag_y'].values, 
                                                                      color='blue', label="ZigZag")
              # Plot original line.
              ax.plot(data_x, data_y, linestyle='dashed', color='black', label="Org. line", linewidth=1)
              plt.show()
              print('{} - {}| success'.format(cont, stock))
          except Exception:
              print('{} - {}| ERROR'.format(cont, stock))
  </code></pre>