使用 Python 计算股票支撑与阻力位的详细指南

·

支撑与阻力位是技术分析中的核心概念,能够帮助交易者识别价格趋势可能反转的关键位置。掌握这些价位,可以为交易决策提供更精准的进出场参考,优化风险控制和收益预期。

本文将通过 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 函数是识别局部高点(峰值)的利器。这些峰值通常对应着潜在的阻力位。该函数有两个关键参数:

识别强阻力位

我们将阻力位分为“强阻力”和“一般阻力”。强阻力位通常具有高 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)应该如何调整?
这些参数没有标准值,需根据交易品种的波动特性和您的交易周期(如日线、小时线)进行调整。波动性大的品种可能需要更大的 distanceprominence 值。建议进行历史回测以找到最佳参数。

这个方法可以用于加密货币或其他资产吗?
完全可以。只要将数据获取部分替换为相应资产的历史价格数据(例如通过其他API获取加密货币数据),该算法的核心逻辑适用于任何有价格波动的交易资产。

如何避免过度拟合?
避免在少量数据上过度优化参数。使用足够长的历史数据进行测试,并确保参数在样本外数据上同样有效。核心思路是抓住显著且重复出现的价格水平,而非捕捉每一个微小波动。

除了寻找高低点,还有其他方法确认支撑阻力吗?
是的。成交量密集区、移动平均线、斐波那契回撤位、心理整数关口等都可以作为确认支撑阻力的辅助手段。本文介绍的方法可以与之结合使用,提高判断的准确性。