前几天写文章分享了《Python实现相似K线的5种方法》,好多粉丝就问能不能提供一套现成的可跑的代码,这不今天就来了!

目标 :从所有A股中,找出近期走势与"xxxx股票"在某段时间内K线走势最相似的前100只股票。 核心方法:提取技术指标特征 → 归一化 → 计算余弦相似度 → 排序输出
准备好需要Python库
库名 | 说明 |
---|---|
mplfinance |
用于画K线图 |
pandas |
常规数据处理 |
matplotlib |
图像绘制 |
xtquant |
基于迅投MiniQMT衍生出来的一套完善的Python策略运行框架 |
numpy |
数值计算 |
scikit-learn |
用于MinMaxScaler 和cosine_similarity |
ta-lib |
技术指标库,常用于量化策略 |
tqdm |
进度条 |
执行以下命令安装需要的库
bash
pip install mplfinance pandas matplotlib numpy scikit-learn tqdm
ta-lib
安装时大部分人会卡住,安装方法可以参考我之前写的文章,里面有详细安装教程: 《史上最强量化工具库 Ta-Lib 从入门到精通,一篇文章就够了!》
接下来是安装xtquant
,可以参考这篇文章:
《MiniQMT+Backtrader:平民股票量化界的"黄金搭档",永远的神!》
代码实现
1、提取K线特征
前面的文章介绍了5种,今天实现多维度特征融合(价格 + 量能 + 技术指标) 的方式查找相似K线。
原理: 只看价格走势太单一,我们可以融合多个维度,把每段K线变成"多维特征向量"后,再比较,不只要形似而要神似
首先提取K线的特征,这里用到了涨幅、量比、乖离率、RSI、MACD等指标,当然也可以根据你的需要换成其它指标。
python
# 特征提取
def extract_features(df,start_date='',end_date='',count = -1):
df = df.copy()
# 价格特征:涨跌幅(连续序列)
df['pct_change'] = df['close'].pct_change().fillna(0)
# 成交量比值(放量)
df['volume_ratio'] = df['volume'] / df['volume'].rolling(10).mean()
# 均线乖离率(bias)
df['bias'] = (df['close'] - df['close'].rolling(10).mean()) / df['close'].rolling(10).mean()
# RSI指标(相对强弱指数)
df['RSI'] = talib.RSI(df['close'], timeperiod=14)
# MACD指标
df['MACD'], df['MACD_signal'], df['MACD_hist'] = talib.MACD(df['close'], fastperiod=12, slowperiod=26, signalperiod=9)
# 截取要对比的时间段
if count==-1:
df = df[(df['date']>=start_date) & (df['date']<=end_date)]
else:
df = df.tail(count)
# 归一化:对于不同特征进行归一化处理,防止量纲不一致
scaler = MinMaxScaler()
features = ['pct_change', 'volume_ratio', 'bias', 'RSI', 'MACD', 'MACD_signal', 'MACD_hist']
df[features] = scaler.fit_transform(df[features])
return df[features].values # 返回归一化后的特征矩阵
2、计算2段K线相似度
提取到K线特征以后是一个(window × n_features)二维矩阵,我们需要的是两个时间序列整体特征矩阵之间的相似度(1个值),通过余弦计算相似度时需要把特征矩阵展平矩阵为1维向量
python
# 展平矩阵为1维向量
vec1 = features.flatten().reshape(1, -1)
vec2 = features_2.flatten().reshape(1, -1)
similarity = cosine_similarity(vec1, vec2)[0][0]
similarity
就是2段K线的相似度取值(0到1),值越大越相似 最后我们保留相似度最高的前N条记录即可。
3、绘图验证
计算完相似度以后,我们可以把2段K线绘制出来,肉眼看看他们是不是长得相似
python
def draw_k(df1, df2,title1 ,title2,save_path=None):
# 创建子图
# 设置 matplotlib 全局字体
plt.rcParams['font.family'] = 'simhei'
plt.rcParams['axes.unicode_minus'] = False
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10), sharex=False)
# 自定义样式
my_style = mpf.make_mpf_style(base_mpf_style='yahoo',
marketcolors=mpf.make_marketcolors(
up='red', # 涨:红色
down='green', # 跌:绿色
edge='inherit', # K线边框颜色(inherit 表示继承 up/down 颜色)
wick='inherit', # 上下影线颜色
volume='inherit' # 成交量颜色
))
# 绘制第一个K线图到 ax1
mpf.plot(df1, type='candle',style=my_style, ax=ax1, volume=False, show_nontrading=True)
ax1.set_title(title1)
# 绘制第二个K线图到 ax2
mpf.plot(df2, type='candle',style=my_style, ax=ax2, volume=False, show_nontrading=True)
ax2.set_title(title2)
# 布局紧凑
plt.tight_layout()
# 保存为PNG图片(如果提供了路径)
if save_path:
fig.savefig(save_path, dpi=300)
print(f"图片已保存至: {save_path}")
# 显示图像
plt.show()
