Support and resistance levels are foundational tools in technical analysis, helping traders identify potential reversal points in price trends. These levels are derived from historical price data and can significantly enhance trading strategies by pinpointing optimal entry and exit points.
Key Concepts: Support and Resistance
- Support Line: A price level where buying interest is strong enough to prevent further decline, often causing a downtrend to pause or reverse.
- Resistance Line: A price level where selling pressure halts an uptrend, potentially leading to a price reversal.
Implementation in Python
1. Install Required Packages
pip install yahooquery pandas scipy mplfinance2. Import Libraries
import yahooquery as yq
import pandas as pd
import scipy as sp
import mplfinance as mpf3. Load Historical Data
bars = yq.Ticker('AAPL').history(start='2022-01-01', interval='1d').reset_index(level=0, drop=True)4. Visualize Price Data
Plot candlestick charts to contextualize price movements:
bars.index = pd.to_datetime(bars.index)
mpf.plot(bars, type='candle', style='charles', title='AAPL Candlestick Chart', volume=True)Identifying Resistance Levels
Strong Peaks
Resistance levels with high prominence and separation:
strong_peaks_distance = 60 # Minimum days between peaks
strong_peaks_prominence = 20 # Peak significance threshold
strong_peaks, _ = sp.signal.find_peaks(
bars['high'],
distance=strong_peaks_distance,
prominence=strong_peaks_prominence
)
strong_peaks_values = bars.iloc[strong_peaks]["high"].values.tolist()
yearly_high = bars["high"].iloc[-252:].max()
strong_peaks_values.append(yearly_high)General Peaks
Shorter-term resistance levels with weaker prominence:
peak_distance = 5 # Days between peaks
peak_rank_width = 2 # Price range for merging peaks
resistance_min_pivot_rank = 3 # Minimum rejections to qualify as resistance
peaks, _ = sp.signal.find_peaks(bars['high'], distance=peak_distance)
peak_to_rank = {peak: 0 for peak in peaks}
for i, current_peak in enumerate(peaks):
current_high = bars.iloc[current_peak]["high"]
for previous_peak in peaks[:i]:
if abs(current_high - bars.iloc[previous_peak]["high"]) <= peak_rank_width:
peak_to_rank[current_peak] += 1
resistances = strong_peaks_values
for peak, rank in peak_to_rank.items():
if rank >= resistance_min_pivot_rank:
resistances.append(bars.iloc[peak]["high"] + 1e-3)
resistances.sort()Merge Nearby Peaks
resistance_bins = []
current_bin = [resistances[0]]
for r in resistances:
if r - current_bin[-1] < peak_rank_width:
current_bin.append(r)
else:
resistance_bins.append(current_bin)
current_bin = [r]
resistance_bins.append(current_bin)
resistances = [np.mean(bin) for bin in resistance_bins]Identifying Support Levels
Apply the same methodology to troughs (price lows):
troughs, _ = sp.signal.find_peaks(-bars['low'], distance=peak_distance)Conclusion
This guide demonstrates how to programmatically identify support and resistance levels using Python. By combining strong peaks (long-term resistances) and general peaks (short-term rejections), traders gain a comprehensive view of key price levels.
๐ Explore advanced trading strategies
FAQs
Q1: Can this method be applied to intraday trading?
A: Yes! Adjust the interval parameter in yq.Ticker() to shorter time frames (e.g., 5m for 5-minute bars).
Q2: How do I avoid overfitting resistance levels?
A: Tweak peak_distance and prominence to filter out insignificant peaks.
Q3: What other indicators complement support/resistance analysis?
A: Volume analysis and moving averages enhance the reliability of these levels.
Q4: Why merge nearby peaks?
A: Merging reduces noise, creating cleaner, more actionable resistance levels.
Q5: How often should I recalculate these levels?
A: Update them periodically (e.g., weekly) to reflect recent price action.
Q6: Can this be automated for multiple stocks?
A: Absolutely. Wrap the code in a loop to process multiple tickers.
๐ Master Python for trading with real-world examples. Happy coding!