
Support and resistance levels are foundational concepts in the world of trading, acting as critical signposts for making informed decisions. These levels help traders predict future breakout or breakdown scenarios. Traders typically discern these levels through manual observation and charting, however, with modern algorithmic techniques traders can now identify these crucial levels with enhanced precision and speed. The purpose of this article is to introduce you to 7 different techniques worth knowing in Python:
Rolling Midpoint Range
Fibonacci Retracement
Swing Highs and Lows
Pivot Point Analysis
K-Means Price Clustering
Volume Profiler
Regression Modelling
The full end-to-end workflow is available in a Google Colab notebook, exclusively for paid subscribers of my newsletter. Paid subscribers also gain access to the complete article, including the full code snippet in the Google Colab notebook, which is accessible below the paywall at the end of the article. Subscribe now to unlock these benefits! |
2. Basics of Support and Resistance
Support and resistance highlight the areas where a stock’s price typically halts its upward or downward trajectory. While the support level acts as a cushion, suggesting significant buying interest, the resistance level emerges as a barrier, indicative of prevailing selling sentiment. An algorithmic approach ensures higher accuracy but also dynamically responds to market shifts, bestowing traders with an enhanced, data-driven edge in their decision-making processes.
3. Python Implementation Techniques
3.1 Rolling Midpoint Range
The Rolling Midpoint Range method employs moving averages and price range evaluations over a designated interval to highlight potential support and resistance areas. This approach fundamentally revolves around the rolling window concept:
Determine High and Low: For each stock price point, a certain number of previous data points are considered. Within this window (e.g., 30 days), the highest and lowest prices are identified.
Establish the Midpoint: This midpoint is calculated by taking the average of the identified high and low values.
Set Support and Resistance Levels: Support is deduced from the midpoint by subtracting half of the price range (difference between the determined high and low). Conversely, resistance is inferred by adding half of this range to the midpoint.
import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
def find_levels(data, window):
high = data['High'].rolling(window=window).max()
low = data['Low'].rolling(window=window).min()
midpoint = (high + low) / 2
diff = high - low
resistance = midpoint + (diff / 2)
support = midpoint - (diff / 2)
return support, resistance
# Download historical stock prices
symbol = "MSFT"
start_date = '2018-01-01'
end_date = '2023-12-30'
data = yf.download(symbol, start=start_date, end=end_date)
window = 30
# Calculate support and resistance levels
support, resistance = find_levels(data, window)
# Plot the stock price, support, and resistance lines
fig, ax = plt.subplots(figsize=(24, 8))
ax.plot(data.index, data['Close'], label='Stock Price')
ax.plot(data.index, support, label='Support', linestyle='--', color='green')
ax.plot(data.index, resistance, label='Resistance', linestyle='--', color='red')
ax.set_xlabel('Date')
ax.set_ylabel('Price')
ax.set_title(f'{symbol} Stock Price with Support and Resistance Levels')
ax.legend()
# Add annotations for last support and resistance levels
last_support = support.iloc[-1]
last_resistance = resistance.iloc[-1]
ax.annotate(f'Support: {last_support:.2f}', xy=(support.index[-1], last_support),
xytext=(support.index[-1] - pd.DateOffset(days=30), last_support + 10),
arrowprops=dict(facecolor='green', arrowstyle='->'))
ax.annotate(f'Resistance: {last_resistance:.2f}', xy=(resistance.index[-1], last_resistance),
xytext=(resistance.index[-1] - pd.DateOffset(days=30), last_resistance - 10),
arrowprops=dict(facecolor='red', arrowstyle='->'))
plt.show()
Figure 1: Microsoft’s stock price from 2018 to 2023, overlaid with dynamic support (green dashed line) and resistance (red dashed line) levels derived from the Rolling Midpoint Range method. The annotations indicate the most recent levels, emphasizing their relevance to current trading conditions.
3.2 Fibonacci Retracement
Fibonacci Retracement, grounded in the Fibonacci sequence established by Leonardo Fibonacci in the 13th century, is a pivotal technical analysis tool. It pinpoints potential support and resistance zones, assisting traders in identifying prospective market reversal points. Here’s a concise breakdown:
Understanding the Tool: Fibonacci retracement levels are horizontal markers on a chart, indicating where price reversals might occur. These levels — 23.6%, 38.2%, 50%, 61.8%, and 78.6% — signify how much of a prior price movement has been retraced. For instance, if a stock ascends from $10 to $20 and then drops to $15, it has retraced 50% of its rise.
Application in Trading: These percentages are used to create horizontal lines on price charts, suggesting areas where prices might pivot. Such levels, particularly the 61.8% (Golden Ratio), are rooted in the Fibonacci sequence and have shown consistent relevance in influencing stock price behavior.
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Get the stock data for ASML.AS
symbol = "GOOG"
stock_data = yf.download(symbol, start="2020-01-01", end="2023-12-17")
# Define the lookback period for calculating high and low prices
lookback_period = 15
# Calculate the high and low prices over the lookback period
high_prices = stock_data["High"].rolling(window=lookback_period).max()
low_prices = stock_data["Low"].rolling(window=lookback_period).min()
# Calculate the price difference and Fibonacci levels
price_diff = high_prices - low_prices
levels = np.array([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1])
fib_levels = low_prices.values.reshape(-1, 1) + price_diff.values.reshape(-1, 1) * levels
# Get the last price for each Fibonacci level
last_prices = fib_levels[-1, :]
# Define a color palette for the Fibonacci levels
colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
# Plot the stock price with the Fibonacci retracement levels and last prices
fig, ax = plt.subplots(figsize=(24,8))
ax.plot(stock_data.index, stock_data["Close"], label="Stock Price")
offsets = [-16, -14, -12, -10, 8, 10, 12]
for i, level in enumerate(levels):
if level == 0 or level == 1:
linestyle = "--"
else:
linestyle = "-"
ax.plot(stock_data.index, fib_levels[:, i], label=f"Fib {level:.3f}", linestyle=linestyle, color=colors[i])
ax.annotate(f"{last_prices[i]:.2f}",
xy=(stock_data.index[-1], fib_levels[-1, i]),
xytext=(stock_data.index[-1] + pd.Timedelta(days=5), fib_levels[-1, i] + offsets[i]),
ha="left", va="center", fontsize=16, color=colors[i])
ax.set_xlabel("Date")
ax.set_ylabel("Price")
ax.set_title(f"{symbol} with Fibonacci Retracement Levels")
ax.legend(loc="lower right", fontsize=14)
plt.show()
Figure 2: Google’s stock price trend from 2020 to 2023, interspersed with Fibonacci retracement levels. These lines mark potential inflection points, providing insight into areas of support or resistance based on the age-old Fibonacci sequence.
3.3 Swing Highs and Lows
Subscribe to our premium content to read the rest.
Become a paying subscriber to get access to this post and other subscriber-only content.
Upgrade