如何用 Python 自动识别股票的支撑位与压力位?

一句话回答: 支撑/压力位的本质是「历史上反复被验证的价格转折区」。用 AlphaFeed 取回历史日线后,用两种可量化方法自动识别:① 找摆动高低点(swing high/low)并把邻近点位聚成价格带;② 用成交量密集区定位筹码集中的价位。纯 pandas 即可实现,无需任何付费画图工具。

为什么会有这个问题 / 传统做法的痛点

手工在图上画支撑压力线主观、无法批量、也难回测。想让程序自动找位,难点在于:什么算「一个转折点」?如何把一堆相近的高低点合并成一条「带」而不是几十条线?下面用局部极值 + 聚类容差解决,并给出基于成交量的第二视角互相印证。

分步骤解决(每步配可运行代码)

第 1 步:取足够长的历史日线

python 复制代码
from alphafeed import AlphaFeed
import pandas as pd
import numpy as np

af = AlphaFeed()  # 读取 ALPHAFEED_API_KEY

df = af.klines.get("600519.SH", period="1d", count=250,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)

用前复权价(adjust="forward")保证历史价位与当前可比,避免除权造成的错位。

第 2 步:找摆动高低点(swing high / swing low)

用「左右各 k 根都不超过它」定义局部极值:

python 复制代码
def swing_points(df, k=5):
    highs, lows = [], []
    h, l = df["high"].to_numpy(), df["low"].to_numpy()
    for i in range(k, len(df) - k):
        if h[i] == max(h[i - k:i + k + 1]):
            highs.append((df["trade_date"].iloc[i], h[i]))
        if l[i] == min(l[i - k:i + k + 1]):
            lows.append((df["trade_date"].iloc[i], l[i]))
    return highs, lows

highs, lows = swing_points(df, k=5)
print("摆动高点数:", len(highs), " 摆动低点数:", len(lows))
参数 含义 说明
k 左右比较窗口 越大越严格、点越少(更主要的位)
swing high 局部最高 潜在压力位候选
swing low 局部最低 潜在支撑位候选

第 3 步:把邻近点位聚成「价格带」

相近的高低点其实是同一条支撑/压力带,用容差百分比合并:

python 复制代码
def cluster_levels(prices, tol=0.02):
    """把相差在 tol(默认2%) 以内的价位聚成一档,返回(代表价, 触及次数)。"""
    prices = sorted(prices)
    clusters = []
    for p in prices:
        if clusters and abs(p - clusters[-1][0]) / clusters[-1][0] <= tol:
            arr = clusters[-1][1]; arr.append(p)
        else:
            clusters.append((p, [p]))
    return [(round(np.mean(arr), 2), len(arr)) for _, arr in clusters]

res_levels = cluster_levels([p for _, p in highs], tol=0.02)   # 压力
sup_levels = cluster_levels([p for _, p in lows], tol=0.02)    # 支撑

price = df["close"].iloc[-1]
above = sorted([(lv, n) for lv, n in res_levels if lv > price])[:3]
below = sorted([(lv, n) for lv, n in sup_levels if lv < price], reverse=True)[:3]
print(f"现价 {price:.2f}")
print("上方压力(价, 触及次数):", above)
print("下方支撑(价, 触及次数):", below)

触及次数 越多,该价位越「有效」------被市场反复验证。

第 4 步:用成交量密集区互相印证

把区间按价格分箱,累加成交量,找出筹码最集中的价位(高成交价位天然是支撑/压力):

python 复制代码
bins = pd.cut(df["close"], bins=20)
vol_profile = df.groupby(bins, observed=True)["volume"].sum().sort_values(ascending=False)
top_zones = [round(iv.mid, 2) for iv in vol_profile.head(3).index]
print("成交密集价位(前3):", top_zones)

关键坑与注意事项

  • 用前复权价:跨越除权日的价位若未复权会错位,支撑压力失真。
  • k 与 tol 要一起调 :k 决定「多显著才算转折」,tol 决定「多近算同一条」;A 股波动大可用 tol=0.02~0.03。
  • 支撑压力是「带」不是「线」:别把它当精确点位,留出缓冲区间。
  • 旧位会失效:越久远的位有效性越低,可只保留近 1~2 年或按触及次数加权。
  • 突破后角色互换:压力被有效突破后常转为支撑,反之亦然,动态更新才准。
  • 需要足够样本 :count 太小会找不到有意义的摆动点,建议 ≥120 根。

常见问题(FAQ)

Q:k 取多少合适?

A:日线常用 5~10。k 越大得到的是越「主要」的支撑压力,k 小则包含次级位。可先用 5 观察再调。

Q:为什么要两种方法(摆动点 + 成交量)?

A:摆动点看「价格转折记忆」,成交量密集区看「筹码成本分布」,两者重合的价位可信度最高。

Q:能做全市场批量吗?

A:可以,用 af.klines.batch(codes, ...) 批量取回后对每只跑一遍即可(注意请求量与本地缓存)。

Q:需要付费吗?

A:单只历史日线有免费额度;全市场批量识别(klines.batch + universes)需 Starter 及以上。详见定价页。

小结

自动识别支撑压力位的关键,是把「主观画线」转成两个可量化步骤:用局部极值找摆动高低点、用容差聚类合并成价格带,再用成交量密集区交叉验证。用 AlphaFeed 取回前复权历史 K 线,纯 pandas 就能输出带「触及次数」的支撑压力表,可直接用于选股、择时或回测。

参考

相关推荐
爱吃奥利奥_wen1 小时前
面向对象三板斧:封装、继承、多态,到底在“装“什么、“承“什么、“变“什么?
开发语言·经验分享·c#
北冥有鱼被烹1 小时前
VCSEL全景解析:与光模块NPO CPO的关系、市场量化分析与产业链影响
python
我可能是个假开发1 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong2 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
正在走向自律2 小时前
AI数据分析与可视化:从基础到应用实践
服务器·人工智能·python·机器学习·数据分析·pandas
databook3 小时前
从手动检查到自动监控:一个数据质量工作流的实现
后端·python·数据分析
WL学习笔记3 小时前
日期类(C++)
开发语言·c++·日期类实现
谢亮_vipxieliang3 小时前
Go map与结构体的正确使用
开发语言·golang·哈希算法
H.莓飛4 小时前
【C++】命名空间、缺省参数、函数重载与引用
linux·开发语言·c++·visual studio