← Back to Home
Significant Turning Points with Zig Zag Indicator in Python

Significant Turning Points with Zig Zag Indicator in Python

Financial markets are dynamic, with prices constantly moving. This activity creates a complex picture, often filled with “noise” – minor fluctuations that can obscure the underlying direction and significant turning points. Technical analysts use various tools to filter this noise and gain clarity. The Zig Zag indicator is one such tool, designed to highlight significant price swings by ignoring smaller movements.

This article delves into a Python script that automates the process of applying the Zig Zag indicator. We’ll explore how it uses libraries like yfinance, pandas, numpy, and mplfinance to fetch data, calculate Zig Zag points, and plot them onto a clear candlestick chart. We will break down the code with snippets and explain the Zig Zag indicator conceptually and its practical applications.

1. Understanding the Zig Zag Indicator

What it is: The Zig Zag indicator is primarily a trend filtering tool. It doesn’t predict future prices but rather helps simplify past price action by connecting significant peaks (highs) and troughs (lows) on a chart.

How it works (Conceptually): Imagine drawing lines on a price chart, but only changing direction when the price moves significantly against the current trend. The Zig Zag indicator does this by establishing a minimum price movement threshold (often a percentage, but sometimes fixed points).

Key Parameter: The reversal threshold (represented as sigma in our script) is crucial.

Visual Representation: Typically, it’s drawn as a series of straight lines connecting alternating, confirmed peaks and troughs directly on the price chart. Our script focuses on marking the peak/trough points themselves.

2. Why Use the Zig Zag Indicator? (Usefulness)

The Zig Zag indicator is valuable for several analytical purposes:

Important Note: The Zig Zag indicator is based on past data and requires a certain amount of price movement after a peak or trough to confirm it. Therefore, the most recent line segment or point is subject to change (repaint) until confirmed by a sufficient reversal. It’s an analytical tool, not typically used for generating direct entry/exit signals in isolation.

3. The Python Implementation: A Code Walkthrough

Let’s break down how the provided Python script implements the Zig Zag calculation and visualization.

3.1 Setting Up the Environment

The script starts by importing the necessary libraries and setting up basic logging:

Python

#!/usr/bin/env python3
import logging
from typing import List, Tuple, Optional # For type hinting

import matplotlib.pyplot as plt # Base plotting library
import mplfinance as mpf        # Financial charting
import numpy as np             # Numerical operations (arrays)
import pandas as pd            # Data manipulation (DataFrames)
import yfinance as yf          # Downloading market data

# --- Setup logging ---
logging.basicConfig(
    level=logging.INFO, # Set minimum level of messages to show
    format='[%(asctime)s] %(levelname)s: %(message)s' # Message format
)

This setup ensures all required tools are available and provides informative output during execution.

3.2 Fetching Market Data

The script fetches historical OHLC (Open, High, Low, Close) data using yfinance within the main execution block:

Python

if __name__ == '__main__':
    # --- Configuration for the run ---
    TICKER = 'BTC-USD'  # Example: Bitcoin USD
    PERIOD = '1mo'     # Example: Data for the last 1 month
                         # Other options: '1y', '6mo', '5d', 'max', etc.
    SIGMA = 0.03       # Example: 3% reversal threshold for Zig Zag

    # --- Download Data ---
    logging.info(f"Downloading {TICKER} data for period: {PERIOD}")
    try:
        # Download data, progress=False hides the download status bar
        data = yf.download(TICKER, period=PERIOD, progress=False)
        if data.empty:
            raise ValueError(f"No data downloaded for {TICKER}.")
        # yfinance sometimes returns multi-level columns, flatten them
        # data.columns = data.columns.droplevel(1) # Adjusted to be optional/checked
        if isinstance(data.columns, pd.MultiIndex):
             data.columns = data.columns.droplevel(1)
        logging.info(f"Data downloaded successfully. Shape: {data.shape}")
    except Exception as e:
        logging.exception(f"Failed to download data for {TICKER}: {e}")
        exit() # Stop script if data download fails

    # ... (Calculation and Plotting calls follow) ...

Here, TICKER, PERIOD, and the crucial SIGMA are defined. The yf.download function retrieves the data into a pandas DataFrame, with basic error handling included.

3.3 The Core Calculation: find_zigzag_extremes

This function contains the algorithm described conceptually above.

3.4 Plotting the Results: plot_zigzag

This function visualizes the OHLC data and overlays the calculated Zig Zag points.

3.5 Running the Script

The if __name__ == '__main__': block ties everything together:

Python

if __name__ == '__main__':
    # --- Configuration ---
    TICKER = 'BTC-USD'
    PERIOD = '1mo'
    SIGMA = 0.03

    # --- Download Data ---
    # (Code shown previously)
    data = yf.download(...)

    # --- Calculate Extremes ---
    logging.info(f"Calculating Zigzag extremes with sigma={SIGMA:.2%}")
    extremes_df = find_zigzag_extremes(
        data['High'].to_numpy(), # Pass price arrays
        data['Low'].to_numpy(),
        data['Close'].to_numpy(),
        SIGMA
    )

    # --- Plot Results ---
    if not extremes_df.empty:
        logging.info(f"Found {len(extremes_df)} extremes.")
        logging.info("Generating plot...")
        plot_title = f"{TICKER} Price with Zigzag Extremes (Sigma={SIGMA:.1%})"
        plot_zigzag(data, extremes_df, plot_title) # Call plotting function
        logging.info("Plot generation complete.")
    else:
        logging.warning("No extremes found to plot.")
        # Optionally plot just price data
        mpf.plot(data, type='candle', title=f"{TICKER} Price Data (No Extremes Found)", ...)

This structure makes the script runnable, executing the download, calculation, and plotting steps sequentially.

Pasted image 20250419132841.png

4. Putting It Together: Example Interpretation

If you run this script with TICKER='BTC-USD', PERIOD='1mo', and SIGMA=0.03, it will:

  1. Download the last month of Bitcoin/USD price data.
  2. Calculate significant turning points where the price reversed by at least 3%.
  3. Display a candlestick chart for that month.
  4. Overlay red upward triangles (^) at the identified significant bottoms (potential support).
  5. Overlay green downward triangles (v) at the identified significant tops (potential resistance).

By observing the sequence and levels of these markers, an analyst can quickly grasp the major swings and potential support/resistance areas within that period according to the 3% Zig Zag criterion.

Conclusion

This Python script provides a practical and automated way to apply the Zig Zag indicator to financial data. It leverages powerful libraries to handle data acquisition, calculation, and visualization efficiently. Understanding both the conceptual basis of the Zig Zag indicator – its role in filtering noise and highlighting significant reversals – and the script’s implementation allows users to effectively utilize this tool for clearer market analysis, trend assessment, and pattern recognition. Remember to choose the sigma value carefully based on the asset’s volatility and the desired level of sensitivity.