“万丈高楼平地起,不管你是初学缠论还是已经有几年盘感,只要你想把交易系统数字化、结构化,那这篇文章你一定要认真看完。
先别急着去学那些花里胡哨的AI选股、量化策略优化,这里讲的是最朴素、最接地气,也是最关键的一步:怎么让程序自动识别并画出缠论线段?
在众多缠论研究者的理论基础之上,结合缠中说禅老师的原始思想,以及摩尔缠论、本心缠论等优秀教学体系的实践精华,本文尝试通过Python程序构建一套可自动识别并绘制缠论线段的实操方案,力求从“人工主观”走向“逻辑客观”。致敬所有为缠论传播与发展付出心血的先行者。
一、为什么要自动画线?
如果你手动画过缠论线段,就知道这活儿有多费眼神、多看感觉。错一个点、漏一笔,后面整个走势判断就全打乱。更关键的是,人画线是主观的,程序画线才能统一逻辑、跑回测、走实盘。
想做自动化策略?想复盘千只个股?那你第一步必须把“线段”这件事搞明白,而且要交给代码。
这篇文章就围绕一个目标展开:如何用Python让程序自动找到缠论的线段?
二、数据是地基:从哪抓K线?
搞程序的人都知道,数据是第一步。没有K线数据,一切都是空谈。我们选了一个大家都能用的免费数据源——东方财富。
虽然它网页抓取有限制(验证码之类),但少量数据足够做自选股分析。
👇下面这段代码,就是用来从东方财富抓K线数据的(注意,它是复权后的数据):
def get_es_qfq(code,klt,begin,end):
timespan = int(round(time.time() * 1000))
cb = "jsonp"+str(timespan)
stock = code[0:6]
shsz = code[-2:]
if shsz=='SZ': stock = '0.'+str(code[0:6])
if shsz=='SH': stock = '1.'+str(code[0:6])
if shsz=='BJ': stock = '1.'+str(code[0:6])
url = 'https://push2his.eastmoney.com/api/qt/stock/kline/get?' + \
'fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&' + \
'fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&' + \
'beg='+str(begin)+'&end='+str(end)+'&ut=fa5fd1943c7b386f172d6893dbfba10b&' + \
'rtntype=6&secid='+stock+'&klt='+str(klt)+'&fqt=1&cb='+cb
res = requests.get(url)
data = json.loads(res.text.replace(cb,''
)[1:-2])
...
我们再封装一下,把不同周期(日K、周K、30分钟、5分钟等)都能一键抓取保存:
def get_stock_list_qfq(code,begin,end='20501231'):
klts = [5,30,101] # 5分钟、30分钟、日线
for klt in klts:
file_name_road = './csv_hq_data/...'
...
到这一步,你已经有了结构清晰的K线数据文件夹:日线、周线、30分钟线……未来分析就靠它。
保存到对应文件夹下:
三、用均线划线?这套路靠谱吗?
有人可能会问:缠论讲究“笔”和“线段”,为啥我们用的是MA5和MA34的交叉点来辅助画线?
原因很简单——程序识别的逻辑要稳定、要明确,而MA交叉是一种清晰、连续、数学可表达的结构。
我们设定一个基本逻辑:
- 每条线段里必须包含一个 MA5 和 MA34 的交叉点;
那么我们就先找交叉点,再往前回溯那个低点或高点作为线段端点。
👇下面的代码就是找交叉点的:
def get_ma_cross_points(stock_k_df, ma5_name, ma34_name):
gold = stock_k_df[(stock_k_df[ma5_name] > stock_k_df[ma34_name]) &
(stock_k_df[ma5_name].shift(1) < stock_k_df[ma34_name].shift(1))]
gold['cross_type'] = 'gold'
dead = stock_k_df[(stock_k_df[ma5_name] < stock_k_df[ma34_name]) &
(stock_k_df[ma5_name].shift(1) > stock_k_df[ma34_name].shift(1))]
dead['cross_type'] = 'dead'
cross = gold.append(dead).sort_values(by='date')
return cross
接着找这些交叉点前的极值点:
def
get_ma_cross_points_min_max(stock_k_df, ma5_ma34_cross_points):
list_points = []
i0 = 0
for i, r in ma5_ma34_cross_points.iterrows():
if r['cross_type'] == 'gold':
i1 = stock_k_df.loc[i0:i, 'low'].idxmin()
else:
i1 = stock_k_df.loc[i0:i, 'high'].idxmax()
list_points.append(i1)
i0 = i
return list_points
这样我们就有了一串点,把它们连起来,线段雏形就出来了。
四、连接这些点,线段就有了“性格”
光有端点还不够,线段是要有“方向”的,是向上还是向下。
所以我们继续写个函数,把这些点按顺序连起来,并识别方向:
def get_line_segments(stock_k_df, list_high_low_points):
line_segments = []
for i in range(len(list_high_low_points) - 1):
...
updown = 'up'if stock_k_df['close'][end] > stock_k_df['close'][begin] else'down'
line_segment = {
'updown': updown,
'begin': begin,
'end': end,
'begin_date': stock_k_df['date'][begin],
'end_date': stock_k_df['date'][end]
}
line_segments.append(line_segment)
return line_segments
这一步跑完,你就可以输出一个文件,把所有的线段都保存下来,未来做图、跑分析、找买卖点都可以用。
五、画出来看看,程序到底画得怎么样?
我们用 echarts 画个图,看一眼效果。程序已经能把这些线段自动连好,并标记上升或下降趋势:
📉 图示:每一段线,都是由金叉/死叉前的极值点决定的。
当然现在画的线段还比较粗略,还没考虑中枢、笔数量、走势力度这些进阶因素。
但没关系,这只是第一步。
六、下一步要干嘛?
我们接下来准备加几个关键优化:
- 加入中枢识别、趋势力度过滤,让线段更贴合缠论本义;
- 最终目标:让整个缠论结构(笔、中枢、趋势)自动生成 + 可视化。
最后一句话
很多人学缠论学了很多年,还是停留在主观判断阶段。其实只要你迈出这一步,让程序动起来,才是真的进到“体系化”阶段。
记住:缠论不是画图的艺术,是结构的科学。
这套思路+代码会持续更新,如果你觉得有价值,就点个“在看”支持一下,下次我继续讲如何用这些线段识别真正的买卖点,我们一起把“缠论程序化”这件事做深、做真!