干货丨如何用时序数据库寻找相似的历史k线

有网友提问应该用什么样的数据库/数据结构/算法来计算某支股票的相似K线? 具体的问题描述是,假设给出某股某段行情K线(单位/日),从任何其他股票历史中匹配出与之最为相似的某段历史K线,并给出相似度值(单位/%),并以此排序,获取最为相似的N个结果。

我们可以使用k线的距离以及股票日回报的相关性来衡量k线相似度,使用Tushare提供的沪深股票2008年到2017年的日线行情数据来做实验。如何把Tushare数据导入到 DolphinDB database 可以参考教程如何使用DolphinDB处理Tushare金融数据

Tushare提供的沪深股票日线行情数据包含以下字段:

名称            描述
ts_code            股票代码
trade_date    交易日期
open            开盘价
high            最高价
low            最低价
close            收盘价
pre_close    昨收价
change            涨跌额
pct_change    涨跌幅
vol            成交量(手)
amount            成交额(千元)

下面将以漫步者(股票代码为002351.SZ)为例,介绍如何在历史数据中,找出与漫步者2016年9月1日到2016年9月30日最为相似的10段历史k线。

首先,把漫步者2016年9月1日到2016年9月30日的日线行情数据加载到内存。

code="002351.SZ"//漫步者
edifier=select * from loadTable("dfs://daily_line","hushen_daily_line") where ts_code=code,date(trade_date) between 2016.09.01:2016.09.30

把股票数据加载到内存中。

num=exec count(*) from edifier
stock=select * from loadTable("dfs://daily_line","hushen_daily_line")

1.使用k线的距离衡量相似度

两段k线之间的距离可以用股票日回报的差的平方和来计算。距离越小表示k线的相似度越高。

def square_sum(x,y):sum2(x-y)
corrTable1=select ts_code,move(date(trade_date),num-1)as beginDate,date(trade_date) as endDate,moving(square_sum{edifier.pct_change},pct_change,num) as distance from stock context by ts_code

上面代码使用的moving是DolphinDB的模板函数,表示在大小为num,边界为beginDate和endDate的滚动窗口中计算两段k线之间的距离。square_sum{edifier.pct_change}是DolphinDB中的部分应用,用于固定函数的部分参数。

找出与漫步者2016年9月1日到2016年9月30日最为相似的10段历史k线。

mostCorrelated1=select * from corrTable1 where isValid(distance),rank(distance,true) between 0:10 order by distance
ts_code            beginDate    endDate            distance
300073.SZ    2016.08.02    2016.08.29    67.024
600995.SH    2017.07.06    2017.08.02    70.8713
600549.SH    2010.12.17    2011.01.14    73.514
600627.SH    2008.07.07    2008.08.07    73.59
600367.SH    2010.12.17    2011.01.14    76.447
600867.SH    2011.07.28    2011.08.24    76.5449
002253.SZ    2010.05.21    2010.06.22    79.2845
002382.SZ    2015.01.06    2015.02.02    79.5101
300266.SZ    2014.07.07    2014.09.17    80.1772
600706.SH    2017.06.05    2017.07.14    80.5079

定义一个函数getReturn,取出相似股票在beginDate和endDate之间的日回报。

def getReturn(t, row): exec pct_change/100 from t where ts_code= row.ts_code, date(trade_date) between row.beginDate : row.endDate

把每只相似股票的日回报数据保存到同一个回报矩阵中,每列表示一只股票在相应时间段中的日回报,并使用图表展示。

retMatrix1 = each(getReturn{stock}, mostCorrelated1).rename!(mostCorrelated1.ts_code)
plot(retMatrix1,,"使用最短k线距离找出相似历史k线") 

上面的代码通过each模板函数取出最相似的10只股票的日回报,并以股票代码来命名每一列。

使用最短k线距离计算出来的股票包含当升科技(30073.SZ)、文山电力(600995.SH)、厦门钨业(600549.SH)、上电股份(600627.SH)、红星发展(600367.SH)、通化东宝(600867.SH)、川大智胜(002253.SZ)、蓝帆医疗(002382.SZ)、兴源环境(300266.SZ)和曲江文旅(600706.SH)。

2.使用股票日回报相关性衡量相似度

股票日回报的相关性是衡量k线相似度很好的指标。

corrTable2=select ts_code,move(date(trade_date),num-1)as beginDate,date(trade_date) as endDate,moving(corr{edifier.pct_change},pct_change,num) as corr from stock context by ts_code

找出与漫步者2016年9月1日到2016年9月30日最为相似的10段历史k线。

mostCorrelated2=select * from corrTable2 where rank(corr,false) between 0:10 order by corr desc
ts_code            beginDate    endDate            corr
600367.SH    2010.12.17    2011.01.14    0.8824
600549.SH    2010.12.17    2011.01.14    0.8806
300073.SZ    2016.08.02    2016.08.29    0.8749
002294.SZ    2014.02.26    2014.03.25    0.8729
600995.SH    2017.07.06    2017.08.02    0.8723
600486.SH    2010.12.17    2011.01.14    0.8721
002382.SZ    2015.01.06    2015.02.02    0.8718
002253.SZ    2010.05.21    2010.06.22    0.8708
000939.SZ    2008.03.21    2008.04.18    0.8706
600627.SH    2008.07.07    2008.08.07    0.8692

同样地,把相似股票的日回报数据保存到回报矩阵中。

retMatrix2 = each(getReturn{stock}, mostCorrelated2).rename!(mostCorrelated2.ts_code)
plot(retMatrix,,"使用股票日回报相关性找出相似历史k线") 

使用股票日回报相关性计算出来的股票包含红星发展(600367.SH)、厦门钨业(600549.SH)、当升科技(300073.SZ)、信立泰(002294.SZ)、文山电力(600995.SH)、扬农化工(600486.SH)、蓝帆医疗(002382.SZ)、川大智胜(002253.SZ)、凯迪生态(000939.SZ)和上电股份(600627.SH)。

3.性能分析

我们使用的是沪深股票2008年到2017年的日线行情数据,共530万的数据。使用第一种方法仅需7秒,使用第二种方法仅需3秒,性能极佳。


恭喜你发现了宝藏~

898 声望
245 粉丝
0 条评论
推荐阅读
DolphinDB定时作业教程
DolphinDB提供的定时作业(scheduled job)功能,可以让系统在指定的时间以指定的频率自动执行作业。当我们需要数据库定时自动执行一些脚本进行计算分析(譬如每日休市后分钟级的K线计算、每月统计报表生成)、数...

DolphinDB2阅读 1.6k

终于卷完了!Redis 打怪升级进阶成神之路(2023 最新版)!
是一种非关系型数据库服务,它能解决常规数据库的并发能力,比如传统的数据库的IO与性能的瓶颈,同样它是关系型数据库的一个补充,有着比较好的高效率与高性能。专注于key-value查询的redis、memcached、ttserver。

民工哥10阅读 810

封面图
硬卷完了!MongoDB 打怪升级进阶成神之路( 2023 最新版 )!
前面我们学习:MySQL 打怪升级进阶成神之路、Redis 打怪升级进阶成神之路,然后我们还在继续 NoSQL 的卷王之路。从第一篇文章开始,我们逐步详细介绍了 MogoDB 基础概念、安装和最基本的CURD操作、索引和聚合、工...

民工哥6阅读 450

封面图
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
又一款内存数据库横空出世,比 Redis 更强,性能直接飙升一倍!杀疯了
KeyDB是Redis的高性能分支,专注于多线程,内存效率和高吞吐量。除了多线程之外,KeyDB还具有仅在Redis Enterprise中可用的功能,例如Active Replication,FLASH存储支持以及一些根本不可用的功能,例如直接备份...

民工哥4阅读 1.7k评论 2

封面图
面试官:请说一下如何优化结构体的性能?
使用内存对齐机制优化结构体性能,妙啊!前言之前分享过2篇结构体文章:10秒改struct性能直接提升15%,产品姐姐都夸我好棒 和 Go语言空结构体这3种妙用,你知道吗? 得到了大家的好评。这篇继续分享进阶内容:结...

王中阳Go4阅读 3.8k评论 2

封面图
MySQL百万数据深度分页优化思路分析
一般在项目开发中会有很多的统计数据需要进行上报分析,一般在分析过后会在后台展示出来给运营和产品进行分页查看,最常见的一种就是根据日期进行筛选。这种统计数据随着时间的推移数据量会慢慢的变大,达到百万...

一个程序员的成长7阅读 893

封面图

恭喜你发现了宝藏~

898 声望
245 粉丝
宣传栏