Python实现基于动态时间规整的股市交易策略测试

  • 一、策略简介
  • 二、策略原理
  • 三、代码实现
  • 四、测试策略
  • 五、完整代码

一、策略简介

该项目采用Python语言,利用动态时间规整算法对沪深300市场构建一种交易策略,并采用夏普比率来对该策略模拟交易的结果进行评估。

本项目只是对交易策略的初探,不涉及投资组合、风险缓释和资金管理等等,也不被视为任何类型的投资建议!欢迎相关专业人士指教。

二、策略原理

动态时间规整是一种衡量两段时间序列的相似度的算法,具体运算细节这里不多赘述。

我们将过去一段时间的沪深300每日涨跌率(当天收盘价与前一天收盘价相比)按照特定天数分成若干个时间序列,并设置持有时间。

为描述方便,商定:在时间序列结尾买入,过了持有时间后卖出,算作一次完整“交易”。

该策略会将正在被测试的时期与过去的若干已知时间序列进行动态时间规整并找到相似度高的时间序列,若这些时间序列的“交易”得到了正收益,我们就期望在现时期进行一次“交易”。

三、代码实现

使用到的库:

import pandas as pd
import matplotlib.pyplot as pltfrom fastdtw import fastdtw
from scipy.spatial.distance import euclidean
import numpy as np
import math

pandas和numpy帮助我们进行数据处理,plt用来画图,fastdtw用来进行动态时间规整。

spy = pd.read_csv('300.csv')
spy = spy.set_index(['Date'])
spy_c = spy['Close']

读取沪深300从2005年到2021年的历史数据,并取出收盘价数据。可以画个图看一下:

分别设置三个参量:时间序列的长度,持有天数,判定相似度高的阈值。

tlen = 5
hold = 7
thre = 5

计算每日涨跌率并按照tlen分成若干时间序列,并计算每个时间序列对应的一次完整“交易”的回报。将两者放入tseries中:

tseries = []
for i in range(tlen,len(spy_c)-hold-1,tlen):pctc = spy_c.iloc[i-tlen:i].pct_change()[1:].values*100res = (spy_c[i+hold+1] - spy_c[i])/spy_c[i] * 100tseries.append((pctc,res))

对每个序列都与其他序列依次计算相似度,并保存两个序列的“交易”回报。dist越低代表相似度越高。
然后清理掉以下情况的数据:

  1. 相似度为0,即相同的两个序列。
  2. 两个序列太近,中间还没超过一个完整的持有周期。
  3. 距离超过阈值,即相似度过低的两个序列。
  4. 第一个序列的“交易”回报为负。
def dtw_dist(x, y):distance, path = fastdtw(x, y, dist=euclidean)return distancedist_pairs = []
for i in range(len(tseries)):for j in range(len(tseries)):dist = dtw_dist(tseries[i][0],tseries[j][0])dist_pairs.append((i,j,dist,tseries[i][1],tseries[j][1]))dist_frame = pd.DataFrame(dist_pairs,columns=['A','B','Dist','A Ret','B Ret'])
sf = dist_frame[dist_frame['Dist']>0].sort_values(['A','B']).reset_index(drop=1)
sfe = sf[sf['A']+math.ceil(float(tlen+hold)/tlen) <= sf['B']]
winf = sfe[(sfe['Dist']<=thre)&(sfe['A Ret']>0)]

四、测试策略

为评估我们的测试结果,我们定义一个评估函数:

def get_stats(s,n=252):cnt = len(s)wins = len(s[s>0])losses = len(s[s<0])mean_trd = round(s.mean(),3)sd = round(np.std(s),3)sharpe_r = round((s.mean()/np.std(s))*np.sqrt(n),4)print 'Trades:',cnt,\'\nWins:',wins,\'\nLosses:',losses,\'\nMean:',mean_trd,\'\nStd Dev:',sd,\'\nSharpe Ratio:',sharpe_r

输入该策略的所有模拟交易回报序列,返回交易次数、盈利次数、亏损次数、平均收益率、回报标准差、修正后的夏普比率。

为方便对该策略的结果有个直观的比较,我们取一个新的策略——固定每天以开盘价买入,以收盘价卖出,作为我们的基准线

>>> id_rtn = ((spy['Close'] - spy['Open'])/spy['Open'])*100
>>> get_stats(id_rtn)
Trades: 3920
Wins: 2121
Losses: 1799
Mean: 0.127
Std Dev: 1.555
Sharpe Ratio: 1.3008

现在进行我们的策略的评估。
对于相似的有正盈利的历史序列,我们会进行交易。如果发生了亏损的情况我们就删除相应历史序列。

excluded = {}
return_list = []
def get_returns(r):if excluded.get(r['A']) is None:return_list.append(r['B Ret'])if r['B Ret']<0:excluded.update({r['A']:1})winf.apply(get_returns,axis=1)

看看我们的策略的评估结果:

>>> get_stats(pd.Series(return_list))
>Trades: 1180
Wins: 753
Losses: 427
Mean: 1.665
Std Dev: 4.913
Sharpe Ratio: 5.3795

可以看到相比基准策略有了更高的夏普比率。

五、完整代码

import pandas as pd
import matplotlib.pyplot as pltfrom fastdtw import fastdtw
from scipy.spatial.distance import euclidean
import numpy as np
import mathdef dtw_dist(x, y):distance, path = fastdtw(x, y, dist=euclidean)return distancedef get_stats(s,n=252):cnt = len(s)wins = len(s[s>0])losses = len(s[s<0])mean_trd = round(s.mean(),3)sd = round(np.std(s),3)sharpe_r = round((s.mean()/np.std(s))*np.sqrt(n),4)print 'Trades:',cnt,\'\nWins:',wins,\'\nLosses:',losses,\'\nMean:',mean_trd,\'\nStd Dev:',sd,\'\nSharpe Ratio:',sharpe_rspy = pd.read_csv('300.csv')
spy = spy.set_index(['Date'])
#spy = spy.sort_values(['Date'])spy_c = spy['Close']tlen = 5
hold = 7
thre = 5tseries = []
for i in range(tlen,len(spy_c)-hold-1,tlen):pctc = spy_c.iloc[i-tlen:i].pct_change()[1:].values*100res = (spy_c[i+hold+1] - spy_c[i])/spy_c[i] * 100tseries.append((pctc,res))dist_pairs = []
for i in range(len(tseries)):for j in range(len(tseries)):dist = dtw_dist(tseries[i][0],tseries[j][0])dist_pairs.append((i,j,dist,tseries[i][1],tseries[j][1]))dist_frame = pd.DataFrame(dist_pairs,columns=['A','B','Dist','A Ret','B Ret'])
sf = dist_frame[dist_frame['Dist']>0].sort_values(['A','B']).reset_index(drop=1)
sfe = sf[sf['A']+math.ceil(float(tlen+hold)/tlen) <= sf['B']]
winf = sfe[(sfe['Dist']<=thre)&(sfe['A Ret']>0)]excluded = {}
return_list = []
def get_returns(r):if excluded.get(r['A']) is None:return_list.append(r['B Ret'])if r['B Ret']<0:excluded.update({r['A']:1})winf.apply(get_returns,axis=1)
get_stats(pd.Series(return_list))

Python实现基于动态时间规整的股市交易策略测试相关推荐

  1. Python语音基础操作--10.1基于动态时间规整(DTW)的孤立字语音识别试验

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  2. 基于动态时间规整算法(DTW)的语音识别技术研究-含Matlab代码

    ⭕⭕ 目 录 ⭕⭕ ⏩ 一.引言 ⏩ 二.动态时间规整算法基本原理 ⏩ 三.语音识别实例分析 ⏩ 四.参考文献 ⏩ 五.Matlab代码获取 ⏩ 一.引言 在语音识别技术的发展过程中,动态时间规整算法 ...

  3. 基于动态时间规整(DTW)的孤立字语音识别

    模板匹配法语音识别系统 用户将词汇表中每个词依次说一遍,并且将其特征矢量时序作为模板存入模板库,在识别阶段,将输入语音的特征矢量时间序列依次与模板库中每个模板进行相识度比较,将相识度最高者作为识别的结 ...

  4. 【语音识别】基于动态时间规整(DTW)的孤立字语音识别Matlab源码

    1 模型 2 部分代码 function trimmed_X = my_vad(x) %端点检测:输入为录入语音,输出为有用信号Ini = 0.1; %初始静默时间 Ts = 0.01; %窗的时长 ...

  5. 【语音识别】基于matlab GUI动态时间规整算法(RTW)语音识别系统【含Matlab源码 341期】

    ⛄一.动态时间规整算法(RTW)语音识别 软件算法主要分为语音信号滤波去噪.预加重.分帧.端点检测.特征参数提取.模式匹配.算法的关键点和难点是特征参数提取和模式匹配.孤立词的语音识别应用程序也是基于 ...

  6. 【语音识别】动态时间规整算法(RTW)语音识别系统【含GUI Matlab源码 341期】

    ⛄一.动态时间规整算法(RTW)语音识别 软件算法主要分为语音信号滤波去噪.预加重.分帧.端点检测.特征参数提取.模式匹配.算法的关键点和难点是特征参数提取和模式匹配.孤立词的语音识别应用程序也是基于 ...

  7. 【时序】动态时间规整(DTW)算法原理及Python实现

    DTW 简介 DTW 定义 动态时间规整(Dynamic Time Warping,DTW)用于比较具有不同长度的两个阵列或时间序列之间的相似性或距离. 假设要计算两个等长数组的距离: a = [1, ...

  8. 初识DTW(动态时间规整)算法及Python实现例

    目录 1. 概要 2. 时序列相似度度量 3. DTW基本算法 4. Python实现 5. Next Action 1. 概要 DTW( Dynamic Time Warping,动态时间规整)是基 ...

  9. 动态时间规整matlab和python代码

    几篇写得很好的文章 [重大修改]动态时间规整(Dynamic Time Warping) 算法笔记-DTW动态时间规整 动态时间规整算法(Dynamic Time Warping, DTW)之初探单词 ...

最新文章

  1. 【点云StatisticalOutlierFilter】python-pcl:去除离群点
  2. 第三周项目三-输出星号图(2)
  3. 20160522--20160526----mybatis入门基础
  4. 数据结构源码笔记(C语言):链接栈
  5. Web Socket 性能对比——Spring Boot vs Tomcat vs Netty
  6. 钉钉小程序数据传递——子传父,父传子
  7. 一切为了开放科学!Papers with Code新增CS、物理、数学、统计学等多个学科
  8. 分布式事务实践 解决数据一致性 分布式事务实现,模式和技术
  9. python列表截取双冒号“::“用法
  10. 未来金融科技宣布已完成mBTC系统和技术升级,消费者可用比特币进行在线支付
  11. 马云:用 10% 大脑创造出来的机器不可能毁灭人类
  12. php相差天数,php获取给定日期相差天数
  13. 未来教育题库 * **java二级第28套试题** *
  14. Docker 启动报错 Error starting daemon: SELinux is not supported with the overlay2 ...alse)
  15. 戴尔服务器物理关机,戴尔服务器的远程开机和关机
  16. 在javascript中重新加载/刷新页面的不同方法
  17. 中国唯一的图灵奖获得者姚期智,在清华开设的“姚班”有哪些 AI 名徒?
  18. 遇见--CondaHTTPError: HTTP 000 CONNECTION FAILED for url 怎么解决
  19. java安全架构____X.509原理
  20. mongoDB百度脑图总结

热门文章

  1. Twitter网页版推出通用搜索功能 复制链接
  2. 世界各国当日数据探索性分析
  3. ArrayList集合类实现的RandomAccess空接口有何用?
  4. 【python】pygame实现植物大战僵尸小游戏(附源码 有注释)
  5. 超好用的在线PDF转Word网站,真后悔没早发现
  6. 题目 1224: 整除的尾数
  7. python的continue用法_Python学习笔记之Break和Continue用法分析
  8. for(auto a :b)
  9. 高效解决阿里云远程桌面连接出现credssp加密oracle修正
  10. RISC-V入门必看