← Back to Home
Do Price Extremes Hold Trading Clues

Do Price Extremes Hold Trading Clues

In the world of financial markets, traders and analysts constantly seek methods to understand price movements and identify potential trading opportunities. Technical analysis offers a range of tools and strategies based on historical price data. One such simple strategy involves observing price breakouts relative to recent highs and lows. Let’s explore a basic “Rolling Max/Min Crossover” strategy, similar to concepts used in channel breakout systems.

The Strategy Explained

The core idea is to identify when the price moves significantly beyond its recent trading range, potentially signaling the start of a new trend or a reversal. We define this “recent range” using a rolling window – a specific number of past trading days (e.g., 20 days).

  1. Rolling Maximum: The highest closing price observed during the specified rolling window period.
  2. Rolling Minimum: The lowest closing price observed during the specified rolling window period.

The trading signals are generated as follows:

Important Note: We calculate the Rolling Max/Min based on the data before the current day (shift(1)) to avoid lookahead bias – we make decisions based only on information available up to that point.

Implementation in Python

Let’s see how this looks in Python using libraries like pandas and yfinance.

1. Getting Data: First, we fetch historical price data. We used Bitcoin (BTC-USD) as an example:

Python

import yfinance as yf
import pandas as pd
import numpy as np

# Fetch Bitcoin data
ticker_symbol = "BTC-USD"
btc_data = yf.Ticker(ticker_symbol)
df = btc_data.history(period="1y") # Get 1 year of data

if df.empty:
    print("Could not fetch data.")
else:
    print(f"Fetched {len(df)} rows of data for {ticker_symbol}")

2. Calculating Signals: We then calculate the rolling minimum/maximum and generate the signals.

Python

# Define the rolling window size (e.g., 20 days)
count = 20

# Create a DataFrame for signals
signals = pd.DataFrame(index=df.index)
signals['signal'] = 0.0 # 0 means hold/no signal
signals['trend'] = df['Close'] # Base the strategy on closing price

# Calculate Rolling Max/Min on *previous* data points
signals['RollingMax'] = signals.trend.shift(1).rolling(count).max()
signals['RollingMin'] = signals.trend.shift(1).rolling(count).min()

# Generate Buy signal (Price drops below Rolling Min)
signals.loc[signals['RollingMin'] > signals.trend, 'signal'] = 1

# Generate Sell signal (Price rises above Rolling Max)
signals.loc[signals['RollingMax'] < signals.trend, 'signal'] = -1

# See how many signals were generated
print("\nSignal distribution:")
print(signals['signal'].value_counts())

Simulating Trades (Backtesting)

Generating signals is one thing; seeing how they might have performed historically is another. This is done via backtesting. We created a function (buy_stock) to simulate making trades based on these signals, starting with an initial amount of capital and tracking hypothetical profits or losses. This function handles buying and selling (including fractional amounts for assets like Bitcoin) when a signal occurs, subject to certain constraints (like only buying if we don’t already hold the asset).

Python

# (Simplified representation of calling the backtest function)

# Assuming 'buy_stock' function is defined as in the previous example...
initial_money = 10000
states_buy, states_sell, total_gains, invest_percent = buy_stock(
    real_movement=df['Close'],
    signal=signals['signal'].values,
    initial_money=initial_money
)

print(f"Simulation Result: Gain ${total_gains:,.2f} ({invest_percent:.2f}%)")

Finally, we visualize the results, plotting the closing price and marking the points where buy and sell signals were executed.

Python

import matplotlib.pyplot as plt

# (Assuming states_buy/states_sell lists contain indices of trades)
if states_buy or states_sell:
    plt.figure(figsize=(15, 7))
    plt.plot(df['Close'], color='r', lw=1.5, label=f'{ticker_symbol} Close Price')
    plt.plot(df['Close'], '^', markersize=8, color='g', label='Buy Signal', markevery=states_buy, markerfacecolor='none')
    plt.plot(df['Close'], 'v', markersize=8, color='k', label='Sell Signal', markevery=states_sell, markerfacecolor='none')
    plt.title(f'{ticker_symbol} - Rolling Max/Min ({count}-day) Strategy Simulation')
    plt.ylabel("Price (USD)")
    plt.xlabel("Date")
    plt.legend()
    plt.grid(True)
    plt.show()
Pasted image 20250504181829.png

Interpretation and Caveats

This strategy provides a basic framework for identifying potential entry and exit points based on recent price ranges.

However, it’s crucial to understand its limitations:

Conclusion

The Rolling Max/Min Crossover strategy serves as a simple, understandable example of how technical indicators can be used to generate trading signals. While likely too basic for direct application without significant refinement and risk management, implementing and backtesting such strategies provides valuable educational insight into quantitative analysis, programming for finance, and the challenges of strategy development. Remember, past performance is not indicative of future results, and this article is purely for educational purposes, not financial advice.