支撑位 与 阻力位 是最常挂在交易者嘴边的关键词之一:
在价格不断下探时,总有一些“地板价”把跌势托住,这被称为支撑;当多头试图冲出重围时,又会被“天花板”压回来,那便是阻力。
把这两个概念交给算法,就可能复盘、回测、甚至在高频里把“直觉”变成量化信号。本文用 K-Means 聚类 来演示怎样在 Python 中自动计算长期水平的支撑与阻力,并一步步剖析怎样做得更好。
1 支撑位与阻力位:交易心理学101
1.1 基本定义
- 支撑位(Support):价格到此区域后出现买盘激增,下跌暂缓。
- 阻力位(Resistance):价格到此区域后抛压加大,上涨受阻。
- 角色互换:一旦跌破支撑,原先的“地板”就变成新的“天花板”;突破阻力后,“天花板”则会反过来当“地板”。
1.2 为什么人们记得整数价位
-human bias- 让 $100、$500、¥70,000、$1,000 成为天然的“心理关卡”。
图 1:价格为上升途中突破阻力,之后原阻力位转为支撑。
1.3 真实案例:Amazon 2018–2022
2018 年亚马逊冲高后回调,$2,020 附近多次上攻失败,形成阻力;2022 年同一价位既然又托住了瀑布式的下跌,角色立刻“反串”成支撑。
2 发现价格“滞区”的两条赛道
| 场景 | 形态 | 代表例子 |
|---|---|---|
| 长期水平 | 多空反复争夺的价格记忆带 | 5 年周线 |
| 短期斜线 | 趋势线通道 | 日内/30 分钟图 |
本文聚焦长期水平用法,先用 K-Means 把 5 年周线 BTC/USD 的收盘数据切成若干“价格坑”;斜线则留给你用线性回归和高低点算法继续探索。
3 K-Means 如何定位支撑阻力?
核心思路:
把 Adj Close 扔进 K-Means,让算法自动切分“密集区”,再把相邻区的边界当作支撑 / 阻力。流程如下:
👉 想跳过基础理论,直接捞源码?戳这看完整 notebook 示例!
3.1 环境与数据准备
pip install pandas scikit-learn plotly numpyimport pandas as pd, numpy as np, plotly.graph_objects as go
from sklearn.cluster import KMeans
# 读取 5 年周线 Bitcoin
btc = pd.read_csv('BTC-USD.2017-2022.week.csv')
btc['Date'] = pd.to_datetime(btc['Date'])
btc.set_index('Date', inplace=True)3.2 聚类到画线 5 步走
准备价格向量:
prices = btc['Adj Close'].values.reshape(-1, 1)跑 K-Means(K=6 起手):
k = 6 model = KMeans(n_clusters=k, random_state=42).fit(prices) labels = model.labels_计算各区边界:
bounds = [] for c in range(k): mask = labels == c lower, upper = prices[mask].min(), prices[mask].max() bounds.append((lower, upper)) bounds = sorted(bounds, key=lambda x: x[0])合并相邻边界(取平均值):
lines = [] for i, (_min, _max) in enumerate(bounds): if i == 0: lines.append(_min) # 最下线 elif i == k-1: lines.append(_max) # 最上线 else: lines.append((_max + bounds[i+1][0]) / 2) # 现在 lines 包含了 k-1 条干净的支撑阻力价位可视化(Plotly 极简版):
fig = go.Figure(go.Scatter(x=btc.index, y=btc['Adj Close'], mode='lines', line=dict(color='black', width=1))) for lvl in lines[1:-1]: # 去掉极值边界 fig.add_hline(y=lvl, line_color='blue', opacity=.8) fig.update_layout(height=500, xaxis_rangeslider_visible=False) fig.show()
4 问:K 定几才合适?
大多数教程会教你“肘部法”,但实践证明 坐标压缩延伸 会让肘部曲线失真。
亲手遍历 k=2~9 并做市图对比更直观:
k=2几乎就是一条中线,信息不足;k=6可能过密,底部区被切得支离破碎;- 推荐 :
先用观察法,再叠加 Silhouette 轮廓系数 微调。
👉 想了解肘部、Silhouette、Gap 三大指标一站对比?点击查看 Demo!
5 聚合可视化:真实样貌
图 7:合并相邻边界后的水平线,把 5 年 BTC 历史切成五块定价带。
图 8:手工改线对比,发现人工经验更侧重“高低点历史回撤”——机器边界略滞后。
=> 启示:K-Means 适合“整体密度”而非“题材新闻驱动的局部大级别高低”。
6 代码边界的局限与改进
- 极值边界失真:
把 5 年中峰顶、峰谷直接当支撑阻力会过度反应;剔除首尾一两个价位即可。 - 滴答密度不均:
K-Means 把高容量横盘区撕开成好几段,解决办法用 加权 K-Means 或以成交量当权重。 - MTF 优化(Multi-TimeFrame):
把日线、4h、周线三维数据压成一个张量用 K-Means++ 或 MiniBatchKMeans,再投影回周线,样本稀疏度显著下降。 - 加入斜线混合模型:
PCA + 线性回归能找到“斜率”显著的通道,再配合 K-Means 提供水平带,实现点—线—面三位一体。
7 总结
支撑与阻力归根结底是“记忆价”,而记忆价往往表现为价格的“密度中心”。
K-Means 给了我们把密度中心转成水平供给/需求带的一把快刀,但它:
- 不会 体现事件驱动(EIP-1559 生效、比特币 ETF 预期);
- 需要 人做出
k选择; - 最好 与偷价指标、趋势线、情绪舆情一起入模型。
因此:
把 K-Means 当“绘图板”而非“圣杯”,再用回测验证真假,才能真正吃透它。
常见问题(FAQ)
Q1:K 选错难道会让系统崩溃吗?
A:不会崩溃,只是真实成交概率直线下降。建议用回测胜率 + 集中交易分布双指标评估。
Q2:聚类法能否用于 A 股日线?
A:当然可以。前提是把节假日缺口对齐,否则聚类中心可能落在停券缺口。
Q3:是否需要分段再跑?例如牛市、熊市?
A:是的。K-Means 假设“一个分布”,把冰火两重天混一起,边界会失真;建议按 60WMA 斜率切分区,效果更稳。
Q4:为何文中剔除了最上/最下线?
A:它们往往是黑天鹅极值,并非“高概率回补区”,拿来做回测易过拟合。
Q5:能否直接拿行业平均、地产概念指数当主成分?
A:可以。宏观经济共振可能使 A 股和港、美共振,需要加权欧式距离或在张量空间聚类。
已在今日一词一句、一图一算法中,陪你走完了 “用 K-Means 计算支撑阻力” 的全程。
下一篇,我们聊 Python 里把 Bollinger、K-Means 打包成Pipeline并用网格 CV 找超参数,敬请期待。