作 者:老余捞鱼
原创不易,转载请标明出处及原作者。

文中示例仅用于技术讨论,不构成任何操作建议。
量化策略开发应以学习和技术交流为目的。
本号不荐股、不卖课、不承诺收益。
市场有风险,请合法合规投资。
本文约 3800 字(含代码) | 预计阅读 9 分钟
· · ·
打开交易软件,把一只票近三个月的日K拉出来,现在算高算低,看一眼心里就有数了。这一眼确实有用。
但如果你想把这份位置感用起来,很快会碰到三个坎。
第一,天数数不出来。图上那条线在某个区间来回晃了多少天,肉眼只能给个大概,给不出准数。
第二,说不出数字。你没法在筛选条件里写「位置偏高一点」,程序听不懂。位置感要能写进代码,先得变成一个数。
第三,没法批量。盯一只票可以看图,可要是想扫一遍自选股,甚至全市场几千只,总不能一张图一张图翻过去。
这三个坎,用同一个笨办法一起迈过去。周末我写了个小脚本,把三只熟悉的票的收盘价重新数了一遍,方法简单到不好意思写,数出来的东西却能直接接进量化系统。这篇把数法和结果一起交出来。
二、63 天收盘价,重新数一遍
三只票大家熟,宁德时代、贵州茅台、中际旭创。取 2026 年 6 月 24 日到 9 月 18 日,63 个交易日的日收盘价,前复权(把分红除权造成的价格断层抹平,三个月前的价格和今天才可比),数据走新浪财经的日线接口。

数法只有三步。第一步算统计量,均值、中位数、最高最低。第二步把三个月的价格范围切成五个等宽的段,数每天收盘价落在哪一段,算占比。第三步画直方图,均值和中位数各画一条竖线。
没有参数要调,全程就是计数,pandas 十几行代码的事。下面三张分布图,一只票一个形状。
三、方法一句话,把时间轴扔掉
K线回答的问题是价格什么时候走到这里。直方图把时间轴直接扔掉,只问另一件事,这 63 天里,收盘价落在每一段的天数各有多少。
把 63 个收盘价想成 63 个包裹,按楼层分堆。哪一层堆得最多,市场就在那一层反复停留,买家卖家在那里达成过大量共识。哪一层基本是空的,价格路过时就没打算停。
高段是市场反复住过的楼层,价格一次次回去又被接住。空段是快速通过的走廊。两坨密集区中间夹着一段空白,多半是价格从旧区间搬进新区间留下的脚印。
所有结论都来自这只票自己最近 63 天的成交记录,没有任何拟合参数。
四、茅台,一条空走廊
先看茅台的五段表。
| 价格区间(元) | 天数 | 占比 |
|---|---|---|
| 1168 – 1207 | 13 | 20.63% |
| 1207 – 1246 | 2 | 3.17% |
| 1246 – 1285 | 10 | 15.87% |
| 1285 – 1323 | 27 | 42.86% |
| 1323 – 1362 | 11 | 17.46% |
最扎眼的是第二行。1207 到 1246 这 39 块的走廊,63 天只停过 2 天,两侧却一边堆着 13 天,一边堆着 10 天。价格两次穿过走廊,都没停。

均值 1277.68,中位数 1293.09,差了 15 块。差值朝下,说明分布被左侧的低价日拖了尾巴,超过一半的日子其实停在更高的位置。
再看 1285 到 1323 那一段,27 天,占 42.86%。茅台这个季度将近一半的时间就待在这 39 块里。9 月 18 日收盘 1257.12,恰好落回那条空走廊。走廊目前是空的,市场接下来要决定的是把它当成路过的一层,还是重新住下来。
五、宁德,密集区悬在头顶
| 价格区间(元) | 天数 | 占比 |
|---|---|---|
| 302 – 322 | 4 | 6.35% |
| 322 – 343 | 5 | 7.94% |
| 343 – 363 | 10 | 15.87% |
| 363 – 383 | 18 | 28.57% |
| 383 – 404 | 26 | 41.27% |
形状和茅台相反。最上面两段加起来 44 天,占 69.84%,这只票三季度大部分时间在 363 到 404 之间活动,重心一路向上。

然后是最近的现实。9 月 18 日收盘 301.95,正好是这 63 天的最低价,两个月里价格把整个密集区从头穿到了脚。
这正是直方图最诚实的地方。363 到 404 的每一段,都堆着大量成交过的日子,市场在那几层楼反复住过。现在价格站在楼底往上看,那些楼层会不会变成上行的阻力,直方图不回答,它只把楼层数清楚,剩下的交给市场。
六、旭创,重心压在楼底
| 价格区间(元) | 天数 | 占比 |
|---|---|---|
| 812 – 915 | 26 | 41.27% |
| 915 – 1017 | 14 | 22.22% |
| 1017 – 1119 | 10 | 15.87% |
| 1119 – 1221 | 8 | 12.70% |
| 1221 – 1323 | 5 | 7.94% |
一根标准的下行楼梯,逐级递减,一段空白都没有。41.27% 的日子挤在最低一段,冲得越高,停留的天数越少。标准差 136.68(衡量波动的剧烈程度),是宁德 25.41 的五倍多,这三个月三只票里它最闹腾。

均值 992.65,中位数 943.00,这次反了过来,均值高出 50 块。少数冲高的日子把均值拽上去,大多数日子其实活在低位。
9 月 18 日收 926.43,又回到最低密集区的上沿。楼梯形状的含义很直接,市场每次向上冲都没能停住,上面的稀疏区成了一道接一道的考题。
七、三种形状,对照着看
| 形状 | 样本 | 读法 |
|---|---|---|
| 空白走廊 | 茅台 1207 到 1246 只停 2 天 | 价格搬家的脚印,旧区和新区各自成立 |
| 重心在顶 | 宁德上两段占 69.84% | 头顶全是住过人的楼层 |
| 下行楼梯 | 旭创逐级递减 | 越往上越站不住 |
形状比单个数字有信息量。均值和中位数的差告诉你分布朝哪边歪,空白段告诉你价格从哪搬来,密集段告诉你市场在哪实打实驻扎过。
八、它不灵的地方
这方法也有边界。
它只看收盘价,盘中打出的高低点一律不算,影线里的故事被整个扔掉了。
切段的方式是人为定的,五段是惯例,切成八段数字会跟着变,茅台那条走廊也未必永远空着。
它滞后。63 天的窗口,价格搬完家,分布要好几个星期才慢慢追上。
最重要的一条,它不猜方向。空走廊可以变成新驻扎地,也可能只是路过。直方图提供的是位置感,方向是另一回事。指标同样不猜方向,区别在于直方图把假设压缩到了最少,没有信号线要解释,只有数出来的天数。
九、把位置感变成一个数字,接进你自己的系统
形状能看懂,还差最后一步,让它变成程序能用的数。
我常用的是一个叫位置分的指标,定义很简单,过去 63 天里,收盘价低于今天的天数占比。宁德的位置分是 0.0%,63 天里没有一天收得比 301.95 更低,它正踩在自家三个月的地板上。茅台 27.0%,位置偏低。旭创 47.6%,不上不下。
这个数的好处是能接进流程。写成一个函数,挂到每日收盘后的扫描脚本里,几千只票几分钟跑完,位置分低于 10% 的自动进候选清单,再逐只看图做判断。看图这一步没人省得掉,省下来的是翻图的功夫。
它当然只是个过滤器。位置分低只说明价格踩在自家地板上,地板会不会继续塌,它不回答。别让任何一个单一数字替你做决定。
十、你自己跑一遍
取数一行接口调用。
① 取数,新浪日线前复权
import akshare as ak
import pandas as pd
df = ak.stock_zh_a_daily(symbol="sh600519", adjust="qfq")
df["date"] = pd.to_datetime(df["date"])
close = df[["date", "close"]].dropna().tail(63)["close"]统计量加五段表,靠的就是 pd.cut 这一行,作用是把连续的价格切成一段一段。
② 统计量加五段表
stats = {
"均价": round(close.mean(), 2),
"中位数": round(close.median(), 2),
"最低": round(close.min(), 2),
"最高": round(close.max(), 2),
}
bins = pd.cut(close, bins=5) # 价格范围切成等宽五段
days = close.groupby(bins, observed=False).count()
print((days / len(close) * 100).round(2))位置分一行就够。
③ 位置分
latest = close.iloc[-1]
pos = (close < latest).mean() # 收得比今天低的天数占比
print("位置分", round(pos * 100, 1))直方图加两条竖线,一眼分清均值和中位数谁高谁低。
④ 直方图加均值中位线
import matplotlib.pyplot as plt
plt.hist(close, bins=20, color="#0984e3", edgecolor="black", alpha=0.65)
plt.axvline(close.mean(), color="red", linestyle="dashed", label="均值")
plt.axvline(close.median(), color="darkorange", label="中位数")
plt.legend()
plt.show()以上数法装上就能用,往下是可直接运行的完整脚本
把 SYMBOL 换成任何一只 A 股,其余不用动。
⑤ 完整脚本
# 价格分布直方图 + 位置分,换 SYMBOL 即可复用
import akshare as ak
import matplotlib.pyplot as plt
import pandas as pd
SYMBOL = "sh600519" # 任意A股,6开头加sh,0或3开头加sz
DAYS = 63 # 一个季度的交易日
df = ak.stock_zh_a_daily(symbol=SYMBOL, adjust="qfq")
df["date"] = pd.to_datetime(df["date"])
close = df[["date", "close"]].dropna().tail(DAYS)["close"]
print("均价", round(close.mean(), 2), "中位数", round(close.median(), 2))
print("最低", round(close.min(), 2), "最高", round(close.max(), 2))
bins = pd.cut(close, bins=5)
days = close.groupby(bins, observed=False).count()
for rng, n in days.items():
print(f"{rng.left:.2f} - {rng.right:.2f} {n}天 {n / len(close) * 100:.2f}%")
latest = close.iloc[-1]
pos = (close < latest).mean() # 位置分,收得比今天低的天数占比
print("位置分", round(pos * 100, 1))
plt.hist(close, bins=20, color="#0984e3", edgecolor="black", alpha=0.65)
plt.axvline(close.mean(), color="red", linestyle="dashed", label=f"均值 {close.mean():.2f}")
plt.axvline(close.median(), color="darkorange", label=f"中位数 {close.median():.2f}")
plt.legend()
plt.title(f"{SYMBOL} 收盘价分布(近{DAYS}个交易日)")
plt.show()翻出你拿得最久的那只票,算一下位置分。过去三个月里,有多少天的收盘价比今天低?评论区报个数。
觉得有用的话,把这篇转给同样在搞量化的朋友。
#量化工具 #Python量化 #pandas #价格分布 #直方图 #技术分析 #A股复盘 #宁德时代 #贵州茅台 #中际旭创 #数据分析 #散户工具箱
Be First to Comment