Back To Top

April 2, 2025

Price Transitions with Adaptive Trend Wave Bands

A line-break band system that encodes directional strength using count-based alpha and ATR-driven volatility offsets

TrendWave Bands don’t try to predict market direction. They react to it cleanly, visually, and in real time. 

We combine smoothed price levels with adaptive volatility buffers to show trend transitions as they emerge, not after they’re obvious.

Each time price crosses above or below the dynamic bands, a new regime begins. As the trend extends, the bands grow more visible to reflect strength and duration.

Let’s implement the analysis, from calculating the bands, defining trend direction and building the visuals to highlight transitions and persistance.

Trendwave Output (OPTIMIZED)

This article is structure as follows:

  • The TrendWave System
  • Compute Bands & Trend Flip Markers
  • Plotting Bands and Transition Perdiods
  • Discussion — Limitations, and Improvements

End-to-end Google Notebook provided below.

1. TrendWave Bands and How They Work

TrendWave Bands combine smoothed price levels with dynamic volatility buffers to identify trend transitions. 

Unlike fixed-width envelopes, these bands adapt in real time to changing market conditions.

The process starts with the typical price, which averages the daily high, low, and close:

formula 1. hlc3

This price acts as the trigger for detecting trend shifts.

To define the adaptive band structure:

  1. Volatility is computed as a simple moving average of the daily range:
formula 2. volatility

2. A smoothed price is added or subtracted from volatility to create raw bands:

  • Upper Raw Band:
formula 3. upper band
  • Lower Raw Band:
formula 4. lower band

Crossover logic detects the moment the typical price breaks through these levels:

  • If hlc3 crosses above the upper raw band → trend shifts up
  • If hlc3 crosses below the lower raw band → trend shifts down

Once a trend is active, a counter tracks how long it persists (up to a fixed cap). 

This trend duration modulates the opacity of the plotted line, the longer the trend, the more visible the band.

To extend the bands and reflect price pressure, an additional layer is added using the Average True Range:

  • True Range:
formula 5. tr
  • Then smoothed over 100 periods:
fomrula 6. atr

These values are used to define extended “wave lines”:

  • Upper Band:
formula 7 upper band
  • Lower Band:
formula 8 lower band

Finally, trend flip markers are added when the trend direction changes and the regime shifts. 

2. Python Implementation

2.1 User Parameters

You set the ticker and date range to pull historical data. Any Yahoo Finance symbol works — stocks, ETFs, crypto, etc.

The LENGTH parameter controls smoothing. Lower values make the bands react faster. Higher values filter noise and slow down trend shifts.

The FACTOR scales band width using volatility. Increase it for wider, more stable bands. Decrease it to make the system more responsive.

Color settings define how trends appear visually — green for up, red for down, cyan for extensions by default.

Toggles like SHOW_BANDS, GRADIENT, and SHOW_DASHBOARD control visuals and whether to print a quick summary to the console.

				
					import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.style.use("dark_background")

# USER PARAMETERS
TICKER     = "ASML.AS"        # Ticker symbol used to pull data from Yahoo Finance
START_DATE = "2023-01-01"     # Start date for historical data
END_DATE   = "2026-06-01"     # End date for historical data

LENGTH     = 50               # Lookback window used to smooth signals and compute trend structure
FACTOR     = 1.0              # Multiplier for volatility band width; higher => wider bands

COLOR_UP   = "#00FF00"        # Line color when trend is up
COLOR_DN   = "#DD1A1A"        # Line color when trend is down
COLOR_UL   = "#00FFFF"        # Color used for wave extensions (ATR-based bands)

SHOW_BANDS      = True        # Toggle to draw the trend-following bands
GRADIENT        = True        # If True, use opacity gradient in the fill for visual emphasis
SHOW_DASHBOARD  = True        # If True, print config and trend summary in the console
				
			

2.2 Data Download & Preprocessing

Daily price data is downloaded for the selected ticker. 

We ensure that key columns such as High, Low, Close, and Volume are correctly identified and standardized. 

The date index is also converted into a NumPy array for plotting.

				
					# Data Download & Preprocessing

# Download daily data
df = yf.download(TICKER, start=START_DATE, end=END_DATE, interval="1d", auto_adjust=False)
if df.empty:
    print("No data returned for the given ticker/date range.")
    exit(1)

# Flatten multi-index columns if present
if isinstance(df.columns, pd.MultiIndex):
    df.columns = df.columns.map("_".join)

# Robust column renaming:
# Expected keys for price data.
keys = ["Open", "High", "Low", "Close", "Volume"]
rename_dict = {}
for key in keys:
    if key not in df.columns:
        # Search for any column that starts with the key
        for col in df.columns:
            if col.startswith(key):
                rename_dict[col] = key
                print(f"Column '{col}' found. Renaming it to '{key}'.")
                break
if rename_dict:
    df.rename(columns=rename_dict, inplace=True)

# Verify required columns exist now.
for key in ["High", "Low", "Close"]:
    if key not in df.columns:
        print(f"Required column '{key}' not found after renaming. Available columns: {df.columns}")
        exit(1)

df.dropna(inplace=True)
if df.empty:
    print("Data is empty after cleaning. Exiting.")
    exit()

# Standardize column names for later use.
df["Price"] = df["Close"]
df["Time"]  = df.index

# Convert the date index to a NumPy array (for positional indexing).
dates_arr = df.index.to_numpy()
				
			

2.3 Compute TrendWave Bands & Trend Flip Markers

Now we calculate the core structure that drives the indicator.

First, we create the typical price by averaging each day’s high, low, and close. This gives a more stable signal than using close price alone.

Next, we build two adaptive bands:

  • The upper raw band uses a short-term moving average plus a volatility buffer.
  • The lower raw band uses a longer average minus the same buffer.

Volatility is measured as the average high–low range over 70 bars, scaled by the FACTOR. These bands expand or contract in real time.

We then track when price crosses these bands:

  • If the typical price crosses above the upper band → trend is up
  • If it crosses below the lower band → trend is down
  • Otherwise, the previous trend continues
formula 9 direction

Each time a trend is active, we count how long it lasts, capped at 70. This count is used later to control line transparency: longer trends = stronger visual signal.

To give the structure more context, we also calculate ATR(100). This extends the bands to form outer “waves” that reflect price pressure beyond the trend core.

Finally, we detect when the trend direction changes and store those points. These flip markers are plotted later to highlight trend shifts visually.

Prev Post

Auto-Detect Price Pivot Zones with Fibonacci Fans

Next Post

Modeling Price Structure with Time-Anchored Linear Regressions

post-bars
Mail Icon

Newsletter

Get Every Weekly Update & Insights

[mc4wp_form id=]

Leave a Comment