支撑与阻力位是技术分析中的核心概念,能够帮助交易者识别价格趋势可能反转的关键位置。掌握这些价位,可以为交易决策提供更精准的进出场参考,优化风险控制和收益预期。
本文将通过 Python 逐步演示如何自动计算并可视化这些关键价位。无论您分析的是 5 分钟 K 线还是日线,该方法都能灵活适配。
所需工具与数据准备
在开始之前,需要安装几个关键的 Python 库。您可以通过 pip 快速安装:
pip install yahooquery pandas scipy mplfinance安装完成后,导入这些库:
import yahooquery as yq
import pandas as pd
import scipy as sp
import mplfinance as mpf接下来,我们获取股票的历史数据。这里以苹果公司(AAPL)的日线数据为例:
bars = yq.Ticker('AAPL').history(start='2022-01-01', interval='1d').reset_index(level=0, drop=True)这段代码会获取从 2022 年初至今的每日价格数据,包含开盘价、最高价、最低价、收盘价和成交量。
可视化历史价格走势
在计算支撑阻力之前,先直观了解价格的整体走势是非常有益的。我们可以使用 mplfinance 库绘制 K 线图:
bars.index = pd.to_datetime(bars.index)
mpf.plot(bars, type='candle', style='charles', title='(AAPL) 日K线图', volume=True)使用 SciPy 识别价格峰值(阻力位)
scipy.signal 模块中的 find_peaks 函数是识别局部高点(峰值)的利器。这些峰值通常对应着潜在的阻力位。该函数有两个关键参数:
- distance: 规定两个连续峰值之间所需的最小数据点数量,用于避免识别出过于密集的峰值。
- prominence: 衡量一个峰值相对于其周围数据的突出程度。 prominence 值越高,峰值越显著。
识别强阻力位
我们将阻力位分为“强阻力”和“一般阻力”。强阻力位通常具有高 prominence 值和较大的间隔距离,并且包含像 52 周高点这样的显著价格水平。
以下是识别强阻力位的代码:
# 定义强峰值的间隔天数
strong_peak_distance = 60
# 定义强峰值的突出程度
strong_peak_prominence = 20
# 在最高价数据中寻找强峰值
strong_peaks, _ = sp.signal.find_peaks(
bars['high'],
distance=strong_peak_distance,
prominence=strong_peak_prominence
)
# 提取强峰值对应的价格
strong_peaks_values = bars.iloc[strong_peaks]["high"].values.tolist()
# 将52周高点也作为一个强阻力位加入列表
yearly_high = bars["high"].iloc[-252:].max()
strong_peaks_values.append(yearly_high)运行后,strong_peaks_values 列表会包含一系列强阻力位的价格。您可能会注意到有些值非常接近,这很正常,我们后续会进行合并处理。
识别一般阻力位
波段交易者通常更关注短期价格波动,因此我们需要识别更多、更频繁出现的峰值,即“一般阻力位”。
这些峰值的 prominence 和 distance 参数设置得比强峰值更宽松。但一个价格要成为一般阻力位,必须满足一个关键条件:价格多次触及该水平并被拒绝。
我们通过设置最小宽度(peak_rank_width)和最小排名(resistance_min_pivot_rank)阈值来实现。此方法将附近的弱峰值分组,如果某个价格水平的“排名”(即被拒绝的次数)达到阈值,则被确认为阻力位。
# 定义一般峰值的间隔天数
peak_distance = 5
# 定义合并峰值的价格宽度阈值
peak_rank_width = 2
# 定义成为一个阻力位所需的最小拒绝次数
resistance_min_pivot_rank = 3
# 寻找一般峰值
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()
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]识别波谷(支撑位)
识别支撑位的逻辑与识别阻力位完全对称,只需将处理的最高价数据替换为最低价数据的负值即可:
troughs, _ = sp.signal.find_peaks(-bars['low'], distance=peak_distance)后续的排名、合并逻辑与阻力位处理完全相同,只需将代码中的 high 替换为 low。
结论与展望
本文详细介绍了如何使用 Python 自动化计算股票的支撑位和阻力位。通过区分强阻力/支撑和一般阻力/支撑,并结合峰值合并算法,我们能够得到一套清晰、有效的关键价位体系。
这种方法适用于任何时间周期和交易品种,为您的交易决策提供数据驱动的技术分析依据。无论是寻找趋势反转点还是短期交易机会,理解支撑和阻力都是至关重要的一步。
常见问题
什么是支撑位和阻力位?
支撑位是价格下跌过程中可能遇到买盘支撑,从而止跌回升的水平。阻力位则是价格上涨过程中可能遇到卖压,从而回落下跌的水平。它们是技术分析的基础,帮助交易者判断潜在的进出场点。
为什么需要区分强阻力和一般阻力?
强阻力通常基于长期、显著的价格高点形成,意义重大,可能主导长期趋势。一般阻力则反映短期、频繁出现的价格拒绝,对波段交易者更具指导意义。区分两者有助于制定不同时间周期的策略。
参数(如 distance, prominence)应该如何调整?
这些参数没有标准值,需根据交易品种的波动特性和您的交易周期(如日线、小时线)进行调整。波动性大的品种可能需要更大的 distance 和 prominence 值。建议进行历史回测以找到最佳参数。
这个方法可以用于加密货币或其他资产吗?
完全可以。只要将数据获取部分替换为相应资产的历史价格数据(例如通过其他API获取加密货币数据),该算法的核心逻辑适用于任何有价格波动的交易资产。
如何避免过度拟合?
避免在少量数据上过度优化参数。使用足够长的历史数据进行测试,并确保参数在样本外数据上同样有效。核心思路是抓住显著且重复出现的价格水平,而非捕捉每一个微小波动。
除了寻找高低点,还有其他方法确认支撑阻力吗?
是的。成交量密集区、移动平均线、斐波那契回撤位、心理整数关口等都可以作为确认支撑阻力的辅助手段。本文介绍的方法可以与之结合使用,提高判断的准确性。